[alsa-devel] [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules
This series adds first the infrastructure for loadable modules in SKL aDSP. The loadable modules are loaded using load/unload IPC to aDSP thru code load DMA and can be configured by user thru TLV byte kcontrols for these modules.
This also adds the implementation of new DAPM sinks for phrase detection modules, and adds support for keeping controller active while is suspend to support ignore_suspend DAIs
Changes on v2: - squash two load module IPCs and load modules usgae patches - add comments for module loading - add active suspend two patches
Dharageswari R (2): ASoC: Intel: Skylake: Add support for Loadable modules ASoC: Intel: Skylake: Add support for Mic Select module
Jeeja KP (4): ASoC: Intel: Skylake: Add memory pages to widget data. ASoC: Intel: Skylake: Fix module init data correctly ASoC: Intel: Skylake: Add dai link for DMIC capture ASoC: Intel: Skylake: Add support for active suspend
Mousami Jana (1): ASoC: Intel: Skylake: add LARGE_CONFIG_GET IPC support
Omair M Abdullah (2): ASoC: Intel: Skylake: update mailbox uplink window offset and size ASoC: Intel: Skylake: read params from DSP if module is on
Praveen Diwakar (1): ASoC: Intel: Skylake: Update ignore suspend for rt286 machine
Vinod Koul (2): ASoC: Intel: Skylake: add wov as int sink ASoc: Intel: Skylake: Fix the dapm machine map
sound/soc/intel/boards/skl_rt286.c | 73 ++++++++++- sound/soc/intel/skylake/skl-messages.c | 40 ++++++ sound/soc/intel/skylake/skl-pcm.c | 27 +++++ sound/soc/intel/skylake/skl-sst-dsp.h | 18 ++- sound/soc/intel/skylake/skl-sst-ipc.c | 106 ++++++++++++++++ sound/soc/intel/skylake/skl-sst-ipc.h | 9 ++ sound/soc/intel/skylake/skl-sst.c | 175 +++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.c | 43 ++++++- sound/soc/intel/skylake/skl-topology.h | 12 +- sound/soc/intel/skylake/skl-tplg-interface.h | 19 ++- sound/soc/intel/skylake/skl.c | 28 ++++- sound/soc/intel/skylake/skl.h | 2 + 12 files changed, 533 insertions(+), 19 deletions(-)
From: Dharageswari R dharageswari.r@intel.com
A module is loaded when the path consisting the module is opened. The module binary(ies) is loaded from file system and cached in kernel memory for future use. This is downloaded to DSP using DMA and invoking Load module IPCs
This patch adds support for load/unload module IPCs, DMAing modules and manging the modules
Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-dsp.h | 14 +++ sound/soc/intel/skylake/skl-sst-ipc.c | 53 ++++++++++ sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++ sound/soc/intel/skylake/skl-sst.c | 175 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.c | 29 +++++- 5 files changed, 276 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index f2a69d9e56b3..5d0947935e2b 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -114,6 +114,9 @@ struct skl_dsp_fw_ops { int (*set_state_D0)(struct sst_dsp *ctx); int (*set_state_D3)(struct sst_dsp *ctx); unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); + int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name); + int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); + };
struct skl_dsp_loader_ops { @@ -123,6 +126,17 @@ struct skl_dsp_loader_ops { struct snd_dma_buffer *dmab); };
+struct skl_load_module_info { + u16 mod_id; + const struct firmware *fw; +}; + +struct skl_module_table { + struct skl_load_module_info *mod_info; + unsigned int usage_cnt; + struct list_head list; +}; + void skl_cldma_process_intr(struct sst_dsp *ctx); void skl_cldma_int_disable(struct sst_dsp *ctx); int skl_cldma_prepare(struct sst_dsp *ctx); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 95679c02c6ee..33860d2311c4 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -130,6 +130,11 @@ #define IPC_SRC_QUEUE_MASK 0x7 #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ << IPC_SRC_QUEUE_SHIFT) +/* Load Module count */ +#define IPC_LOAD_MODULE_SHIFT 0 +#define IPC_LOAD_MODULE_MASK 0xFF +#define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \ + << IPC_LOAD_MODULE_SHIFT)
/* Save pipeline messgae extension register */ #define IPC_DMA_ID_SHIFT 0 @@ -728,6 +733,54 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, } EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
+/* + * In order to load a module we need to send IPC to initiate that. DMA will + * performed to load the module memory. The FW supports multiple module load + * at single shot, so we can send IPC with N modules represented by + * module_cnt + */ +int skl_ipc_load_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret; + + header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); + header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, + (sizeof(u16) * module_cnt), NULL, 0); + if (ret < 0) + dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(skl_ipc_load_modules); + +int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, + void *data) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret; + + header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); + header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, + (sizeof(u16) * module_cnt), NULL, 0); + if (ret < 0) + dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(skl_ipc_unload_modules); + int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param) { diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index f1a154e45dc3..e17012778560 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -108,6 +108,12 @@ int skl_ipc_init_instance(struct sst_generic_ipc *sst_ipc, int skl_ipc_bind_unbind(struct sst_generic_ipc *sst_ipc, struct skl_ipc_bind_unbind_msg *msg);
+int skl_ipc_load_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data); + +int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data); + int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx);
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index e1d34d5c3f9a..8cd5cdb21fd5 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -38,6 +38,8 @@ #define SKL_INSTANCE_ID 0 #define SKL_BASE_FW_MODULE_ID 0
+#define SKL_NUM_MODULES 1 + static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status) { u32 cur_sts; @@ -202,11 +204,182 @@ static unsigned int skl_get_errorcode(struct sst_dsp *ctx) return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE); }
+/* + * since get/set_module are called from DAPM context, + * we don't need lock for usage count + */ +static unsigned int skl_get_module(struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return ++module->usage_cnt; + } + + return -EINVAL; +} + +static unsigned int skl_put_module(struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return --module->usage_cnt; + } + + return -EINVAL; +} + +static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx, + char *mod_name, int mod_id) +{ + const struct firmware *fw; + struct skl_module_table *skl_module; + unsigned int size; + int ret; + + ret = request_firmware(&fw, mod_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request Module %s failed :%d\n", + mod_name, ret); + return NULL; + } + + skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL); + if (skl_module == NULL) { + release_firmware(fw); + return NULL; + } + + size = sizeof(*skl_module->mod_info); + skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL); + if (skl_module->mod_info == NULL) { + release_firmware(fw); + return NULL; + } + + skl_module->mod_info->mod_id = mod_id; + skl_module->mod_info->fw = fw; + list_add(&skl_module->list, &ctx->module_list); + + return skl_module; +} + +/* get a module from it's unique ID */ +static struct skl_module_table *skl_module_get_from_id( + struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + if (list_empty(&ctx->module_list)) { + dev_err(ctx->dev, "Module list is empty\n"); + return NULL; + } + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return module; + } + + return NULL; +} + +static int skl_transfer_module(struct sst_dsp *ctx, + struct skl_load_module_info *module) +{ + int ret; + struct skl_sst *skl = ctx->thread_context; + + ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, module->fw->data, + module->fw->size); + if (ret < 0) + return ret; + + ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, + (void *)&module->mod_id); + if (ret < 0) + dev_err(ctx->dev, "Failed to Load module: %d\n", ret); + + ctx->cl_dev.ops.cl_stop_dma(ctx); + + return ret; +} + +static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, char *guid) +{ + struct skl_module_table *module_entry = NULL; + int ret = 0; + char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ + + snprintf(mod_name, sizeof(mod_name), "%s%s%s", + "intel/dsp_fw_", guid, ".bin"); + + module_entry = skl_module_get_from_id(ctx, mod_id); + if (module_entry == NULL) { + module_entry = skl_fill_module_table(ctx, mod_name, mod_id); + if (module_entry == NULL) { + dev_err(ctx->dev, "Failed to Load module\n"); + return -EINVAL; + } + } + + if (!module_entry->usage_cnt) { + ret = skl_transfer_module(ctx, module_entry->mod_info); + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load module\n"); + return ret; + } + } + + ret = skl_get_module(ctx, mod_id); + + return ret; +} + +static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) +{ + unsigned int usage_cnt; + struct skl_sst *skl = ctx->thread_context; + int ret = 0; + + usage_cnt = skl_put_module(ctx, mod_id); + if (usage_cnt < 0) { + dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt); + return -EIO; + } + ret = skl_ipc_unload_modules(&skl->ipc, + SKL_NUM_MODULES, &mod_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to UnLoad module\n"); + skl_get_module(ctx, mod_id); + return ret; + } + + return ret; +} + +static void skl_clear_module_table(struct sst_dsp *ctx) +{ + struct skl_module_table *module, *tmp; + + if (list_empty(&ctx->module_list)) + return; + + list_for_each_entry_safe(module, tmp, &ctx->module_list, list) { + list_del(&module->list); + release_firmware(module->mod_info->fw); + } +} + static struct skl_dsp_fw_ops skl_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 = { @@ -251,6 +424,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 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;
@@ -277,6 +451,7 @@ EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { + skl_clear_module_table(ctx->dsp); skl_ipc_free(&ctx->ipc); ctx->dsp->ops->free(ctx->dsp); } diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index dde8d3c7059a..95b6dd49d6a4 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -26,6 +26,8 @@ #include "skl-topology.h" #include "skl.h" #include "skl-tplg-interface.h" +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h"
#define SKL_CH_FIXUP_MASK (1 << 0) #define SKL_RATE_FIXUP_MASK (1 << 1) @@ -412,6 +414,13 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (!skl_tplg_alloc_pipe_mcps(skl, mconfig)) return -ENOMEM;
+ if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { + ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, + mconfig->id.module_id, mconfig->guid); + if (ret < 0) + return ret; + } + /* * apply fix/conversion to module params based on * FE/BE params @@ -431,6 +440,24 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) return 0; }
+static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, + struct skl_pipe *pipe) +{ + struct skl_pipe_module *w_module = NULL; + struct skl_module_cfg *mconfig = NULL; + + list_for_each_entry(w_module, &pipe->w_list, node) { + mconfig = w_module->w->priv; + + if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod) + return ctx->dsp->fw_ops.unload_mod(ctx->dsp, + mconfig->id.module_id); + } + + /* no modules to unload in this path, so return */ + return 0; +} + /* * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we * need create the pipeline. So we do following: @@ -755,7 +782,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
ret = skl_delete_pipe(ctx, mconfig->pipe);
- return ret; + return skl_tplg_unload_pipe_modules(ctx, s_pipe); }
/*
The patch
ASoC: Intel: Skylake: Add support for Loadable modules
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 6c5768b3aa6f554a719834591ad2c6b4e1291397 Mon Sep 17 00:00:00 2001
From: Dharageswari R dharageswari.r@intel.com Date: Thu, 3 Dec 2015 23:29:50 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Add support for Loadable modules
A module is loaded when the path consisting the module is opened. The module binary(ies) is loaded from file system and cached in kernel memory for future use. This is downloaded to DSP using DMA and invoking Load module IPCs
This patch adds support for load/unload module IPCs, DMAing modules and manging the modules
Signed-off-by: Dharageswari R dharageswari.r@intel.com 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/skylake/skl-sst-dsp.h | 14 +++ sound/soc/intel/skylake/skl-sst-ipc.c | 53 ++++++++++ sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++ sound/soc/intel/skylake/skl-sst.c | 175 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.c | 29 +++++- 5 files changed, 276 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index f2a69d9e56b3..5d0947935e2b 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -114,6 +114,9 @@ struct skl_dsp_fw_ops { int (*set_state_D0)(struct sst_dsp *ctx); int (*set_state_D3)(struct sst_dsp *ctx); unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); + int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name); + int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); + };
struct skl_dsp_loader_ops { @@ -123,6 +126,17 @@ struct skl_dsp_loader_ops { struct snd_dma_buffer *dmab); };
+struct skl_load_module_info { + u16 mod_id; + const struct firmware *fw; +}; + +struct skl_module_table { + struct skl_load_module_info *mod_info; + unsigned int usage_cnt; + struct list_head list; +}; + void skl_cldma_process_intr(struct sst_dsp *ctx); void skl_cldma_int_disable(struct sst_dsp *ctx); int skl_cldma_prepare(struct sst_dsp *ctx); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 95679c02c6ee..33860d2311c4 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -130,6 +130,11 @@ #define IPC_SRC_QUEUE_MASK 0x7 #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ << IPC_SRC_QUEUE_SHIFT) +/* Load Module count */ +#define IPC_LOAD_MODULE_SHIFT 0 +#define IPC_LOAD_MODULE_MASK 0xFF +#define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \ + << IPC_LOAD_MODULE_SHIFT)
/* Save pipeline messgae extension register */ #define IPC_DMA_ID_SHIFT 0 @@ -728,6 +733,54 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, } EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
+/* + * In order to load a module we need to send IPC to initiate that. DMA will + * performed to load the module memory. The FW supports multiple module load + * at single shot, so we can send IPC with N modules represented by + * module_cnt + */ +int skl_ipc_load_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret; + + header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); + header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, + (sizeof(u16) * module_cnt), NULL, 0); + if (ret < 0) + dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(skl_ipc_load_modules); + +int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, + void *data) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret; + + header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); + header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, + (sizeof(u16) * module_cnt), NULL, 0); + if (ret < 0) + dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(skl_ipc_unload_modules); + int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param) { diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index f1a154e45dc3..e17012778560 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -108,6 +108,12 @@ int skl_ipc_init_instance(struct sst_generic_ipc *sst_ipc, int skl_ipc_bind_unbind(struct sst_generic_ipc *sst_ipc, struct skl_ipc_bind_unbind_msg *msg);
+int skl_ipc_load_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data); + +int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, + u8 module_cnt, void *data); + int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx);
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index e1d34d5c3f9a..8cd5cdb21fd5 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -38,6 +38,8 @@ #define SKL_INSTANCE_ID 0 #define SKL_BASE_FW_MODULE_ID 0
+#define SKL_NUM_MODULES 1 + static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status) { u32 cur_sts; @@ -202,11 +204,182 @@ static unsigned int skl_get_errorcode(struct sst_dsp *ctx) return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE); }
+/* + * since get/set_module are called from DAPM context, + * we don't need lock for usage count + */ +static unsigned int skl_get_module(struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return ++module->usage_cnt; + } + + return -EINVAL; +} + +static unsigned int skl_put_module(struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return --module->usage_cnt; + } + + return -EINVAL; +} + +static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx, + char *mod_name, int mod_id) +{ + const struct firmware *fw; + struct skl_module_table *skl_module; + unsigned int size; + int ret; + + ret = request_firmware(&fw, mod_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request Module %s failed :%d\n", + mod_name, ret); + return NULL; + } + + skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL); + if (skl_module == NULL) { + release_firmware(fw); + return NULL; + } + + size = sizeof(*skl_module->mod_info); + skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL); + if (skl_module->mod_info == NULL) { + release_firmware(fw); + return NULL; + } + + skl_module->mod_info->mod_id = mod_id; + skl_module->mod_info->fw = fw; + list_add(&skl_module->list, &ctx->module_list); + + return skl_module; +} + +/* get a module from it's unique ID */ +static struct skl_module_table *skl_module_get_from_id( + struct sst_dsp *ctx, u16 mod_id) +{ + struct skl_module_table *module; + + if (list_empty(&ctx->module_list)) { + dev_err(ctx->dev, "Module list is empty\n"); + return NULL; + } + + list_for_each_entry(module, &ctx->module_list, list) { + if (module->mod_info->mod_id == mod_id) + return module; + } + + return NULL; +} + +static int skl_transfer_module(struct sst_dsp *ctx, + struct skl_load_module_info *module) +{ + int ret; + struct skl_sst *skl = ctx->thread_context; + + ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, module->fw->data, + module->fw->size); + if (ret < 0) + return ret; + + ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, + (void *)&module->mod_id); + if (ret < 0) + dev_err(ctx->dev, "Failed to Load module: %d\n", ret); + + ctx->cl_dev.ops.cl_stop_dma(ctx); + + return ret; +} + +static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, char *guid) +{ + struct skl_module_table *module_entry = NULL; + int ret = 0; + char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ + + snprintf(mod_name, sizeof(mod_name), "%s%s%s", + "intel/dsp_fw_", guid, ".bin"); + + module_entry = skl_module_get_from_id(ctx, mod_id); + if (module_entry == NULL) { + module_entry = skl_fill_module_table(ctx, mod_name, mod_id); + if (module_entry == NULL) { + dev_err(ctx->dev, "Failed to Load module\n"); + return -EINVAL; + } + } + + if (!module_entry->usage_cnt) { + ret = skl_transfer_module(ctx, module_entry->mod_info); + if (ret < 0) { + dev_err(ctx->dev, "Failed to Load module\n"); + return ret; + } + } + + ret = skl_get_module(ctx, mod_id); + + return ret; +} + +static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) +{ + unsigned int usage_cnt; + struct skl_sst *skl = ctx->thread_context; + int ret = 0; + + usage_cnt = skl_put_module(ctx, mod_id); + if (usage_cnt < 0) { + dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt); + return -EIO; + } + ret = skl_ipc_unload_modules(&skl->ipc, + SKL_NUM_MODULES, &mod_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to UnLoad module\n"); + skl_get_module(ctx, mod_id); + return ret; + } + + return ret; +} + +static void skl_clear_module_table(struct sst_dsp *ctx) +{ + struct skl_module_table *module, *tmp; + + if (list_empty(&ctx->module_list)) + return; + + list_for_each_entry_safe(module, tmp, &ctx->module_list, list) { + list_del(&module->list); + release_firmware(module->mod_info->fw); + } +} + static struct skl_dsp_fw_ops skl_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 = { @@ -251,6 +424,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 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;
@@ -277,6 +451,7 @@ EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { + skl_clear_module_table(ctx->dsp); skl_ipc_free(&ctx->ipc); ctx->dsp->ops->free(ctx->dsp); } diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 622f7430e100..32735eff386c 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -26,6 +26,8 @@ #include "skl-topology.h" #include "skl.h" #include "skl-tplg-interface.h" +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h"
#define SKL_CH_FIXUP_MASK (1 << 0) #define SKL_RATE_FIXUP_MASK (1 << 1) @@ -412,6 +414,13 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (!skl_tplg_alloc_pipe_mcps(skl, mconfig)) return -ENOMEM;
+ if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { + ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, + mconfig->id.module_id, mconfig->guid); + if (ret < 0) + return ret; + } + /* * apply fix/conversion to module params based on * FE/BE params @@ -431,6 +440,24 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) return 0; }
+static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, + struct skl_pipe *pipe) +{ + struct skl_pipe_module *w_module = NULL; + struct skl_module_cfg *mconfig = NULL; + + list_for_each_entry(w_module, &pipe->w_list, node) { + mconfig = w_module->w->priv; + + if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod) + return ctx->dsp->fw_ops.unload_mod(ctx->dsp, + mconfig->id.module_id); + } + + /* no modules to unload in this path, so return */ + return 0; +} + /* * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we * need create the pipeline. So we do following: @@ -755,7 +782,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
ret = skl_delete_pipe(ctx, mconfig->pipe);
- return ret; + return skl_tplg_unload_pipe_modules(ctx, s_pipe); }
/*
From: Jeeja KP jeeja.kp@intel.com
A module can require extra memory for processing, like audio algorithms. The memory for these modules needs to be represented in base module configuration and passed to DSP on init, so add the memory pages as a field in widget data
Signed-off-by: Dharageswari.R dharageswari.r@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-messages.c | 1 + sound/soc/intel/skylake/skl-topology.c | 1 + sound/soc/intel/skylake/skl-topology.h | 1 + 3 files changed, 3 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 7770a7e4162f..5297b345839a 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -212,6 +212,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx, base_cfg->cps = mconfig->mcps; base_cfg->ibs = mconfig->ibs; base_cfg->obs = mconfig->obs; + base_cfg->is_pages = mconfig->mem_pages; }
/* diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 95b6dd49d6a4..ad1388e4f847 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1339,6 +1339,7 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, mconfig->converter = dfw_config->converter; mconfig->m_type = dfw_config->module_type; mconfig->vbus_id = dfw_config->vbus_id; + mconfig->mem_pages = dfw_config->mem_pages;
pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe); if (pipe) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 51e785424a37..04318e2091fd 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -277,6 +277,7 @@ struct skl_module_cfg { u32 params_fixup; u32 converter; u32 vbus_id; + u32 mem_pages; struct skl_module_pin *m_in_pin; struct skl_module_pin *m_out_pin; enum skl_module_type m_type;
From: "Dharageswari R" dharageswari.r@intel.com
Mic select is a DSP module which is used to select one or many inputs to form an output. This is useful to select data selectively from PDM input and hence the name. This module is of generic module type.
This patch adds support to add and configure Mic select module in firmware topology.
Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-messages.c | 26 ++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.h | 5 +++++ sound/soc/intel/skylake/skl-tplg-interface.h | 3 ++- 3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 5297b345839a..a91161be7f5d 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -410,6 +410,25 @@ static void skl_set_algo_format(struct skl_sst *ctx,
}
+/* + * Mic select module allows selecting one or many input channels, thus + * acting as a demux. + * + * Mic select module take base module configuration and out-format + * configuration + */ +static void skl_set_base_outfmt_format(struct skl_sst *ctx, + struct skl_module_cfg *mconfig, + struct skl_base_outfmt_cfg *base_outfmt_mcfg) +{ + struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt; + struct skl_base_cfg *base_cfg = + (struct skl_base_cfg *)base_outfmt_mcfg; + + skl_set_base_module_format(ctx, mconfig, base_cfg); + skl_setup_out_format(ctx, mconfig, out_fmt); +} + static u16 skl_get_module_param_size(struct skl_sst *ctx, struct skl_module_cfg *mconfig) { @@ -432,6 +451,9 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, param_size += mconfig->formats_config.caps_size; return param_size;
+ case SKL_MODULE_TYPE_BASE_OUTFMT: + return sizeof(struct skl_base_outfmt_cfg); + default: /* * return only base cfg when no specific module type is @@ -482,6 +504,10 @@ static int skl_set_module_format(struct skl_sst *ctx, skl_set_algo_format(ctx, module_config, *param_data); break;
+ case SKL_MODULE_TYPE_BASE_OUTFMT: + skl_set_base_outfmt_format(ctx, module_config, *param_data); + break; + default: skl_set_base_module_format(ctx, module_config, *param_data); break; diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 04318e2091fd..349f2a3b6613 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -145,6 +145,11 @@ struct skl_algo_cfg { char params[0]; } __packed;
+struct skl_base_outfmt_cfg { + struct skl_base_cfg base_cfg; + struct skl_audio_data_format out_fmt; +} __packed; + enum skl_dma_type { SKL_DMA_HDA_HOST_OUTPUT_CLASS = 0, SKL_DMA_HDA_HOST_INPUT_CLASS = 1, diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 3f1908e3ae80..626b148317fe 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -79,7 +79,8 @@ enum skl_module_type { SKL_MODULE_TYPE_COPIER, SKL_MODULE_TYPE_UPDWMIX, SKL_MODULE_TYPE_SRCINT, - SKL_MODULE_TYPE_ALGO + SKL_MODULE_TYPE_ALGO, + SKL_MODULE_TYPE_BASE_OUTFMT };
enum skl_core_affinity {
From: Jeeja KP jeeja.kp@intel.com
Module initialization parameter data can be set by - INIT_INSTANCE IPC by using the default value - SET_PARAMS immediately after INIT_INSTANCE - SET_PARAMS data from kcontrol values set this patch add param type to identify the parameters has to be sent to DSP.
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-topology.c | 6 +++--- sound/soc/intel/skylake/skl-topology.h | 4 ++-- sound/soc/intel/skylake/skl-tplg-interface.h | 16 +++++++++++----- 3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index ad1388e4f847..d5919d75fee4 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -331,7 +331,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, struct skl_specific_cfg *sp_cfg;
if (mconfig->formats_config.caps_size > 0 && - mconfig->formats_config.set_params) { + mconfig->formats_config.set_params == SKL_PARAM_SET) { sp_cfg = &mconfig->formats_config; ret = skl_set_module_params(ctx, sp_cfg->caps, sp_cfg->caps_size, @@ -346,7 +346,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, sb = (void *) k->private_value; bc = (struct skl_algo_data *)sb->dobj.private;
- if (bc->set_params) { + if (bc->set_params == SKL_PARAM_SET) { ret = skl_set_module_params(ctx, (u32 *)bc->params, bc->max, bc->param_id, mconfig); @@ -379,7 +379,7 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) sb = (struct soc_bytes_ext *)k->private_value; bc = (struct skl_algo_data *)sb->dobj.private;
- if (bc->set_params) + if (bc->set_params != SKL_PARAM_INIT) continue;
mconfig->formats_config.caps = (u32 *)&bc->params; diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 349f2a3b6613..6ba0bdc7753c 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -211,7 +211,7 @@ struct skl_module_pin { };
struct skl_specific_cfg { - bool set_params; + u32 set_params; u32 param_id; u32 caps_size; u32 *caps; @@ -294,7 +294,7 @@ struct skl_module_cfg {
struct skl_algo_data { u32 param_id; - bool set_params; + u32 set_params; u32 max; char *params; }; diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 626b148317fe..c9ae010b3cc8 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -141,6 +141,12 @@ enum module_pin_type { SKL_PIN_TYPE_HETEROGENEOUS, };
+enum skl_module_param_type { + SKL_PARAM_DEFAULT = 0, + SKL_PARAM_INIT, + SKL_PARAM_SET +}; + struct skl_dfw_module_pin { u16 module_id; u16 instance_id; @@ -158,8 +164,8 @@ struct skl_dfw_module_fmt { } __packed;
struct skl_dfw_module_caps { - u32 set_params:1; - u32 rsvd:31; + u32 set_params:2; + u32 rsvd:30; u32 param_id; u32 caps_size; u32 caps[HDA_SST_CFG_MAX]; @@ -214,10 +220,10 @@ struct skl_dfw_module { } __packed;
struct skl_dfw_algo_data { - u32 set_params:1; - u32 rsvd:31; - u32 max; + u32 set_params:2; + u32 rsvd:30; u32 param_id; + u32 max; char params[0]; } __packed;
From: Omair M Abdullah omair.m.abdullah@intel.com
SKL actual mailbox size is 0x10000 and initial values were 0x800, so update these accordingly
Signed-off-by: Omair M Abdullah omair.m.abdullah@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-dsp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 5d0947935e2b..cbb40751c37e 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -58,9 +58,9 @@ struct sst_dsp_device;
#define SKL_ADSP_MMIO_LEN 0x10000
-#define SKL_ADSP_W0_STAT_SZ 0x800 +#define SKL_ADSP_W0_STAT_SZ 0x1000
-#define SKL_ADSP_W0_UP_SZ 0x800 +#define SKL_ADSP_W0_UP_SZ 0x1000
#define SKL_ADSP_W1_SZ 0x1000
From: Mousami Jana mousami.janax@intel.com
For messages which have larger payload than mailbox data, we need to split the payload using set of messages containing mailbox size as payload.
For sending such payload we already support LARGE_CONFIG_SET IPCs and now to query such payload add LARGE_CONFIG_GET IPC
Signed-off-by: Mousami Jana mousami.janax@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-ipc.c | 53 +++++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-sst-ipc.h | 3 ++ 2 files changed, 56 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 33860d2311c4..62e665a3b8f7 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -349,6 +349,8 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, switch (reply) { case IPC_GLB_REPLY_SUCCESS: dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary); + /* copy the rx data from the mailbox */ + sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); break;
case IPC_GLB_REPLY_OUT_OF_MEMORY: @@ -834,3 +836,54 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, return ret; } EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); + +int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, + struct skl_ipc_large_config_msg *msg, u32 *param) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret = 0; + size_t sz_remaining, rx_size, data_offset; + + header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET); + header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); + header.primary |= IPC_MOD_ID(msg->module_id); + + header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); + header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); + header.extension |= IPC_FINAL_BLOCK(1); + header.extension |= IPC_INITIAL_BLOCK(1); + + sz_remaining = msg->param_data_size; + data_offset = 0; + + while (sz_remaining != 0) { + rx_size = sz_remaining > SKL_ADSP_W1_SZ + ? SKL_ADSP_W1_SZ : sz_remaining; + if (rx_size == sz_remaining) + header.extension |= IPC_FINAL_BLOCK(1); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, + ((char *)param) + data_offset, + msg->param_data_size); + if (ret < 0) { + dev_err(ipc->dev, + "ipc: get large config fail, err: %d\n", ret); + return ret; + } + sz_remaining -= rx_size; + data_offset = msg->param_data_size - sz_remaining; + + /* clear the fields */ + header.extension &= IPC_INITIAL_BLOCK_CLEAR; + header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; + /* fill the fields */ + header.extension |= IPC_INITIAL_BLOCK(1); + header.extension |= IPC_DATA_OFFSET_SZ(data_offset); + } + + return ret; +} +EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e17012778560..1bbcdb471cf2 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -120,6 +120,9 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param);
+int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, + struct skl_ipc_large_config_msg *msg, u32 *param); + 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);
From: Omair M Abdullah omair.m.abdullah@intel.com
If a module is ON then we should read the module parameters from DSP rather than driver cached values
Signed-off-by: Omair M Abdullah omair.m.abdullah@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-messages.c | 13 +++++++++++++ sound/soc/intel/skylake/skl-topology.c | 7 +++++++ sound/soc/intel/skylake/skl-topology.h | 2 ++ 3 files changed, 22 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index a91161be7f5d..46310d9ac008 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -927,3 +927,16 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
return skl_ipc_set_large_config(&ctx->ipc, &msg, params); } + +int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg) +{ + struct skl_ipc_large_config_msg msg; + + msg.module_id = mcfg->id.module_id; + msg.instance_id = mcfg->id.instance_id; + msg.param_data_size = size; + msg.large_param_id = param_id; + + return skl_ipc_get_large_config(&ctx->ipc, &msg, params); +} diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index d5919d75fee4..5fb56cb168da 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -908,6 +908,13 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *sb = (struct soc_bytes_ext *)kcontrol->private_value; struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; + struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); + struct skl_module_cfg *mconfig = w->priv; + struct skl *skl = get_skl_ctx(w->dapm->dev); + + if (w->power) + skl_get_module_params(skl->skl_sst, (u32 *)bc->params, + bc->max, bc->param_id, mconfig);
if (bc->params) { if (copy_to_user(data, &bc->param_id, sizeof(u32))) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 6ba0bdc7753c..9aa2a2b6598a 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -342,6 +342,8 @@ int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg
int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg); +int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg);
enum skl_bitdepth skl_get_bit_depth(int params); #endif
The patch
ASoC: Intel: Skylake: read params from DSP if module is on
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 7d9f29119d3e4db6ae817881d8e305650424032c Mon Sep 17 00:00:00 2001
From: Omair M Abdullah omair.m.abdullah@intel.com Date: Thu, 3 Dec 2015 23:29:56 +0530 Subject: [PATCH] ASoC: Intel: Skylake: read params from DSP if module is on
If a module is ON then we should read the module parameters from DSP rather than driver cached values
Signed-off-by: Omair M Abdullah omair.m.abdullah@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-messages.c | 13 +++++++++++++ sound/soc/intel/skylake/skl-topology.c | 7 +++++++ sound/soc/intel/skylake/skl-topology.h | 2 ++ 3 files changed, 22 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index a91161be7f5d..46310d9ac008 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -927,3 +927,16 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
return skl_ipc_set_large_config(&ctx->ipc, &msg, params); } + +int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg) +{ + struct skl_ipc_large_config_msg msg; + + msg.module_id = mcfg->id.module_id; + msg.instance_id = mcfg->id.instance_id; + msg.param_data_size = size; + msg.large_param_id = param_id; + + return skl_ipc_get_large_config(&ctx->ipc, &msg, params); +} diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index eb31235f7040..b824450edcb4 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -908,6 +908,13 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *sb = (struct soc_bytes_ext *)kcontrol->private_value; struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; + struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); + struct skl_module_cfg *mconfig = w->priv; + struct skl *skl = get_skl_ctx(w->dapm->dev); + + if (w->power) + skl_get_module_params(skl->skl_sst, (u32 *)bc->params, + bc->max, bc->param_id, mconfig);
if (bc->params) { if (copy_to_user(data, &bc->param_id, sizeof(u32))) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 6ba0bdc7753c..9aa2a2b6598a 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -342,6 +342,8 @@ int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg
int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg); +int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg);
enum skl_bitdepth skl_get_bit_depth(int params); #endif
From: Jeeja KP jeeja.kp@intel.com
Since in Skylake we support another DAI for DMIC quad capture, add a dailink for this as well. Also specify constrains for DMIC FE devices and fixup for DMIC BEs
Signed-off-by: Dharageswari.R dharageswari.r@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/boards/skl_rt286.c | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 57333a476136..e4fc8a1ce471 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -190,6 +190,42 @@ static struct snd_soc_ops skylake_rt286_ops = { .hw_params = skylake_rt286_hw_params, };
+static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + channels->min = channels->max = 4; + + return 0; +} + +static unsigned int channels_dmic[] = { + 2, 4, +}; + +static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { + .count = ARRAY_SIZE(channels_dmic), + .list = channels_dmic, + .mask = 0, +}; + +static int skylake_dmic_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = 4; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_dmic_channels); + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); +} + +static struct snd_soc_ops skylake_dmic_ops = { + .startup = skylake_dmic_startup, +}; + /* skylake digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link skylake_rt286_dais[] = { /* Front End DAI links */ @@ -238,6 +274,20 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .nonatomic = 1, .dynamic = 1, }, + { + .name = "Skl Audio DMIC cap", + .stream_name = "dmiccap", + .cpu_dai_name = "DMIC Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .init = NULL, + .dpcm_capture = 1, + .ignore_suspend = 1, + .nonatomic = 1, + .dynamic = 1, + .ops = &skylake_dmic_ops, + },
/* Back End DAI links */ { @@ -267,6 +317,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .codec_name = "dmic-codec", .codec_dai_name = "dmic-hifi", .platform_name = "0000:00:1f.3", + .be_hw_params_fixup = skylake_dmic_fixup, .ignore_suspend = 1, .dpcm_capture = 1, .no_pcm = 1,
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/boards/skl_rt286.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index e4fc8a1ce471..0a924901b9b6 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -52,6 +52,7 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_MIC("DMIC2", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), + SND_SOC_DAPM_SINK("WoV Sink"), };
static const struct snd_soc_dapm_route skylake_rt286_map[] = { @@ -69,6 +70,8 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { {"DMIC1 Pin", NULL, "DMIC2"}, {"DMIC AIF", NULL, "SoC DMIC"},
+ {"WoV Sink", NULL, "hwd_in sink"}, + /* CODEC BE connections */ { "AIF1 Playback", NULL, "ssp0 Tx"}, { "ssp0 Tx", NULL, "codec0_out"},
DAPM Machine map for machine was not specifying the paths correctly.
The correct order should be: "DMIC01 Rx" (SoC DMIC BE), connected to "DMIC AIF" (DMic Codec AIF) and then "DMic" (DMic codec Input) connected to "SoC DMIC" (Machine DMIC MIC Widget)
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/boards/skl_rt286.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 0a924901b9b6..51c4eb87e6ec 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -68,7 +68,7 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
/* digital mics */ {"DMIC1 Pin", NULL, "DMIC2"}, - {"DMIC AIF", NULL, "SoC DMIC"}, + {"DMic", NULL, "SoC DMIC"},
{"WoV Sink", NULL, "hwd_in sink"},
@@ -82,7 +82,7 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { { "ssp0 Rx", NULL, "AIF1 Capture" },
{ "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "Capture" }, + { "DMIC01 Rx", NULL, "DMIC AIF" },
{ "hif1", NULL, "iDisp Tx"}, { "iDisp Tx", NULL, "iDisp_out"},
From: Jeeja KP jeeja.kp@intel.com
Some of the usecases can be marked as 'ignore_suspend' by machine. For these on suspend we should keep audio controller ON by saving the state and not suspending the device
For this we need to maintain a counter for these streams and be active on suspend when such a stream is opened.
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-pcm.c | 27 +++++++++++++++++++++++++++ sound/soc/intel/skylake/skl.c | 28 ++++++++++++++++++++++++++-- sound/soc/intel/skylake/skl.h | 2 ++ 3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6570e5753e49..b89ae6f7c096 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -109,6 +109,31 @@ static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *e return HDAC_EXT_STREAM_TYPE_COUPLED; }
+/* + * check if the stream opened is marked as ignore_suspend by machine, if so + * then enable suspend_active refcount + * + * The count supend_active does not need lock as it is used in open/close + * and suspend context + */ +static void skl_set_suspend_active(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, bool enable) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct snd_soc_dapm_widget *w; + struct skl *skl = ebus_to_skl(ebus); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + w = dai->playback_widget; + else + w = dai->capture_widget; + + if (w->ignore_suspend && enable) + skl->supend_active++; + else if (w->ignore_suspend && !enable) + skl->supend_active--; +} + static int skl_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -146,6 +171,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "stream tag set in dma params=%d\n", dma_params->stream_tag); + skl_set_suspend_active(substream, dai, true); snd_pcm_set_sync(substream);
return 0; @@ -257,6 +283,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, * dma_params */ snd_soc_dai_set_dma_data(dai, substream, NULL); + skl_set_suspend_active(substream, dai, false);
kfree(dma_params); } diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index d3e87b6f93fe..2c16325d1ce1 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -169,16 +169,40 @@ static int skl_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_ext_bus *ebus = pci_get_drvdata(pci); + struct skl *skl = ebus_to_skl(ebus);
- return _skl_suspend(ebus); + /* + * Do not suspend if streams which are marked ignore suspend are + * running, we need to save the state for these and continue + */ + if (skl->supend_active) { + pci_save_state(pci); + pci_disable_device(pci); + return 0; + } else { + return _skl_suspend(ebus); + } }
static int skl_resume(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_ext_bus *ebus = pci_get_drvdata(pci); + struct skl *skl = ebus_to_skl(ebus); + int ret;
- return _skl_resume(ebus); + /* + * resume only when we are not in suspend active, otherwise need to + * restore the device + */ + if (skl->supend_active) { + pci_restore_state(pci); + ret = pci_enable_device(pci); + } else { + ret = _skl_resume(ebus); + } + + return ret; } #endif /* CONFIG_PM_SLEEP */
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 774c29cf84dc..3d167eed0f59 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -70,6 +70,8 @@ struct skl { struct list_head ppl_list;
const char *fw_name; + + int supend_active; };
#define skl_to_ebus(s) (&(s)->ebus)
The patch
ASoC: Intel: Skylake: Add support for active suspend
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 4557c305d4fc9356563a1d41fa6fe29e494f0460 Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Thu, 3 Dec 2015 23:30:00 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Add support for active suspend
Some of the usecases can be marked as 'ignore_suspend' by machine. For these on suspend we should keep audio controller ON by saving the state and not suspending the device
For this we need to maintain a counter for these streams and be active on suspend when such a stream is opened.
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/skylake/skl-pcm.c | 27 +++++++++++++++++++++++++++ sound/soc/intel/skylake/skl.c | 28 ++++++++++++++++++++++++++-- sound/soc/intel/skylake/skl.h | 2 ++ 3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6570e5753e49..b89ae6f7c096 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -109,6 +109,31 @@ static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *e return HDAC_EXT_STREAM_TYPE_COUPLED; }
+/* + * check if the stream opened is marked as ignore_suspend by machine, if so + * then enable suspend_active refcount + * + * The count supend_active does not need lock as it is used in open/close + * and suspend context + */ +static void skl_set_suspend_active(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, bool enable) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); + struct snd_soc_dapm_widget *w; + struct skl *skl = ebus_to_skl(ebus); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + w = dai->playback_widget; + else + w = dai->capture_widget; + + if (w->ignore_suspend && enable) + skl->supend_active++; + else if (w->ignore_suspend && !enable) + skl->supend_active--; +} + static int skl_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -146,6 +171,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "stream tag set in dma params=%d\n", dma_params->stream_tag); + skl_set_suspend_active(substream, dai, true); snd_pcm_set_sync(substream);
return 0; @@ -257,6 +283,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, * dma_params */ snd_soc_dai_set_dma_data(dai, substream, NULL); + skl_set_suspend_active(substream, dai, false);
kfree(dma_params); } diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index d3e87b6f93fe..2c16325d1ce1 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -169,16 +169,40 @@ static int skl_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_ext_bus *ebus = pci_get_drvdata(pci); + struct skl *skl = ebus_to_skl(ebus);
- return _skl_suspend(ebus); + /* + * Do not suspend if streams which are marked ignore suspend are + * running, we need to save the state for these and continue + */ + if (skl->supend_active) { + pci_save_state(pci); + pci_disable_device(pci); + return 0; + } else { + return _skl_suspend(ebus); + } }
static int skl_resume(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_ext_bus *ebus = pci_get_drvdata(pci); + struct skl *skl = ebus_to_skl(ebus); + int ret;
- return _skl_resume(ebus); + /* + * resume only when we are not in suspend active, otherwise need to + * restore the device + */ + if (skl->supend_active) { + pci_restore_state(pci); + ret = pci_enable_device(pci); + } else { + ret = _skl_resume(ebus); + } + + return ret; } #endif /* CONFIG_PM_SLEEP */
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 774c29cf84dc..3d167eed0f59 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -70,6 +70,8 @@ struct skl { struct list_head ppl_list;
const char *fw_name; + + int supend_active; };
#define skl_to_ebus(s) (&(s)->ebus)
From: Praveen Diwakar praveen.diwakar@intel.com
We should only add ignore suspend flag for some DAIs and not all. This patches removes it from the DAIs where we do not support this
It also marks the endpoints for which ignore_suspend should be enabled
Signed-off-by: Praveen Diwakar praveen.diwakar@intel.com Signed-off-by: Vunny Sodhi vunnyx.sodhi@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/boards/skl_rt286.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 51c4eb87e6ec..7396ddb427d8 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -89,6 +89,17 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
};
+static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dapm_context *dapm; + struct snd_soc_component *component = rtd->cpu_dai->component; + + dapm = snd_soc_component_get_dapm(component); + snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); + + return 0; +} + static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -104,6 +115,9 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
rt286_mic_detect(codec, &skylake_headset);
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); + snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink"); + return 0; }
@@ -241,6 +255,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .dynamic = 1, .codec_name = "snd-soc-dummy", .codec_dai_name = "snd-soc-dummy-dai", + .init = skylake_rt286_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST @@ -286,7 +301,6 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, - .ignore_suspend = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, @@ -306,7 +320,6 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp0_fixup, .ops = &skylake_rt286_ops,
The patch
ASoC: Intel: Skylake: Update ignore suspend for rt286 machine
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 9ec2053b13f75d7ad9c0e6db9763954bd1a1b9ae Mon Sep 17 00:00:00 2001
From: Praveen Diwakar praveen.diwakar@intel.com Date: Thu, 3 Dec 2015 23:30:01 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine
We should only add ignore suspend flag for some DAIs and not all. This patches removes it from the DAIs where we do not support this
It also marks the endpoints for which ignore_suspend should be enabled
Signed-off-by: Praveen Diwakar praveen.diwakar@intel.com Signed-off-by: Vunny Sodhi vunnyx.sodhi@intel.com 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/boards/skl_rt286.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 51c4eb87e6ec..7396ddb427d8 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -89,6 +89,17 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
};
+static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dapm_context *dapm; + struct snd_soc_component *component = rtd->cpu_dai->component; + + dapm = snd_soc_component_get_dapm(component); + snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); + + return 0; +} + static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -104,6 +115,9 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
rt286_mic_detect(codec, &skylake_headset);
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); + snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink"); + return 0; }
@@ -241,6 +255,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .dynamic = 1, .codec_name = "snd-soc-dummy", .codec_dai_name = "snd-soc-dummy-dai", + .init = skylake_rt286_fe_init, .trigger = { SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST @@ -286,7 +301,6 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .platform_name = "0000:00:1f.3", .init = NULL, .dpcm_capture = 1, - .ignore_suspend = 1, .nonatomic = 1, .dynamic = 1, .ops = &skylake_dmic_ops, @@ -306,7 +320,6 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, - .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = skylake_ssp0_fixup, .ops = &skylake_rt286_ops,
participants (2)
-
Mark Brown
-
Vinod Koul