summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/intel/cnl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/intel/cnl.c')
-rw-r--r--sound/soc/sof/intel/cnl.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index 19d0b1909bfd..6b075bbe5bfb 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -37,10 +37,12 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
{
struct sof_ipc4_msg notification_data = {{ 0 }};
struct snd_sof_dev *sdev = context;
+ bool ack_received = false;
bool ipc_irq = false;
u32 hipcida, hipctdr;
hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
+ hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
/* DSP received the message */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
@@ -49,9 +51,9 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
cnl_ipc_dsp_done(sdev);
ipc_irq = true;
+ ack_received = true;
}
- hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
/* Message from DSP (reply or notification) */
u32 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
@@ -70,6 +72,7 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
spin_lock_irq(&sdev->ipc_lock);
snd_sof_ipc_get_reply(sdev);
+ cnl_ipc_host_done(sdev);
snd_sof_ipc_reply(sdev, data->primary);
spin_unlock_irq(&sdev->ipc_lock);
@@ -86,10 +89,10 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
sdev->ipc->msg.rx_data = &notification_data;
snd_sof_ipc_msgs_rx(sdev);
sdev->ipc->msg.rx_data = NULL;
- }
- /* Let DSP know that we have finished processing the message */
- cnl_ipc_host_done(sdev);
+ /* Let DSP know that we have finished processing the message */
+ cnl_ipc_host_done(sdev);
+ }
ipc_irq = true;
}
@@ -98,6 +101,13 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
/* This interrupt is not shared so no need to return IRQ_NONE. */
dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
+ if (ack_received) {
+ struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
+
+ if (hdev->delayed_ipc_tx_msg)
+ cnl_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg);
+ }
+
return IRQ_HANDLED;
}
@@ -251,8 +261,16 @@ static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
+ struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
struct sof_ipc4_msg *msg_data = msg->msg_data;
+ if (hda_ipc4_tx_is_busy(sdev)) {
+ hdev->delayed_ipc_tx_msg = msg;
+ return 0;
+ }
+
+ hdev->delayed_ipc_tx_msg = NULL;
+
/* send the message via mailbox */
if (msg_data->data_size)
sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
@@ -389,6 +407,9 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev)
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_1_8;
+ /* External library loading support */
+ ipc4_data->load_library = hda_dsp_ipc4_load_library;
+
/* doorbell */
sof_cnl_ops.irq_thread = cnl_ipc4_irq_thread;
@@ -435,6 +456,9 @@ const struct sof_intel_dsp_desc cnl_chip_info = {
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
.sdw_shim_base = SDW_SHIM_BASE,
.sdw_alh_base = SDW_ALH_BASE,
+ .d0i3_offset = SOF_HDA_VS_D0I3C,
+ .read_sdw_lcount = hda_sdw_check_lcount_common,
+ .enable_sdw_irq = hda_common_enable_sdw_irq,
.check_sdw_irq = hda_common_check_sdw_irq,
.check_ipc_irq = hda_dsp_check_ipc_irq,
.cl_init = cl_dsp_init,
@@ -467,6 +491,9 @@ const struct sof_intel_dsp_desc jsl_chip_info = {
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
.sdw_shim_base = SDW_SHIM_BASE,
.sdw_alh_base = SDW_ALH_BASE,
+ .d0i3_offset = SOF_HDA_VS_D0I3C,
+ .read_sdw_lcount = hda_sdw_check_lcount_common,
+ .enable_sdw_irq = hda_common_enable_sdw_irq,
.check_sdw_irq = hda_common_check_sdw_irq,
.check_ipc_irq = hda_dsp_check_ipc_irq,
.cl_init = cl_dsp_init,