root/sound/soc/sof/intel/cnl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cnl_ipc_irq_thread
  2. cnl_ipc_host_done
  3. cnl_ipc_dsp_done
  4. cnl_ipc_send_msg
  5. cnl_ipc_dump

   1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
   2 //
   3 // This file is provided under a dual BSD/GPLv2 license.  When using or
   4 // redistributing this file, you may do so under either license.
   5 //
   6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
   7 //
   8 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
   9 //          Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
  10 //          Rander Wang <rander.wang@intel.com>
  11 //          Keyon Jie <yang.jie@linux.intel.com>
  12 //
  13 
  14 /*
  15  * Hardware interface for audio DSP on Cannonlake.
  16  */
  17 
  18 #include "../ops.h"
  19 #include "hda.h"
  20 
  21 static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
  22         {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
  23         {"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
  24         {"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
  25 };
  26 
  27 static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
  28 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
  29 
  30 static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
  31 {
  32         struct snd_sof_dev *sdev = context;
  33         u32 hipci;
  34         u32 hipcida;
  35         u32 hipctdr;
  36         u32 hipctdd;
  37         u32 msg;
  38         u32 msg_ext;
  39         bool ipc_irq = false;
  40 
  41         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
  42         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
  43         hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
  44         hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
  45 
  46         /* reply message from DSP */
  47         if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
  48                 msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK;
  49                 msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK;
  50 
  51                 dev_vdbg(sdev->dev,
  52                          "ipc: firmware response, msg:0x%x, msg_ext:0x%x\n",
  53                          msg, msg_ext);
  54 
  55                 /* mask Done interrupt */
  56                 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
  57                                         CNL_DSP_REG_HIPCCTL,
  58                                         CNL_DSP_REG_HIPCCTL_DONE, 0);
  59 
  60                 spin_lock_irq(&sdev->ipc_lock);
  61 
  62                 /* handle immediate reply from DSP core */
  63                 hda_dsp_ipc_get_reply(sdev);
  64                 snd_sof_ipc_reply(sdev, msg);
  65 
  66                 if (sdev->code_loading) {
  67                         sdev->code_loading = 0;
  68                         wake_up(&sdev->waitq);
  69                 }
  70 
  71                 cnl_ipc_dsp_done(sdev);
  72 
  73                 spin_unlock_irq(&sdev->ipc_lock);
  74 
  75                 ipc_irq = true;
  76         }
  77 
  78         /* new message from DSP */
  79         if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
  80                 msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
  81                 msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
  82 
  83                 dev_vdbg(sdev->dev,
  84                          "ipc: firmware initiated, msg:0x%x, msg_ext:0x%x\n",
  85                          msg, msg_ext);
  86 
  87                 /* handle messages from DSP */
  88                 if ((hipctdr & SOF_IPC_PANIC_MAGIC_MASK) ==
  89                    SOF_IPC_PANIC_MAGIC) {
  90                         snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext));
  91                 } else {
  92                         snd_sof_ipc_msgs_rx(sdev);
  93                 }
  94 
  95                 cnl_ipc_host_done(sdev);
  96 
  97                 ipc_irq = true;
  98         }
  99 
 100         if (!ipc_irq) {
 101                 /*
 102                  * This interrupt is not shared so no need to return IRQ_NONE.
 103                  */
 104                 dev_dbg_ratelimited(sdev->dev,
 105                                     "nothing to do in IPC IRQ thread\n");
 106         }
 107 
 108         /* re-enable IPC interrupt */
 109         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
 110                                 HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);
 111 
 112         return IRQ_HANDLED;
 113 }
 114 
 115 static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
 116 {
 117         /*
 118          * clear busy interrupt to tell dsp controller this
 119          * interrupt has been accepted, not trigger it again
 120          */
 121         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
 122                                        CNL_DSP_REG_HIPCTDR,
 123                                        CNL_DSP_REG_HIPCTDR_BUSY,
 124                                        CNL_DSP_REG_HIPCTDR_BUSY);
 125         /*
 126          * set done bit to ack dsp the msg has been
 127          * processed and send reply msg to dsp
 128          */
 129         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
 130                                        CNL_DSP_REG_HIPCTDA,
 131                                        CNL_DSP_REG_HIPCTDA_DONE,
 132                                        CNL_DSP_REG_HIPCTDA_DONE);
 133 }
 134 
 135 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
 136 {
 137         /*
 138          * set DONE bit - tell DSP we have received the reply msg
 139          * from DSP, and processed it, don't send more reply to host
 140          */
 141         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
 142                                        CNL_DSP_REG_HIPCIDA,
 143                                        CNL_DSP_REG_HIPCIDA_DONE,
 144                                        CNL_DSP_REG_HIPCIDA_DONE);
 145 
 146         /* unmask Done interrupt */
 147         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
 148                                 CNL_DSP_REG_HIPCCTL,
 149                                 CNL_DSP_REG_HIPCCTL_DONE,
 150                                 CNL_DSP_REG_HIPCCTL_DONE);
 151 }
 152 
 153 static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
 154                             struct snd_sof_ipc_msg *msg)
 155 {
 156         /* send the message */
 157         sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
 158                           msg->msg_size);
 159         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
 160                           CNL_DSP_REG_HIPCIDR_BUSY);
 161 
 162         return 0;
 163 }
 164 
 165 static void cnl_ipc_dump(struct snd_sof_dev *sdev)
 166 {
 167         u32 hipcctl;
 168         u32 hipcida;
 169         u32 hipctdr;
 170 
 171         hda_ipc_irq_dump(sdev);
 172 
 173         /* read IPC status */
 174         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
 175         hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
 176         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
 177 
 178         /* dump the IPC regs */
 179         /* TODO: parse the raw msg */
 180         dev_err(sdev->dev,
 181                 "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
 182                 hipcida, hipctdr, hipcctl);
 183 }
 184 
 185 /* cannonlake ops */
 186 const struct snd_sof_dsp_ops sof_cnl_ops = {
 187         /* probe and remove */
 188         .probe          = hda_dsp_probe,
 189         .remove         = hda_dsp_remove,
 190 
 191         /* Register IO */
 192         .write          = sof_io_write,
 193         .read           = sof_io_read,
 194         .write64        = sof_io_write64,
 195         .read64         = sof_io_read64,
 196 
 197         /* Block IO */
 198         .block_read     = sof_block_read,
 199         .block_write    = sof_block_write,
 200 
 201         /* doorbell */
 202         .irq_handler    = hda_dsp_ipc_irq_handler,
 203         .irq_thread     = cnl_ipc_irq_thread,
 204 
 205         /* ipc */
 206         .send_msg       = cnl_ipc_send_msg,
 207         .fw_ready       = sof_fw_ready,
 208         .get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset,
 209         .get_window_offset = hda_dsp_ipc_get_window_offset,
 210 
 211         .ipc_msg_data   = hda_ipc_msg_data,
 212         .ipc_pcm_params = hda_ipc_pcm_params,
 213 
 214         /* debug */
 215         .debug_map      = cnl_dsp_debugfs,
 216         .debug_map_count        = ARRAY_SIZE(cnl_dsp_debugfs),
 217         .dbg_dump       = hda_dsp_dump,
 218         .ipc_dump       = cnl_ipc_dump,
 219 
 220         /* stream callbacks */
 221         .pcm_open       = hda_dsp_pcm_open,
 222         .pcm_close      = hda_dsp_pcm_close,
 223         .pcm_hw_params  = hda_dsp_pcm_hw_params,
 224         .pcm_hw_free    = hda_dsp_stream_hw_free,
 225         .pcm_trigger    = hda_dsp_pcm_trigger,
 226         .pcm_pointer    = hda_dsp_pcm_pointer,
 227 
 228         /* firmware loading */
 229         .load_firmware = snd_sof_load_firmware_raw,
 230 
 231         /* pre/post fw run */
 232         .pre_fw_run = hda_dsp_pre_fw_run,
 233         .post_fw_run = hda_dsp_post_fw_run,
 234 
 235         /* dsp core power up/down */
 236         .core_power_up = hda_dsp_enable_core,
 237         .core_power_down = hda_dsp_core_reset_power_down,
 238 
 239         /* firmware run */
 240         .run = hda_dsp_cl_boot_firmware,
 241 
 242         /* trace callback */
 243         .trace_init = hda_dsp_trace_init,
 244         .trace_release = hda_dsp_trace_release,
 245         .trace_trigger = hda_dsp_trace_trigger,
 246 
 247         /* DAI drivers */
 248         .drv            = skl_dai,
 249         .num_drv        = SOF_SKL_NUM_DAIS,
 250 
 251         /* PM */
 252         .suspend                = hda_dsp_suspend,
 253         .resume                 = hda_dsp_resume,
 254         .runtime_suspend        = hda_dsp_runtime_suspend,
 255         .runtime_resume         = hda_dsp_runtime_resume,
 256         .runtime_idle           = hda_dsp_runtime_idle,
 257         .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
 258 };
 259 EXPORT_SYMBOL(sof_cnl_ops);
 260 
 261 const struct sof_intel_dsp_desc cnl_chip_info = {
 262         /* Cannonlake */
 263         .cores_num = 4,
 264         .init_core_mask = 1,
 265         .cores_mask = HDA_DSP_CORE_MASK(0) |
 266                                 HDA_DSP_CORE_MASK(1) |
 267                                 HDA_DSP_CORE_MASK(2) |
 268                                 HDA_DSP_CORE_MASK(3),
 269         .ipc_req = CNL_DSP_REG_HIPCIDR,
 270         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
 271         .ipc_ack = CNL_DSP_REG_HIPCIDA,
 272         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
 273         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
 274         .rom_init_timeout       = 300,
 275         .ssp_count = CNL_SSP_COUNT,
 276         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
 277 };
 278 EXPORT_SYMBOL(cnl_chip_info);
 279 
 280 const struct sof_intel_dsp_desc icl_chip_info = {
 281         /* Icelake */
 282         .cores_num = 4,
 283         .init_core_mask = 1,
 284         .cores_mask = HDA_DSP_CORE_MASK(0) |
 285                                 HDA_DSP_CORE_MASK(1) |
 286                                 HDA_DSP_CORE_MASK(2) |
 287                                 HDA_DSP_CORE_MASK(3),
 288         .ipc_req = CNL_DSP_REG_HIPCIDR,
 289         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
 290         .ipc_ack = CNL_DSP_REG_HIPCIDA,
 291         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
 292         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
 293         .rom_init_timeout       = 300,
 294         .ssp_count = ICL_SSP_COUNT,
 295         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
 296 };
 297 EXPORT_SYMBOL(icl_chip_info);
 298 
 299 const struct sof_intel_dsp_desc tgl_chip_info = {
 300         /* Tigerlake */
 301         .cores_num = 4,
 302         .init_core_mask = 1,
 303         .cores_mask = HDA_DSP_CORE_MASK(0),
 304         .ipc_req = CNL_DSP_REG_HIPCIDR,
 305         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
 306         .ipc_ack = CNL_DSP_REG_HIPCIDA,
 307         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
 308         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
 309         .rom_init_timeout       = 300,
 310         .ssp_count = ICL_SSP_COUNT,
 311         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
 312 };
 313 EXPORT_SYMBOL(tgl_chip_info);
 314 
 315 const struct sof_intel_dsp_desc ehl_chip_info = {
 316         /* Elkhartlake */
 317         .cores_num = 4,
 318         .init_core_mask = 1,
 319         .cores_mask = HDA_DSP_CORE_MASK(0),
 320         .ipc_req = CNL_DSP_REG_HIPCIDR,
 321         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
 322         .ipc_ack = CNL_DSP_REG_HIPCIDA,
 323         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
 324         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
 325         .rom_init_timeout       = 300,
 326         .ssp_count = ICL_SSP_COUNT,
 327         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
 328 };
 329 EXPORT_SYMBOL(ehl_chip_info);

/* [<][>][^][v][top][bottom][index][help] */