ASoC: Intel: Skylake: Correct the runtime handler behaviour
authorJeeja KP <jeeja.kp@intel.com>
Fri, 9 Oct 2015 08:01:50 +0000 (09:01 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 9 Oct 2015 10:19:00 +0000 (11:19 +0100)
On runtime pm resume, we need to download the firmware, also on
suspend we need to ensure all the interrupts from controller and
DSP are disabled.

Also since we download the firmware on resume, we don't need to do
so on init, so remove that bit

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/common/sst-dsp-priv.h
sound/soc/intel/skylake/skl-sst-ipc.c
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst.c

index cbd568eac033ebe3aa1af77a2b51ec92e3ccae50..2151652d37b72e33c556b11ea46af565747fd965 100644 (file)
@@ -314,6 +314,7 @@ struct sst_dsp {
        int sst_state;
        struct skl_cl_dev cl_dev;
        u32 intr_status;
+       const struct firmware *fw;
 };
 
 /* Size optimised DRAM/IRAM memcpy */
index 937a0a3a63a0f0241cb19c89f79a2410665d898a..3345ea0d44147e9fdb62275f73d1d0d6d64e0c5f 100644 (file)
@@ -464,6 +464,18 @@ void skl_ipc_op_int_enable(struct sst_dsp *ctx)
                SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
 }
 
+void skl_ipc_op_int_disable(struct sst_dsp *ctx)
+{
+       /* disable IPC DONE interrupt */
+       sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
+                                       SKL_ADSP_REG_HIPCCTL_DONE, 0);
+
+       /* Disable IPC BUSY interrupt */
+       sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
+                                       SKL_ADSP_REG_HIPCCTL_BUSY, 0);
+
+}
+
 bool skl_ipc_int_status(struct sst_dsp *ctx)
 {
        return sst_dsp_shim_read_unlocked(ctx,
index 9f5f67202858fdbbcfe665c9a9275bfae1f073e7..f1a154e45dc343209b7a1adb8010f62313785bf8 100644 (file)
@@ -116,6 +116,7 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
 
 void skl_ipc_int_enable(struct sst_dsp *dsp);
 void skl_ipc_op_int_enable(struct sst_dsp *ctx);
+void skl_ipc_op_int_disable(struct sst_dsp *ctx);
 void skl_ipc_int_disable(struct sst_dsp *dsp);
 
 bool skl_ipc_int_status(struct sst_dsp *dsp);
index c18ea51b7484d13e0ed79d3d56f774d6c55b653f..3b83dc99f1d405ffd5ea65e1376cae6920a99e63 100644 (file)
@@ -70,15 +70,31 @@ static int skl_transfer_firmware(struct sst_dsp *ctx,
 static int skl_load_base_firmware(struct sst_dsp *ctx)
 {
        int ret = 0, i;
-       const struct firmware *fw = NULL;
        struct skl_sst *skl = ctx->thread_context;
        u32 reg;
 
-       ret = request_firmware(&fw, "dsp_fw_release.bin", ctx->dev);
+       skl->boot_complete = false;
+       init_waitqueue_head(&skl->boot_wait);
+
+       if (ctx->fw == NULL) {
+               ret = request_firmware(&ctx->fw, "dsp_fw_release.bin", ctx->dev);
+               if (ret < 0) {
+                       dev_err(ctx->dev, "Request firmware failed %d\n", ret);
+                       skl_dsp_disable_core(ctx);
+                       return -EIO;
+               }
+       }
+
+       ret = skl_dsp_boot(ctx);
        if (ret < 0) {
-               dev_err(ctx->dev, "Request firmware failed %d\n", ret);
-               skl_dsp_disable_core(ctx);
-               return -EIO;
+               dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret);
+               goto skl_load_base_firmware_failed;
+       }
+
+       ret = skl_cldma_prepare(ctx);
+       if (ret < 0) {
+               dev_err(ctx->dev, "CL dma prepare failed : %d", ret);
+               goto skl_load_base_firmware_failed;
        }
 
        /* enable Interrupt */
@@ -102,7 +118,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
                goto skl_load_base_firmware_failed;
        }
 
-       ret = skl_transfer_firmware(ctx, fw->data, fw->size);
+       ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size);
        if (ret < 0) {
                dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
                goto skl_load_base_firmware_failed;
@@ -118,13 +134,12 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
                dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
                skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
        }
-       release_firmware(fw);
-
        return 0;
 
 skl_load_base_firmware_failed:
        skl_dsp_disable_core(ctx);
-       release_firmware(fw);
+       release_firmware(ctx->fw);
+       ctx->fw = NULL;
        return ret;
 }
 
@@ -172,6 +187,12 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
        }
        skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
 
+       /* disable Interrupt */
+       ctx->cl_dev.ops.cl_cleanup_controller(ctx);
+       skl_cldma_int_disable(ctx);
+       skl_ipc_op_int_disable(ctx);
+       skl_ipc_int_disable(ctx);
+
        return ret;
 }
 
@@ -235,22 +256,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
        if (ret)
                return ret;
 
-       skl->boot_complete = false;
-       init_waitqueue_head(&skl->boot_wait);
-
-       ret = skl_dsp_boot(sst);
-       if (ret < 0) {
-               dev_err(skl->dev, "Boot dsp core failed ret: %d", ret);
-               goto free_ipc;
-       }
-
-       ret = skl_cldma_prepare(sst);
-       if (ret < 0) {
-               dev_err(dev, "CL dma prepare failed : %d", ret);
-               goto free_ipc;
-       }
-
-
        ret = sst->fw_ops.load_fw(sst);
        if (ret < 0) {
                dev_err(dev, "Load base fw failed : %d", ret);
@@ -262,7 +267,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 
        return 0;
 
-free_ipc:
        skl_ipc_free(&skl->ipc);
        return ret;
 }