]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ASoC: Intel: Skylake: split fw and dsp initialization
authorVinod Koul <vinod.koul@intel.com>
Tue, 26 Jul 2016 12:36:42 +0000 (18:06 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 8 Aug 2016 10:54:59 +0000 (11:54 +0100)
The DSP instance creation also loads the firmware on DSPs. For library load
the firmware names come from topology so can't be loaded at object creation.

So split the firmware load and object creation. FW load is now called after
topology init in platform probe.

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl.h

index 2663781278aa8b9648e23d7bc6fcc7623bb834e8..eb68258b653d4f0a55549c16dd62616a8a9128d8 100644 (file)
@@ -397,6 +397,19 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
        skl->cores.count = 2;
        skl->boot_complete = false;
        init_waitqueue_head(&skl->boot_wait);
+       skl->is_first_boot = true;
+
+       if (dsp)
+               *dsp = skl;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
+
+int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx)
+{
+       int ret;
+       struct sst_dsp *sst = ctx->dsp;
 
        ret = sst->fw_ops.load_fw(sst);
        if (ret < 0) {
@@ -406,13 +419,11 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 
        skl_dsp_init_core_state(sst);
 
-       if (dsp)
-               *dsp = skl;
+       ctx->is_first_boot = false;
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
-
+EXPORT_SYMBOL_GPL(bxt_sst_init_fw);
 
 void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
 {
index 25d057679f2c93fa9ae22dfb6b9d11e03283aa91..2199a91d90d68ec2fd8cd810817f96ba8354a41f 100644 (file)
@@ -203,18 +203,21 @@ static const struct skl_dsp_ops dsp_ops[] = {
                .id = 0x9d70,
                .loader_ops = skl_get_loader_ops,
                .init = skl_sst_dsp_init,
+               .init_fw = skl_sst_init_fw,
                .cleanup = skl_sst_dsp_cleanup
        },
        {
                .id = 0x9d71,
                .loader_ops = skl_get_loader_ops,
                .init = skl_sst_dsp_init,
+               .init_fw = skl_sst_init_fw,
                .cleanup = skl_sst_dsp_cleanup
        },
        {
                .id = 0x5a98,
                .loader_ops = bxt_get_loader_ops,
                .init = bxt_sst_dsp_init,
+               .init_fw = bxt_sst_init_fw,
                .cleanup = bxt_sst_dsp_cleanup
        },
 };
@@ -264,7 +267,6 @@ int skl_init_dsp(struct skl *skl)
        if (ret < 0)
                return ret;
 
-       skl_dsp_enable_notification(skl->skl_sst, false);
        dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
 
        return ret;
@@ -325,6 +327,10 @@ int skl_resume_dsp(struct skl *skl)
        snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
        snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true);
 
+       /* check if DSP 1st boot is done */
+       if (skl->skl_sst->is_first_boot == true)
+               return 0;
+
        ret = skl_dsp_wake(ctx->dsp);
        if (ret < 0)
                return ret;
index 6e05bf8622f7ad1f1cf0ac6f9b11516469e4b86f..22d4f0703a33fe667bf4474e230aa639ff2fff99 100644 (file)
@@ -1142,8 +1142,10 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
 {
        struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
        struct skl *skl = ebus_to_skl(ebus);
+       const struct skl_dsp_ops *ops;
        int ret;
 
+       pm_runtime_get_sync(platform->dev);
        if (ebus->ppcap) {
                ret = skl_tplg_init(platform, ebus);
                if (ret < 0) {
@@ -1151,7 +1153,25 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
                        return ret;
                }
                skl->platform = platform;
+
+               /* load the firmwares, since all is set */
+               ops = skl_get_dsp_ops(skl->pci->device);
+               if (!ops)
+                       return -EIO;
+
+               if (skl->skl_sst->is_first_boot == false) {
+                       dev_err(platform->dev, "DSP reports first boot done!!!\n");
+                       return -EIO;
+               }
+
+               ret = ops->init_fw(platform->dev, skl->skl_sst);
+               if (ret < 0) {
+                       dev_err(platform->dev, "Failed to boot first fw: %d\n", ret);
+                       return ret;
+               }
        }
+       pm_runtime_mark_last_busy(platform->dev);
+       pm_runtime_put_autosuspend(platform->dev);
 
        return 0;
 }
index 0f8629ef79ac86a315029b19e28a780323d9b11c..7e994688d8a00827f1a5050221ea592b9e467634 100644 (file)
@@ -203,6 +203,8 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
                const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
                struct skl_sst **dsp);
+int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx);
+int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx);
 void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
 void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
 
index 2e3d4e80ef97553fb0573b1d9f7d888fb41cb58c..0a0d09cde99dc61cdbc1ba8fa770be3b049b51c1 100644 (file)
@@ -75,6 +75,9 @@ struct skl_sst {
        /* Is firmware loaded */
        bool fw_loaded;
 
+       /* first boot ? */
+       bool is_first_boot;
+
        /* multi-core */
        struct skl_dsp_cores cores;
 };
index 588f899ceb652b5efcb2b87451a058f6dfc2ab0d..6de4c027a65b0aa494f5ceeece393c81c711364d 100644 (file)
@@ -484,25 +484,32 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
                return ret;
 
        skl->cores.count = 2;
+       skl->is_first_boot = true;
+
+       if (dsp)
+               *dsp = skl;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
+
+int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx)
+{
+       int ret;
+       struct sst_dsp *sst = ctx->dsp;
 
        ret = sst->fw_ops.load_fw(sst);
        if (ret < 0) {
                dev_err(dev, "Load base fw failed : %d", ret);
-               goto cleanup;
+               return ret;
        }
 
        skl_dsp_init_core_state(sst);
+       ctx->is_first_boot = false;
 
-       if (dsp)
-               *dsp = skl;
-
-       return ret;
-
-cleanup:
-       skl_sst_dsp_cleanup(dev, skl);
-       return ret;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
+EXPORT_SYMBOL_GPL(skl_sst_init_fw);
 
 void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
 {
index c3538f8b17d951fc9664ff80aa6f3cabb8ec0872..5d4fbb094c48da9fe238b8c27f09f3c41141d0ed 100644 (file)
@@ -105,6 +105,7 @@ struct skl_dsp_ops {
                        int irq, const char *fw_name,
                        struct skl_dsp_loader_ops loader_ops,
                        struct skl_sst **skl_sst);
+       int (*init_fw)(struct device *dev, struct skl_sst *ctx);
        void (*cleanup)(struct device *dev, struct skl_sst *ctx);
 };