[alsa-devel] [PATCH v2 0/6] ASoC: Intel: Skylake: Add loadable module support for Kabylake
KBL module load is a bit different than rest as Library manifest containing module information is required to be loaded first before loading module.
So common changes are moved to helpers and arguments are modified as a pre-work for adding module loading support.
Also, separate dsp_fw_ops is registered and load library for kabylake is added to use code loader dma for library and module load.
changes in v2: - Few minor fixes in comments - Fixed the cover letter subject
G Kranthi (2): ASoC: Intel: Skylake: Move sst common initialization to a helper function ASoC: Intel: Skylake: Modify arguments to reuse module transfer function
Sodhi, VunnyX (1): ASoC: Intel: Skylake: Add loadable module support on KBL platform
Subhransu S. Prusty (3): ASoC: Intel: Skylake: Commonize library load ASoC: Intel: Skylake: Register dsp_fw_ops for kabylake ASoC: Intel: Skylake: Modify load_lib_ipc arguments for a nowait version
sound/soc/intel/skylake/bxt-sst.c | 68 +++-------------- sound/soc/intel/skylake/skl-messages.c | 2 +- sound/soc/intel/skylake/skl-sst-dsp.h | 13 +++- sound/soc/intel/skylake/skl-sst-ipc.c | 10 ++- sound/soc/intel/skylake/skl-sst-ipc.h | 2 +- sound/soc/intel/skylake/skl-sst-utils.c | 80 ++++++++++++++++++++ sound/soc/intel/skylake/skl-sst.c | 125 ++++++++++++++++++++++++-------- 7 files changed, 208 insertions(+), 92 deletions(-)
From: G Kranthi gudishax.kranthikumar@intel.com
Some skl sst context are not dependent of platform and initializing them independently for each platform can lead to errors. So optimize by moving them to a helper function and platform specific init code can call this.
Signed-off-by: G Kranthi gudishax.kranthikumar@intel.com Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/bxt-sst.c | 28 +++++-------------------- sound/soc/intel/skylake/skl-sst-dsp.h | 3 +++ sound/soc/intel/skylake/skl-sst-utils.c | 37 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-sst.c | 32 ++++++---------------------- 4 files changed, 51 insertions(+), 49 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 600d95891996..c54f56c568e8 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -590,23 +590,14 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, struct sst_dsp *sst; int ret;
- skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); - if (skl == NULL) - return -ENOMEM; - - skl->dev = dev; - skl_dev.thread_context = skl; - INIT_LIST_HEAD(&skl->uuid_list); - - skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); - if (!skl->dsp) { - dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); - return -ENODEV; + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev); + if (ret < 0) { + dev_err(skl->dev, "%s: no device\n", __func__); + return ret; }
+ skl = *dsp; sst = skl->dsp; - sst->fw_name = fw_name; - sst->dsp_ops = dsp_ops; sst->fw_ops = bxt_fw_ops; sst->addr.lpe = mmio_base; sst->addr.shim = mmio_base; @@ -614,24 +605,15 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
- INIT_LIST_HEAD(&sst->module_list); - ret = skl_ipc_init(dev, skl); - if (ret) - return ret; - /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); - skl->is_first_boot = true; INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); skl->d0i3.state = SKL_DSP_D0I3_NONE;
- if (dsp) - *dsp = skl; - return 0; } EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 7229a12b4c94..c1f95e23933d 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -247,5 +247,8 @@ int skl_get_pvt_instance_id_map(struct skl_sst *ctx,
int skl_dsp_strip_extended_manifest(struct firmware *fw); void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable); +int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, + struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, + struct sst_dsp_device *skl_dev);
#endif /*__SKL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 6d5bff04bf65..a72152123c3c 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -361,3 +361,40 @@ int skl_dsp_strip_extended_manifest(struct firmware *fw)
return 0; } + +int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, + struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, + struct sst_dsp_device *skl_dev) +{ + struct skl_sst *skl; + struct sst_dsp *sst; + int ret; + + skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); + if (skl == NULL) + return -ENOMEM; + + skl->dev = dev; + skl_dev->thread_context = skl; + INIT_LIST_HEAD(&skl->uuid_list); + skl->dsp = skl_dsp_ctx_init(dev, skl_dev, irq); + if (!skl->dsp) { + dev_err(skl->dev, "%s: no device\n", __func__); + return -ENODEV; + } + + sst = skl->dsp; + sst->fw_name = fw_name; + sst->dsp_ops = dsp_ops; + init_waitqueue_head(&skl->mod_load_wait); + INIT_LIST_HEAD(&sst->module_list); + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + + skl->is_first_boot = true; + if (dsp) + *dsp = skl; + + return ret; +} diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 539529729e3f..4fdd503a837c 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -330,7 +330,6 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, int ret, bytes_left, curr_pos; struct skl_sst *skl = ctx->thread_context; skl->mod_load_complete = false; - init_waitqueue_head(&skl->mod_load_wait);
bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false); if (bytes_left < 0) @@ -489,43 +488,24 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, struct sst_dsp *sst; int ret;
- skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); - if (skl == NULL) - return -ENOMEM; - - skl->dev = dev; - skl_dev.thread_context = skl; - INIT_LIST_HEAD(&skl->uuid_list); - - skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); - if (!skl->dsp) { - dev_err(skl->dev, "%s: no device\n", __func__); - return -ENODEV; + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev); + if (ret < 0) { + dev_err(dev, "%s: no device\n", __func__); + return ret; }
+ skl = *dsp; sst = skl->dsp; - - sst->fw_name = fw_name; sst->addr.lpe = mmio_base; sst->addr.shim = mmio_base; sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
- INIT_LIST_HEAD(&sst->module_list); - sst->dsp_ops = dsp_ops; sst->fw_ops = skl_fw_ops;
- ret = skl_ipc_init(dev, skl); - if (ret) - return ret; - skl->cores.count = 2; - skl->is_first_boot = true; - - if (dsp) - *dsp = skl;
- return ret; + return 0; } EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
request firmware, strip extended manifest and release library changes are common to kabylake and APL.
So move these common code to utils to be reused in later patches for kabylake library load.
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/bxt-sst.c | 38 ++++------------------------- sound/soc/intel/skylake/skl-sst-dsp.h | 7 +++++- sound/soc/intel/skylake/skl-sst-utils.c | 43 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 34 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index c54f56c568e8..2df7d104bfca 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -53,18 +53,6 @@ static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); }
-static void sst_bxt_release_library(struct skl_lib_info *linfo, int lib_count) -{ - int i; - - for (i = 1; i < lib_count; i++) { - if (linfo[i].fw) { - release_firmware(linfo[i].fw); - linfo[i].fw = NULL; - } - } -} - static int bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) { @@ -75,26 +63,10 @@ static void sst_bxt_release_library(struct skl_lib_info *linfo, int lib_count)
/* library indices start from 1 to N. 0 represents base FW */ for (i = 1; i < lib_count; i++) { - if (linfo[i].fw == NULL) { - ret = request_firmware(&linfo[i].fw, linfo[i].name, - ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request lib %s failed:%d\n", - linfo[i].name, ret); - goto load_library_failed; - } - } - - if (skl->is_first_boot) { - ret = snd_skl_parse_uuids(ctx, linfo[i].fw, + ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, BXT_ADSP_FW_BIN_HDR_OFFSET, i); - if (ret < 0) - goto load_library_failed; - } - - stripped_fw.data = linfo[i].fw->data; - stripped_fw.size = linfo[i].fw->size; - skl_dsp_strip_extended_manifest(&stripped_fw); + if (ret < 0) + goto load_library_failed;
stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, stripped_fw.size, &dmab); @@ -121,7 +93,7 @@ static void sst_bxt_release_library(struct skl_lib_info *linfo, int lib_count) return ret;
load_library_failed: - sst_bxt_release_library(linfo, lib_count); + skl_release_library(linfo, lib_count); return ret; }
@@ -648,7 +620,7 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) {
- sst_bxt_release_library(ctx->lib_info, ctx->lib_count); + skl_release_library(ctx->lib_info, ctx->lib_count); if (ctx->dsp->fw) release_firmware(ctx->dsp->fw); skl_freeup_uuid_list(ctx); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index c1f95e23933d..6d9aed23d5cd 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -18,6 +18,7 @@
#include <linux/interrupt.h> #include <linux/uuid.h> +#include <linux/firmware.h> #include <sound/memalloc.h> #include "skl-sst-cldma.h"
@@ -145,7 +146,7 @@ struct skl_dsp_fw_ops { int (*load_fw)(struct sst_dsp *ctx); /* FW module parser/loader */ int (*load_library)(struct sst_dsp *ctx, - struct skl_lib_info *linfo, int count); + struct skl_lib_info *linfo, int lib_count); int (*parse_fw)(struct sst_dsp *ctx); int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); @@ -250,5 +251,9 @@ int skl_get_pvt_instance_id_map(struct skl_sst *ctx, int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, struct sst_dsp_device *skl_dev); +int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, + struct firmware *stripped_fw, + unsigned int hdr_offset, int index); +void skl_release_library(struct skl_lib_info *linfo, int lib_count);
#endif /*__SKL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index a72152123c3c..81ee251881b4 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -398,3 +398,46 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name,
return ret; } + +int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, + struct firmware *stripped_fw, + unsigned int hdr_offset, int index) +{ + int ret; + struct sst_dsp *dsp = skl->dsp; + + if (linfo->fw == NULL) { + ret = request_firmware(&linfo->fw, linfo->name, + skl->dev); + if (ret < 0) { + dev_err(skl->dev, "Request lib %s failed:%d\n", + linfo->name, ret); + return ret; + } + } + + if (skl->is_first_boot) { + ret = snd_skl_parse_uuids(dsp, linfo->fw, hdr_offset, index); + if (ret < 0) + return ret; + } + + stripped_fw->data = linfo->fw->data; + stripped_fw->size = linfo->fw->size; + skl_dsp_strip_extended_manifest(stripped_fw); + + return 0; +} + +void skl_release_library(struct skl_lib_info *linfo, int lib_count) +{ + int i; + + /* library indices start from 1 to N. 0 represents base FW */ + for (i = 1; i < lib_count; i++) { + if (linfo[i].fw) { + release_firmware(linfo[i].fw); + linfo[i].fw = NULL; + } + } +}
From: G Kranthi gudishax.kranthikumar@intel.com
Kabylake also uses code loader dma for module load and library load. skl_transfer_module can be reused. Modify the arguments to include library index to be passed to lib load ipc and module/lib check to use correct ipc for lib/module load.
Signed-off-by: G Kranthi gudishax.kranthikumar@intel.com Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/skl-sst.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 4fdd503a837c..b4c3b5c63115 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -325,7 +325,7 @@ static struct skl_module_table *skl_module_get_from_id( }
static int skl_transfer_module(struct sst_dsp *ctx, const void *data, - u32 size, u16 mod_id) + u32 size, u16 mod_id, u8 table_id, bool is_module) { int ret, bytes_left, curr_pos; struct skl_sst *skl = ctx->thread_context; @@ -335,10 +335,12 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, if (bytes_left < 0) return bytes_left;
- ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load module: %d\n", ret); - goto out; + if (is_module) { /* load module */ + ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load module: %d\n", ret); + goto out; + } }
/* @@ -393,7 +395,8 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid)
if (!module_entry->usage_cnt) { ret = skl_transfer_module(ctx, module_entry->mod_info->fw->data, - module_entry->mod_info->fw->size, mod_id); + module_entry->mod_info->fw->size, + mod_id, 0, true); if (ret < 0) { dev_err(ctx->dev, "Failed to Load module\n"); return ret;
The patch
ASoC: Intel: Skylake: Modify arguments to reuse module transfer function
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4e0277d226b578be99cf8899fd1442bf11873d12 Mon Sep 17 00:00:00 2001
From: G Kranthi gudishax.kranthikumar@intel.com Date: Tue, 25 Apr 2017 12:18:21 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Modify arguments to reuse module transfer function
Kabylake also uses code loader dma for module load and library load. skl_transfer_module can be reused. Modify the arguments to include library index to be passed to lib load ipc and module/lib check to use correct ipc for lib/module load.
Signed-off-by: G Kranthi gudishax.kranthikumar@intel.com Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Acked-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 4fdd503a837c..b4c3b5c63115 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -325,7 +325,7 @@ static struct skl_module_table *skl_module_get_from_id( }
static int skl_transfer_module(struct sst_dsp *ctx, const void *data, - u32 size, u16 mod_id) + u32 size, u16 mod_id, u8 table_id, bool is_module) { int ret, bytes_left, curr_pos; struct skl_sst *skl = ctx->thread_context; @@ -335,10 +335,12 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, if (bytes_left < 0) return bytes_left;
- ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load module: %d\n", ret); - goto out; + if (is_module) { /* load module */ + ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load module: %d\n", ret); + goto out; + } }
/* @@ -393,7 +395,8 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid)
if (!module_entry->usage_cnt) { ret = skl_transfer_module(ctx, module_entry->mod_info->fw->data, - module_entry->mod_info->fw->size, mod_id); + module_entry->mod_info->fw->size, + mod_id, 0, true); if (ret < 0) { dev_err(ctx->dev, "Failed to Load module\n"); return ret;
For audio kabylake is same as skylake except the module load approach. This patch registers different dsp_fw_ops for kabylake and next patch adds the module load support for kabylake.
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/skl-messages.c | 2 +- sound/soc/intel/skylake/skl-sst-dsp.h | 3 +++ sound/soc/intel/skylake/skl-sst.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 09730dd8e6a3..ab1adc0c9cc3 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -209,7 +209,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void) { .id = 0x9d71, .loader_ops = skl_get_loader_ops, - .init = skl_sst_dsp_init, + .init = kbl_sst_dsp_init, .init_fw = skl_sst_init_fw, .cleanup = skl_sst_dsp_cleanup }, diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 6d9aed23d5cd..eba20d37ba8c 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -230,6 +230,9 @@ int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx, int skl_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 kbl_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 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); diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index b4c3b5c63115..20968e5ec86d 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -470,6 +470,15 @@ static void skl_clear_module_table(struct sst_dsp *ctx) .unload_mod = skl_unload_module, };
+static struct skl_dsp_fw_ops kbl_fw_ops = { + .set_state_D0 = skl_set_dsp_D0, + .set_state_D3 = skl_set_dsp_D3, + .load_fw = skl_load_base_firmware, + .get_fw_errcode = skl_get_errorcode, + .load_mod = skl_load_module, + .unload_mod = skl_unload_module, +}; + static struct sst_ops skl_ops = { .irq_handler = skl_dsp_sst_interrupt, .write = sst_shim32_write, @@ -512,6 +521,27 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, } EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
+int kbl_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) +{ + struct sst_dsp *sst; + int ret; + + ret = skl_sst_dsp_init(dev, mmio_base, irq, fw_name, dsp_ops, dsp); + if (ret < 0) { + dev_err(dev, "%s: Init failed %d\n", __func__, ret); + return ret; + } + + sst = (*dsp)->dsp; + sst->fw_ops = kbl_fw_ops; + + return 0; + +} +EXPORT_SYMBOL_GPL(kbl_sst_dsp_init); + int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) { int ret;
Kabylake uses code loader dma and wait on notification instead of ipc reply for load library ipc status. So modify the argument of skl_sst_ipc_load_library to check on flag to wait for ipc reply.
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/bxt-sst.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.c | 8 ++++++-- sound/soc/intel/skylake/skl-sst-ipc.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 2df7d104bfca..a7d1a3ffedcb 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -81,7 +81,7 @@ static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) memcpy(dmab.area, stripped_fw.data, stripped_fw.size);
ctx->dsp_ops.trigger(ctx->dev, true, stream_tag); - ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); + ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i, true); if (ret < 0) dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", linfo[i].name, ret); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index d51b483b4d79..c0226dd59445 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -971,7 +971,7 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, - u8 dma_id, u8 table_id) + u8 dma_id, u8 table_id, bool wait) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); @@ -983,7 +983,11 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, header.primary |= IPC_MOD_INSTANCE_ID(table_id); header.primary |= IPC_MOD_ID(dma_id);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + if (wait) + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, + NULL, 0, NULL, 0); + else + ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0);
if (ret < 0) dev_err(ipc->dev, "ipc: load lib failed\n"); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 4abf98c0e00e..e057da2713c6 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -197,7 +197,7 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param);
int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, - u8 dma_id, u8 table_id); + u8 dma_id, u8 table_id, bool wait);
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg);
From: "Sodhi, VunnyX" vunnyx.sodhi@intel.com
Kabylake platform expects modules in a library manifest. After loading base firmware library manifest is loaded using load library IPC. This is followed by module load using load multiple modules IPC.
Signed-off-by: Sodhi, VunnyX vunnyx.sodhi@intel.com Signed-off-by: G Kranthi gudishax.kranthikumar@intel.com Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com --- sound/soc/intel/skylake/skl-sst-ipc.c | 2 ++ sound/soc/intel/skylake/skl-sst.c | 64 +++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index c0226dd59445..3679d6c61cbf 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -427,6 +427,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: + case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = true; wake_up(&skl->mod_load_wait); @@ -443,6 +444,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: + case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = false; wake_up(&skl->mod_load_wait); diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 20968e5ec86d..155e456b7a3a 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -179,6 +179,18 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) dev_err(ctx->dev, "unable to load firmware\n"); return ret; } + + /* load libs as they are also lost on D3 */ + if (skl->lib_count > 1) { + ret = ctx->fw_ops.load_library(ctx, skl->lib_info, + skl->lib_count); + if (ret < 0) { + dev_err(ctx->dev, "reload libs failed: %d\n", + ret); + return ret; + } + + } }
/* @@ -204,7 +216,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
skl->cores.state[core_id] = SKL_DSP_RUNNING;
- return ret; + return 0; }
static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) @@ -335,12 +347,16 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, if (bytes_left < 0) return bytes_left;
- if (is_module) { /* load module */ + /* check is_module flag to load module or library */ + if (is_module) ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load module: %d\n", ret); - goto out; - } + else + ret = skl_sst_ipc_load_library(&skl->ipc, 0, table_id, false); + + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load %s with err %d\n", + is_module ? "module" : "lib", ret); + goto out; }
/* @@ -373,6 +389,32 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, return ret; }
+static int +kbl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) +{ + struct skl_sst *skl = ctx->thread_context; + struct firmware stripped_fw; + int ret, i; + + /* library indices start from 1 to N. 0 represents base FW */ + for (i = 1; i < lib_count; i++) { + ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, + SKL_ADSP_FW_BIN_HDR_OFFSET, i); + if (ret < 0) + goto load_library_failed; + ret = skl_transfer_module(ctx, stripped_fw.data, + stripped_fw.size, 0, i, false); + if (ret < 0) + goto load_library_failed; + } + + return 0; + +load_library_failed: + skl_release_library(linfo, lib_count); + return ret; +} + static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) { struct skl_module_table *module_entry = NULL; @@ -475,6 +517,7 @@ static void skl_clear_module_table(struct sst_dsp *ctx) .set_state_D3 = skl_set_dsp_D3, .load_fw = skl_load_base_firmware, .get_fw_errcode = skl_get_errorcode, + .load_library = kbl_load_library, .load_mod = skl_load_module, .unload_mod = skl_unload_module, }; @@ -554,6 +597,15 @@ int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) }
skl_dsp_init_core_state(sst); + + if (ctx->lib_count > 1) { + ret = sst->fw_ops.load_library(sst, ctx->lib_info, + ctx->lib_count); + if (ret < 0) { + dev_err(dev, "Load Library failed : %x\n", ret); + return ret; + } + } ctx->is_first_boot = false;
return 0;
The patch
ASoC: Intel: Skylake: Add loadable module support on KBL platform
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From b6726009af555129c57dfbbf80a1fcf4d5a36ba0 Mon Sep 17 00:00:00 2001
From: "Sodhi, VunnyX" vunnyx.sodhi@intel.com Date: Tue, 25 Apr 2017 12:18:24 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Add loadable module support on KBL platform
Kabylake platform expects modules in a library manifest. After loading base firmware library manifest is loaded using load library IPC. This is followed by module load using load multiple modules IPC.
Signed-off-by: Sodhi, VunnyX vunnyx.sodhi@intel.com Signed-off-by: G Kranthi gudishax.kranthikumar@intel.com Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Acked-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst-ipc.c | 2 ++ sound/soc/intel/skylake/skl-sst.c | 64 +++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 7147eddc6d3c..58c525096a7c 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -427,6 +427,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: + case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = true; wake_up(&skl->mod_load_wait); @@ -443,6 +444,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: + case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = false; wake_up(&skl->mod_load_wait); diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 20968e5ec86d..155e456b7a3a 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -179,6 +179,18 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) dev_err(ctx->dev, "unable to load firmware\n"); return ret; } + + /* load libs as they are also lost on D3 */ + if (skl->lib_count > 1) { + ret = ctx->fw_ops.load_library(ctx, skl->lib_info, + skl->lib_count); + if (ret < 0) { + dev_err(ctx->dev, "reload libs failed: %d\n", + ret); + return ret; + } + + } }
/* @@ -204,7 +216,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
skl->cores.state[core_id] = SKL_DSP_RUNNING;
- return ret; + return 0; }
static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) @@ -335,12 +347,16 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, if (bytes_left < 0) return bytes_left;
- if (is_module) { /* load module */ + /* check is_module flag to load module or library */ + if (is_module) ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load module: %d\n", ret); - goto out; - } + else + ret = skl_sst_ipc_load_library(&skl->ipc, 0, table_id, false); + + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load %s with err %d\n", + is_module ? "module" : "lib", ret); + goto out; }
/* @@ -373,6 +389,32 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, return ret; }
+static int +kbl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) +{ + struct skl_sst *skl = ctx->thread_context; + struct firmware stripped_fw; + int ret, i; + + /* library indices start from 1 to N. 0 represents base FW */ + for (i = 1; i < lib_count; i++) { + ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, + SKL_ADSP_FW_BIN_HDR_OFFSET, i); + if (ret < 0) + goto load_library_failed; + ret = skl_transfer_module(ctx, stripped_fw.data, + stripped_fw.size, 0, i, false); + if (ret < 0) + goto load_library_failed; + } + + return 0; + +load_library_failed: + skl_release_library(linfo, lib_count); + return ret; +} + static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) { struct skl_module_table *module_entry = NULL; @@ -475,6 +517,7 @@ static struct skl_dsp_fw_ops kbl_fw_ops = { .set_state_D3 = skl_set_dsp_D3, .load_fw = skl_load_base_firmware, .get_fw_errcode = skl_get_errorcode, + .load_library = kbl_load_library, .load_mod = skl_load_module, .unload_mod = skl_unload_module, }; @@ -554,6 +597,15 @@ int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) }
skl_dsp_init_core_state(sst); + + if (ctx->lib_count > 1) { + ret = sst->fw_ops.load_library(sst, ctx->lib_info, + ctx->lib_count); + if (ret < 0) { + dev_err(dev, "Load Library failed : %x\n", ret); + return ret; + } + } ctx->is_first_boot = false;
return 0;
On Tue, Apr 25, 2017 at 12:18:18PM +0530, Subhransu S. Prusty wrote:
KBL module load is a bit different than rest as Library manifest containing module information is required to be loaded first before loading module.
So common changes are moved to helpers and arguments are modified as a pre-work for adding module loading support.
Also, separate dsp_fw_ops is registered and load library for kabylake is added to use code loader dma for library and module load.
Acked-by: Vinod Koul vinod.koul@intel.com
participants (3)
-
Mark Brown
-
Subhransu S. Prusty
-
Vinod Koul