All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules
@ 2015-12-03 17:59 Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules Vinod Koul
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel; +Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul


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(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Add support for Loadable modules" to the asoc tree Mark Brown
  2015-12-03 17:59 ` [PATCH v2 02/12] ASoC: Intel: Skylake: Add memory pages to widget data Vinod Koul
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: Dharageswari R, patches.audio, liam.r.girdwood, Vinod Koul,
	broonie, Jeeja KP

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);
 }
 
 /*
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 02/12] ASoC: Intel: Skylake: Add memory pages to widget data.
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 03/12] ASoC: Intel: Skylake: Add support for Mic Select module Vinod Koul
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: Dharageswari.R, patches.audio, liam.r.girdwood, Vinod Koul,
	broonie, Jeeja KP

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;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 03/12] ASoC: Intel: Skylake: Add support for Mic Select module
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 02/12] ASoC: Intel: Skylake: Add memory pages to widget data Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 04/12] ASoC: Intel: Skylake: Fix module init data correctly Vinod Koul
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: Dharageswari R, patches.audio, liam.r.girdwood, Vinod Koul,
	broonie, Jeeja KP

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 {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 04/12] ASoC: Intel: Skylake: Fix module init data correctly
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (2 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 03/12] ASoC: Intel: Skylake: Add support for Mic Select module Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 05/12] ASoC: Intel: Skylake: update mailbox uplink window offset and size Vinod Koul
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel; +Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Jeeja KP

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;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 05/12] ASoC: Intel: Skylake: update mailbox uplink window offset and size
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (3 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 04/12] ASoC: Intel: Skylake: Fix module init data correctly Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 06/12] ASoC: Intel: Skylake: add LARGE_CONFIG_GET IPC support Vinod Koul
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Omair M Abdullah

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
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 06/12] ASoC: Intel: Skylake: add LARGE_CONFIG_GET IPC support
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (4 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 05/12] ASoC: Intel: Skylake: update mailbox uplink window offset and size Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 07/12] ASoC: Intel: Skylake: read params from DSP if module is on Vinod Koul
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: liam.r.girdwood, patches.audio, broonie, Mousami Jana, Vinod Koul

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);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 07/12] ASoC: Intel: Skylake: read params from DSP if module is on
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (5 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 06/12] ASoC: Intel: Skylake: add LARGE_CONFIG_GET IPC support Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: read params from DSP if module is on" to the asoc tree Mark Brown
  2015-12-03 17:59 ` [PATCH v2 08/12] ASoC: Intel: Skylake: Add dai link for DMIC capture Vinod Koul
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Omair M Abdullah

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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 08/12] ASoC: Intel: Skylake: Add dai link for DMIC capture
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (6 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 07/12] ASoC: Intel: Skylake: read params from DSP if module is on Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 09/12] ASoC: Intel: Skylake: add wov as int sink Vinod Koul
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel
  Cc: Dharageswari.R, patches.audio, liam.r.girdwood, Vinod Koul,
	broonie, Jeeja KP

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,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 09/12] ASoC: Intel: Skylake: add wov as int sink
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (7 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 08/12] ASoC: Intel: Skylake: Add dai link for DMIC capture Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 17:59 ` [PATCH v2 10/12] ASoc: Intel: Skylake: Fix the dapm machine map Vinod Koul
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel; +Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Jeeja KP

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"},
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 10/12] ASoc: Intel: Skylake: Fix the dapm machine map
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (8 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 09/12] ASoC: Intel: Skylake: add wov as int sink Vinod Koul
@ 2015-12-03 17:59 ` Vinod Koul
  2015-12-03 18:00 ` [PATCH v2 11/12] ASoC: Intel: Skylake: Add support for active suspend Vinod Koul
  2015-12-03 18:00 ` [PATCH v2 12/12] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine Vinod Koul
  11 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 17:59 UTC (permalink / raw)
  To: alsa-devel; +Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Jeeja KP

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"},
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 11/12] ASoC: Intel: Skylake: Add support for active suspend
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (9 preceding siblings ...)
  2015-12-03 17:59 ` [PATCH v2 10/12] ASoc: Intel: Skylake: Fix the dapm machine map Vinod Koul
@ 2015-12-03 18:00 ` Vinod Koul
  2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Add support for active suspend" to the asoc tree Mark Brown
  2015-12-03 18:00 ` [PATCH v2 12/12] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine Vinod Koul
  11 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 18:00 UTC (permalink / raw)
  To: alsa-devel; +Cc: liam.r.girdwood, patches.audio, broonie, Vinod Koul, Jeeja KP

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)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 12/12] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine
  2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
                   ` (10 preceding siblings ...)
  2015-12-03 18:00 ` [PATCH v2 11/12] ASoC: Intel: Skylake: Add support for active suspend Vinod Koul
@ 2015-12-03 18:00 ` Vinod Koul
  2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Update ignore suspend for rt286 machine" to the asoc tree Mark Brown
  11 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2015-12-03 18:00 UTC (permalink / raw)
  To: alsa-devel
  Cc: patches.audio, Praveen Diwakar, liam.r.girdwood, Vinod Koul,
	broonie, Vunny Sodhi, Jeeja KP

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,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Applied "ASoC: Intel: Skylake: Update ignore suspend for rt286 machine" to the asoc tree
  2015-12-03 18:00 ` [PATCH v2 12/12] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine Vinod Koul
@ 2015-12-08 19:11   ` Mark Brown
  0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2015-12-08 19:11 UTC (permalink / raw)
  To: Praveen Diwakar, Vunny Sodhi, Jeeja KP, Vinod Koul, Mark Brown; +Cc: alsa-devel

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,
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Applied "ASoC: Intel: Skylake: Add support for active suspend" to the asoc tree
  2015-12-03 18:00 ` [PATCH v2 11/12] ASoC: Intel: Skylake: Add support for active suspend Vinod Koul
@ 2015-12-08 19:11   ` Mark Brown
  0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2015-12-08 19:11 UTC (permalink / raw)
  To: Jeeja KP, Vinod Koul, Mark Brown; +Cc: alsa-devel

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)
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Applied "ASoC: Intel: Skylake: read params from DSP if module is on" to the asoc tree
  2015-12-03 17:59 ` [PATCH v2 07/12] ASoC: Intel: Skylake: read params from DSP if module is on Vinod Koul
@ 2015-12-08 19:11   ` Mark Brown
  0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2015-12-08 19:11 UTC (permalink / raw)
  To: Omair M Abdullah, Vinod Koul, Mark Brown; +Cc: alsa-devel

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
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Applied "ASoC: Intel: Skylake: Add support for Loadable modules" to the asoc tree
  2015-12-03 17:59 ` [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules Vinod Koul
@ 2015-12-08 19:11   ` Mark Brown
  0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2015-12-08 19:11 UTC (permalink / raw)
  To: Dharageswari R, Jeeja KP, Vinod Koul, Mark Brown; +Cc: alsa-devel

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);
 }
 
 /*
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-12-08 19:11 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-03 17:59 [PATCH v2 00/12] ASoC: Intel: Skylake: Add support for loadable modules Vinod Koul
2015-12-03 17:59 ` [PATCH v2 01/12] ASoC: Intel: Skylake: Add support for Loadable modules Vinod Koul
2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Add support for Loadable modules" to the asoc tree Mark Brown
2015-12-03 17:59 ` [PATCH v2 02/12] ASoC: Intel: Skylake: Add memory pages to widget data Vinod Koul
2015-12-03 17:59 ` [PATCH v2 03/12] ASoC: Intel: Skylake: Add support for Mic Select module Vinod Koul
2015-12-03 17:59 ` [PATCH v2 04/12] ASoC: Intel: Skylake: Fix module init data correctly Vinod Koul
2015-12-03 17:59 ` [PATCH v2 05/12] ASoC: Intel: Skylake: update mailbox uplink window offset and size Vinod Koul
2015-12-03 17:59 ` [PATCH v2 06/12] ASoC: Intel: Skylake: add LARGE_CONFIG_GET IPC support Vinod Koul
2015-12-03 17:59 ` [PATCH v2 07/12] ASoC: Intel: Skylake: read params from DSP if module is on Vinod Koul
2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: read params from DSP if module is on" to the asoc tree Mark Brown
2015-12-03 17:59 ` [PATCH v2 08/12] ASoC: Intel: Skylake: Add dai link for DMIC capture Vinod Koul
2015-12-03 17:59 ` [PATCH v2 09/12] ASoC: Intel: Skylake: add wov as int sink Vinod Koul
2015-12-03 17:59 ` [PATCH v2 10/12] ASoc: Intel: Skylake: Fix the dapm machine map Vinod Koul
2015-12-03 18:00 ` [PATCH v2 11/12] ASoC: Intel: Skylake: Add support for active suspend Vinod Koul
2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Add support for active suspend" to the asoc tree Mark Brown
2015-12-03 18:00 ` [PATCH v2 12/12] ASoC: Intel: Skylake: Update ignore suspend for rt286 machine Vinod Koul
2015-12-08 19:11   ` Applied "ASoC: Intel: Skylake: Update ignore suspend for rt286 machine" to the asoc tree Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.