Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // This file is provided under a dual BSD/GPLv2 license.  When using or
0004 // redistributing this file, you may do so under either license.
0005 //
0006 // Copyright(c) 2018 Intel Corporation. All rights reserved.
0007 //
0008 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
0009 //      Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
0010 //      Rander Wang <rander.wang@intel.com>
0011 //          Keyon Jie <yang.jie@linux.intel.com>
0012 //
0013 
0014 /*
0015  * Hardware interface for audio DSP on Cannonlake.
0016  */
0017 
0018 #include <sound/sof/ext_manifest4.h>
0019 #include <sound/sof/ipc4/header.h>
0020 #include "../ipc4-priv.h"
0021 #include "../ops.h"
0022 #include "hda.h"
0023 #include "hda-ipc.h"
0024 #include "../sof-audio.h"
0025 
0026 static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
0027     {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
0028     {"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
0029     {"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
0030 };
0031 
0032 static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
0033 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
0034 
0035 irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
0036 {
0037     struct sof_ipc4_msg notification_data = {{ 0 }};
0038     struct snd_sof_dev *sdev = context;
0039     bool ipc_irq = false;
0040     u32 hipcida, hipctdr;
0041 
0042     hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0043     if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
0044         /* DSP received the message */
0045         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0046                     CNL_DSP_REG_HIPCCTL,
0047                     CNL_DSP_REG_HIPCCTL_DONE, 0);
0048         cnl_ipc_dsp_done(sdev);
0049 
0050         ipc_irq = true;
0051     }
0052 
0053     hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0054     if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
0055         /* Message from DSP (reply or notification) */
0056         u32 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
0057                            CNL_DSP_REG_HIPCTDD);
0058         u32 primary = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
0059         u32 extension = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
0060 
0061         if (primary & SOF_IPC4_MSG_DIR_MASK) {
0062             /* Reply received */
0063             if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
0064                 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
0065 
0066                 data->primary = primary;
0067                 data->extension = extension;
0068 
0069                 spin_lock_irq(&sdev->ipc_lock);
0070 
0071                 snd_sof_ipc_get_reply(sdev);
0072                 snd_sof_ipc_reply(sdev, data->primary);
0073 
0074                 spin_unlock_irq(&sdev->ipc_lock);
0075             } else {
0076                 dev_dbg_ratelimited(sdev->dev,
0077                             "IPC reply before FW_READY: %#x|%#x\n",
0078                             primary, extension);
0079             }
0080         } else {
0081             /* Notification received */
0082             notification_data.primary = primary;
0083             notification_data.extension = extension;
0084 
0085             sdev->ipc->msg.rx_data = &notification_data;
0086             snd_sof_ipc_msgs_rx(sdev);
0087             sdev->ipc->msg.rx_data = NULL;
0088         }
0089 
0090         /* Let DSP know that we have finished processing the message */
0091         cnl_ipc_host_done(sdev);
0092 
0093         ipc_irq = true;
0094     }
0095 
0096     if (!ipc_irq)
0097         /* This interrupt is not shared so no need to return IRQ_NONE. */
0098         dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
0099 
0100     return IRQ_HANDLED;
0101 }
0102 
0103 irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
0104 {
0105     struct snd_sof_dev *sdev = context;
0106     u32 hipci;
0107     u32 hipcida;
0108     u32 hipctdr;
0109     u32 hipctdd;
0110     u32 msg;
0111     u32 msg_ext;
0112     bool ipc_irq = false;
0113 
0114     hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0115     hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0116     hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
0117     hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
0118 
0119     /* reply message from DSP */
0120     if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
0121         msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK;
0122         msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK;
0123 
0124         dev_vdbg(sdev->dev,
0125              "ipc: firmware response, msg:0x%x, msg_ext:0x%x\n",
0126              msg, msg_ext);
0127 
0128         /* mask Done interrupt */
0129         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0130                     CNL_DSP_REG_HIPCCTL,
0131                     CNL_DSP_REG_HIPCCTL_DONE, 0);
0132 
0133         if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
0134             spin_lock_irq(&sdev->ipc_lock);
0135 
0136             /* handle immediate reply from DSP core */
0137             hda_dsp_ipc_get_reply(sdev);
0138             snd_sof_ipc_reply(sdev, msg);
0139 
0140             cnl_ipc_dsp_done(sdev);
0141 
0142             spin_unlock_irq(&sdev->ipc_lock);
0143         } else {
0144             dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
0145                         msg);
0146         }
0147 
0148         ipc_irq = true;
0149     }
0150 
0151     /* new message from DSP */
0152     if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
0153         msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
0154         msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
0155 
0156         dev_vdbg(sdev->dev,
0157              "ipc: firmware initiated, msg:0x%x, msg_ext:0x%x\n",
0158              msg, msg_ext);
0159 
0160         /* handle messages from DSP */
0161         if ((hipctdr & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
0162             struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0163             bool non_recoverable = true;
0164 
0165             /*
0166              * This is a PANIC message!
0167              *
0168              * If it is arriving during firmware boot and it is not
0169              * the last boot attempt then change the non_recoverable
0170              * to false as the DSP might be able to boot in the next
0171              * iteration(s)
0172              */
0173             if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS &&
0174                 hda->boot_iteration < HDA_FW_BOOT_ATTEMPTS)
0175                 non_recoverable = false;
0176 
0177             snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext),
0178                       non_recoverable);
0179         } else {
0180             snd_sof_ipc_msgs_rx(sdev);
0181         }
0182 
0183         cnl_ipc_host_done(sdev);
0184 
0185         ipc_irq = true;
0186     }
0187 
0188     if (!ipc_irq) {
0189         /*
0190          * This interrupt is not shared so no need to return IRQ_NONE.
0191          */
0192         dev_dbg_ratelimited(sdev->dev,
0193                     "nothing to do in IPC IRQ thread\n");
0194     }
0195 
0196     return IRQ_HANDLED;
0197 }
0198 
0199 static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
0200 {
0201     /*
0202      * clear busy interrupt to tell dsp controller this
0203      * interrupt has been accepted, not trigger it again
0204      */
0205     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0206                        CNL_DSP_REG_HIPCTDR,
0207                        CNL_DSP_REG_HIPCTDR_BUSY,
0208                        CNL_DSP_REG_HIPCTDR_BUSY);
0209     /*
0210      * set done bit to ack dsp the msg has been
0211      * processed and send reply msg to dsp
0212      */
0213     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0214                        CNL_DSP_REG_HIPCTDA,
0215                        CNL_DSP_REG_HIPCTDA_DONE,
0216                        CNL_DSP_REG_HIPCTDA_DONE);
0217 }
0218 
0219 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
0220 {
0221     /*
0222      * set DONE bit - tell DSP we have received the reply msg
0223      * from DSP, and processed it, don't send more reply to host
0224      */
0225     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0226                        CNL_DSP_REG_HIPCIDA,
0227                        CNL_DSP_REG_HIPCIDA_DONE,
0228                        CNL_DSP_REG_HIPCIDA_DONE);
0229 
0230     /* unmask Done interrupt */
0231     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0232                 CNL_DSP_REG_HIPCCTL,
0233                 CNL_DSP_REG_HIPCCTL_DONE,
0234                 CNL_DSP_REG_HIPCCTL_DONE);
0235 }
0236 
0237 static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
0238                      u32 *dr, u32 *dd)
0239 {
0240     struct sof_ipc_pm_gate *pm_gate = msg->msg_data;
0241 
0242     if (pm_gate->hdr.cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) {
0243         /* send the compact message via the primary register */
0244         *dr = HDA_IPC_MSG_COMPACT | HDA_IPC_PM_GATE;
0245 
0246         /* send payload via the extended data register */
0247         *dd = pm_gate->flags;
0248 
0249         return true;
0250     }
0251 
0252     return false;
0253 }
0254 
0255 int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0256 {
0257     struct sof_ipc4_msg *msg_data = msg->msg_data;
0258 
0259     /* send the message via mailbox */
0260     if (msg_data->data_size)
0261         sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
0262                   msg_data->data_size);
0263 
0264     snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD, msg_data->extension);
0265     snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0266               msg_data->primary | CNL_DSP_REG_HIPCIDR_BUSY);
0267 
0268     return 0;
0269 }
0270 
0271 int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0272 {
0273     struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
0274     struct sof_ipc_cmd_hdr *hdr;
0275     u32 dr = 0;
0276     u32 dd = 0;
0277 
0278     /*
0279      * Currently the only compact IPC supported is the PM_GATE
0280      * IPC which is used for transitioning the DSP between the
0281      * D0I0 and D0I3 states. And these are sent only during the
0282      * set_power_state() op. Therefore, there will never be a case
0283      * that a compact IPC results in the DSP exiting D0I3 without
0284      * the host and FW being in sync.
0285      */
0286     if (cnl_compact_ipc_compress(msg, &dr, &dd)) {
0287         /* send the message via IPC registers */
0288         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD,
0289                   dd);
0290         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0291                   CNL_DSP_REG_HIPCIDR_BUSY | dr);
0292         return 0;
0293     }
0294 
0295     /* send the message via mailbox */
0296     sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
0297               msg->msg_size);
0298     snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0299               CNL_DSP_REG_HIPCIDR_BUSY);
0300 
0301     hdr = msg->msg_data;
0302 
0303     /*
0304      * Use mod_delayed_work() to schedule the delayed work
0305      * to avoid scheduling multiple workqueue items when
0306      * IPCs are sent at a high-rate. mod_delayed_work()
0307      * modifies the timer if the work is pending.
0308      * Also, a new delayed work should not be queued after the
0309      * CTX_SAVE IPC, which is sent before the DSP enters D3.
0310      */
0311     if (hdr->cmd != (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE))
0312         mod_delayed_work(system_wq, &hdev->d0i3_work,
0313                  msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS));
0314 
0315     return 0;
0316 }
0317 
0318 void cnl_ipc_dump(struct snd_sof_dev *sdev)
0319 {
0320     u32 hipcctl;
0321     u32 hipcida;
0322     u32 hipctdr;
0323 
0324     hda_ipc_irq_dump(sdev);
0325 
0326     /* read IPC status */
0327     hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0328     hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
0329     hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0330 
0331     /* dump the IPC regs */
0332     /* TODO: parse the raw msg */
0333     dev_err(sdev->dev,
0334         "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
0335         hipcida, hipctdr, hipcctl);
0336 }
0337 
0338 /* cannonlake ops */
0339 struct snd_sof_dsp_ops sof_cnl_ops;
0340 EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
0341 
0342 int sof_cnl_ops_init(struct snd_sof_dev *sdev)
0343 {
0344     /* common defaults */
0345     memcpy(&sof_cnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
0346 
0347     /* probe/remove/shutdown */
0348     sof_cnl_ops.shutdown    = hda_dsp_shutdown;
0349 
0350     /* ipc */
0351     if (sdev->pdata->ipc_type == SOF_IPC) {
0352         /* doorbell */
0353         sof_cnl_ops.irq_thread  = cnl_ipc_irq_thread;
0354 
0355         /* ipc */
0356         sof_cnl_ops.send_msg    = cnl_ipc_send_msg;
0357     }
0358 
0359     if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
0360         struct sof_ipc4_fw_data *ipc4_data;
0361 
0362         sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL);
0363         if (!sdev->private)
0364             return -ENOMEM;
0365 
0366         ipc4_data = sdev->private;
0367         ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
0368 
0369         /* doorbell */
0370         sof_cnl_ops.irq_thread  = cnl_ipc4_irq_thread;
0371 
0372         /* ipc */
0373         sof_cnl_ops.send_msg    = cnl_ipc4_send_msg;
0374     }
0375 
0376     /* set DAI driver ops */
0377     hda_set_dai_drv_ops(sdev, &sof_cnl_ops);
0378 
0379     /* debug */
0380     sof_cnl_ops.debug_map   = cnl_dsp_debugfs;
0381     sof_cnl_ops.debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs);
0382     sof_cnl_ops.ipc_dump    = cnl_ipc_dump;
0383 
0384     /* pre/post fw run */
0385     sof_cnl_ops.post_fw_run = hda_dsp_post_fw_run;
0386 
0387     /* firmware run */
0388     sof_cnl_ops.run = hda_dsp_cl_boot_firmware;
0389 
0390     /* dsp core get/put */
0391     sof_cnl_ops.core_get = hda_dsp_core_get;
0392 
0393     return 0;
0394 };
0395 EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
0396 
0397 const struct sof_intel_dsp_desc cnl_chip_info = {
0398     /* Cannonlake */
0399     .cores_num = 4,
0400     .init_core_mask = 1,
0401     .host_managed_cores_mask = GENMASK(3, 0),
0402     .ipc_req = CNL_DSP_REG_HIPCIDR,
0403     .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
0404     .ipc_ack = CNL_DSP_REG_HIPCIDA,
0405     .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
0406     .ipc_ctl = CNL_DSP_REG_HIPCCTL,
0407     .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
0408     .rom_init_timeout   = 300,
0409     .ssp_count = CNL_SSP_COUNT,
0410     .ssp_base_offset = CNL_SSP_BASE_OFFSET,
0411     .sdw_shim_base = SDW_SHIM_BASE,
0412     .sdw_alh_base = SDW_ALH_BASE,
0413     .check_sdw_irq  = hda_common_check_sdw_irq,
0414     .check_ipc_irq  = hda_dsp_check_ipc_irq,
0415     .cl_init = cl_dsp_init,
0416     .hw_ip_version = SOF_INTEL_CAVS_1_8,
0417 };
0418 EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
0419 
0420 /*
0421  * JasperLake is technically derived from IceLake, and should be in
0422  * described in icl.c. However since JasperLake was designed with
0423  * two cores, it cannot support the IceLake-specific power-up sequences
0424  * which rely on core3. To simplify, JasperLake uses the CannonLake ops and
0425  * is described in cnl.c
0426  */
0427 const struct sof_intel_dsp_desc jsl_chip_info = {
0428     /* Jasperlake */
0429     .cores_num = 2,
0430     .init_core_mask = 1,
0431     .host_managed_cores_mask = GENMASK(1, 0),
0432     .ipc_req = CNL_DSP_REG_HIPCIDR,
0433     .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
0434     .ipc_ack = CNL_DSP_REG_HIPCIDA,
0435     .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
0436     .ipc_ctl = CNL_DSP_REG_HIPCCTL,
0437     .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
0438     .rom_init_timeout   = 300,
0439     .ssp_count = ICL_SSP_COUNT,
0440     .ssp_base_offset = CNL_SSP_BASE_OFFSET,
0441     .sdw_shim_base = SDW_SHIM_BASE,
0442     .sdw_alh_base = SDW_ALH_BASE,
0443     .check_sdw_irq  = hda_common_check_sdw_irq,
0444     .check_ipc_irq  = hda_dsp_check_ipc_irq,
0445     .cl_init = cl_dsp_init,
0446     .hw_ip_version = SOF_INTEL_CAVS_2_0,
0447 };
0448 EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);