ASoC: SOF: Intel: CNL: add support for sending compact IPC
[platform/kernel/linux-rpi.git] / sound / soc / sof / intel / cnl.c
index 982b81a..0e1e265 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "../ops.h"
 #include "hda.h"
+#include "hda-ipc.h"
 
 static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
        {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
@@ -150,14 +151,45 @@ static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
                                CNL_DSP_REG_HIPCCTL_DONE);
 }
 
+static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
+                                    u32 *dr, u32 *dd)
+{
+       struct sof_ipc_pm_gate *pm_gate;
+
+       if (msg->header == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) {
+               pm_gate = msg->msg_data;
+
+               /* send the compact message via the primary register */
+               *dr = HDA_IPC_MSG_COMPACT | HDA_IPC_PM_GATE;
+
+               /* send payload via the extended data register */
+               *dd = pm_gate->flags;
+
+               return true;
+       }
+
+       return false;
+}
+
 static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
                            struct snd_sof_ipc_msg *msg)
 {
-       /* send the message */
-       sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
-                         msg->msg_size);
-       snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
-                         CNL_DSP_REG_HIPCIDR_BUSY);
+       u32 dr = 0;
+       u32 dd = 0;
+
+       if (cnl_compact_ipc_compress(msg, &dr, &dd)) {
+               /* send the message via IPC registers */
+               snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD,
+                                 dd);
+               snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
+                                 CNL_DSP_REG_HIPCIDR_BUSY | dr);
+       } else {
+               /* send the message via mailbox */
+               sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+                                 msg->msg_size);
+               snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
+                                 CNL_DSP_REG_HIPCIDR_BUSY);
+       }
 
        return 0;
 }