All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ASoC: SOF: control/topology improvements
@ 2019-06-12 17:01 Pierre-Louis Bossart
  2019-06-12 17:01 ` [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table Pierre-Louis Bossart
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Pierre-Louis Bossart @ 2019-06-12 17:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Pierre-Louis Bossart

3 patches to improve volume handling and DMIC unmute, plus a
long-overdue one to avoid waking-up the DSP when reading from a
kcontrol cached value.

Bard Liao (1):
  ASoC: SOF: dont wake dsp up in kcontrol IO

Seppo Ingalsuo (1):
  ASoC: SOF: Add DMIC token for unmute gain ramp time

Zhu Yingjiang (2):
  ASoC: SOF: topology: add min/max step for volume_table
  ASoC: SOF: topology: pass volume min/max linear value to FW

 include/sound/sof/dai-intel.h   |   3 +-
 include/uapi/sound/sof/abi.h    |   2 +-
 include/uapi/sound/sof/tokens.h |   1 +
 sound/soc/sof/control.c         | 270 +++++---------------------------
 sound/soc/sof/sof-priv.h        |   2 +
 sound/soc/sof/topology.c        |  68 ++++++++
 6 files changed, 112 insertions(+), 234 deletions(-)

-- 
2.20.1

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

* [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table
  2019-06-12 17:01 [PATCH 0/4] ASoC: SOF: control/topology improvements Pierre-Louis Bossart
@ 2019-06-12 17:01 ` Pierre-Louis Bossart
  2019-06-13 19:06   ` Applied "ASoC: SOF: topology: add min/max step for volume_table" to the asoc tree Mark Brown
  2019-06-12 17:01 ` [PATCH 2/4] ASoC: SOF: topology: pass volume min/max linear value to FW Pierre-Louis Bossart
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Pierre-Louis Bossart @ 2019-06-12 17:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Zhu Yingjiang, Pierre-Louis Bossart

From: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>

add two units min_volume_step and max_volume_step to the snd_sof_control
struct, for the min and max step of the volume_table.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/sof-priv.h | 2 ++
 sound/soc/sof/topology.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 563623bcaad6..d2dbca7d57d1 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -297,6 +297,8 @@ struct snd_sof_pcm {
 struct snd_sof_control {
 	struct snd_sof_dev *sdev;
 	int comp_id;
+	int min_volume_step; /* min volume step for volume_table */
+	int max_volume_step; /* max volume step for volume_table */
 	int num_channels;
 	u32 readback_offset; /* offset to mmaped data if used */
 	struct sof_ipc_ctrl_data *control_data;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index a13233ae6d0e..1c661dec8dd4 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -451,6 +451,8 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
 		return -ENOMEM;
 
 	scontrol->comp_id = sdev->next_comp_id;
+	scontrol->min_volume_step = le32_to_cpu(mc->min);
+	scontrol->max_volume_step = le32_to_cpu(mc->max);
 	scontrol->num_channels = le32_to_cpu(mc->num_channels);
 
 	/* set cmd for mixer control */
-- 
2.20.1

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

* [PATCH 2/4] ASoC: SOF: topology: pass volume min/max linear value to FW
  2019-06-12 17:01 [PATCH 0/4] ASoC: SOF: control/topology improvements Pierre-Louis Bossart
  2019-06-12 17:01 ` [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table Pierre-Louis Bossart
@ 2019-06-12 17:01 ` Pierre-Louis Bossart
  2019-06-13 19:05   ` Applied "ASoC: SOF: topology: pass volume min/max linear value to FW" to the asoc tree Mark Brown
  2019-06-12 17:01 ` [PATCH 3/4] ASoC: SOF: Add DMIC token for unmute gain ramp time Pierre-Louis Bossart
  2019-06-12 17:01 ` [PATCH 4/4] ASoC: SOF: dont wake dsp up in kcontrol IO Pierre-Louis Bossart
  3 siblings, 1 reply; 9+ messages in thread
From: Pierre-Louis Bossart @ 2019-06-12 17:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Zhu Yingjiang, Pierre-Louis Bossart

From: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>

The driver currently passes the volume ramp type and length
topology tokens to firmware, but the min and max volume are
not set. This patch provides a correction to convert the
information from the topology file and pass the linear volume
min/max value to the firmware to improve transitions.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/topology.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 1c661dec8dd4..bbad8053b1bc 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1552,6 +1552,9 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index,
 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
 	struct snd_soc_tplg_private *private = &tw->priv;
 	struct sof_ipc_comp_volume *volume;
+	struct snd_sof_control *scontrol;
+	int min_step;
+	int max_step;
 	int ret;
 
 	volume = kzalloc(sizeof(*volume), GFP_KERNEL);
@@ -1594,6 +1597,17 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index,
 
 	swidget->private = volume;
 
+	list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
+		if (scontrol->comp_id == swidget->comp_id) {
+			min_step = scontrol->min_volume_step;
+			max_step = scontrol->max_volume_step;
+			volume->min_value = scontrol->volume_table[min_step];
+			volume->max_value = scontrol->volume_table[max_step];
+			volume->channels = scontrol->num_channels;
+			break;
+		}
+	}
+
 	ret = sof_ipc_tx_message(sdev->ipc, volume->comp.hdr.cmd, volume,
 				 sizeof(*volume), r, sizeof(*r));
 	if (ret >= 0)
-- 
2.20.1

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

* [PATCH 3/4] ASoC: SOF: Add DMIC token for unmute gain ramp time
  2019-06-12 17:01 [PATCH 0/4] ASoC: SOF: control/topology improvements Pierre-Louis Bossart
  2019-06-12 17:01 ` [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table Pierre-Louis Bossart
  2019-06-12 17:01 ` [PATCH 2/4] ASoC: SOF: topology: pass volume min/max linear value to FW Pierre-Louis Bossart
@ 2019-06-12 17:01 ` Pierre-Louis Bossart
  2019-06-13 19:05   ` Applied "ASoC: SOF: Add DMIC token for unmute gain ramp time" to the asoc tree Mark Brown
  2019-06-12 17:01 ` [PATCH 4/4] ASoC: SOF: dont wake dsp up in kcontrol IO Pierre-Louis Bossart
  3 siblings, 1 reply; 9+ messages in thread
From: Pierre-Louis Bossart @ 2019-06-12 17:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Pierre-Louis Bossart, Seppo Ingalsuo

From: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>

The settling time of DMIC DC level is both platform and used
microphone model specific. The unmute gain ramp is used to conceal
most of the large DC level seen in beginning of capture. This patch
adds into the DMIC DAI IPC struct a new field called unmute_ramp_time
and a new token SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME. The value is the
ramp length in milliseconds (ms).

The ABI minor version is incremented for this backwards compatible
change.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/sof/dai-intel.h   | 3 ++-
 include/uapi/sound/sof/abi.h    | 2 +-
 include/uapi/sound/sof/tokens.h | 1 +
 sound/soc/sof/topology.c        | 4 ++++
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h
index 4bd83f7adddf..4bb8ee138ba7 100644
--- a/include/sound/sof/dai-intel.h
+++ b/include/sound/sof/dai-intel.h
@@ -167,9 +167,10 @@ struct sof_ipc_dai_dmic_params {
 
 	uint32_t wake_up_time;      /**< Time from clock start to data (us) */
 	uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */
+	uint32_t unmute_ramp_time;  /**< Length of logarithmic gain ramp (ms) */
 
 	/* reserved for future use */
-	uint32_t reserved[6];
+	uint32_t reserved[5];
 
 	/**< variable number of pdm controller config */
 	struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h
index 92eee681bc62..4a9c24434f42 100644
--- a/include/uapi/sound/sof/abi.h
+++ b/include/uapi/sound/sof/abi.h
@@ -26,7 +26,7 @@
 
 /* SOF ABI version major, minor and patch numbers */
 #define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 7
+#define SOF_ABI_MINOR 8
 #define SOF_ABI_PATCH 0
 
 /* SOF ABI version number. Format within 32bit word is MMmmmppp */
diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h
index 53ea94bf1c08..dc1b27daaac6 100644
--- a/include/uapi/sound/sof/tokens.h
+++ b/include/uapi/sound/sof/tokens.h
@@ -85,6 +85,7 @@
 #define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE	605
 #define SOF_TKN_INTEL_DMIC_SAMPLE_RATE		608
 #define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH	609
+#define SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS  610
 
 /* DMIC PDM */
 #define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID		700
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index bbad8053b1bc..8e00f829bfdb 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -779,6 +779,10 @@ static const struct sof_topology_token dmic_tokens[] = {
 	{SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH,
 		SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
 		offsetof(struct sof_ipc_dai_dmic_params, fifo_bits), 0},
+	{SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS,
+		SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+		offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time), 0},
+
 };
 
 /*
-- 
2.20.1

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

* [PATCH 4/4] ASoC: SOF: dont wake dsp up in kcontrol IO
  2019-06-12 17:01 [PATCH 0/4] ASoC: SOF: control/topology improvements Pierre-Louis Bossart
                   ` (2 preceding siblings ...)
  2019-06-12 17:01 ` [PATCH 3/4] ASoC: SOF: Add DMIC token for unmute gain ramp time Pierre-Louis Bossart
@ 2019-06-12 17:01 ` Pierre-Louis Bossart
  2019-06-13 19:05   ` Applied "ASoC: SOF: dont wake dsp up in kcontrol IO" to the asoc tree Mark Brown
  3 siblings, 1 reply; 9+ messages in thread
From: Pierre-Louis Bossart @ 2019-06-12 17:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Bard Liao, Pierre-Louis Bossart

From: Bard Liao <yung-chuan.liao@linux.intel.com>

Always get kcontrol value from cache, set kcontrol value to DSP
when DSP is active. Kcontrol values will be restored when DSP boot up.
We will set the default value of kcontrol in sof_complete to make sure
the value is align with firmware.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/control.c  | 270 ++++++---------------------------------
 sound/soc/sof/topology.c |  48 +++++++
 2 files changed, 86 insertions(+), 232 deletions(-)

diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c
index 84e2cbfbbcbb..a4983f90ff5b 100644
--- a/sound/soc/sof/control.c
+++ b/sound/soc/sof/control.c
@@ -39,26 +39,8 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *sm =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = sm->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the mixer data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_VOLUME,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
@@ -66,12 +48,6 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
 			ipc_to_mixer(cdata->chanv[i].value,
 				     scontrol->volume_table, sm->max + 1);
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -84,16 +60,6 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -104,18 +70,13 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of mixer updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_VOLUME,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_VOLUME,
+					      true);
+
 	return 0;
 }
 
@@ -125,37 +86,13 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *sm =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = sm->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the mixer data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_SWITCH,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
 		ucontrol->value.integer.value[i] = cdata->chanv[i].value;
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -168,16 +105,6 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -186,18 +113,13 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of mixer updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_SWITCH,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_SWITCH,
+					      true);
+
 	return 0;
 }
 
@@ -207,37 +129,13 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
 	struct soc_enum *se =
 		(struct soc_enum *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = se->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the enum data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_ENUM,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
 		ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -250,16 +148,6 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -268,18 +156,13 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of enum updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_ENUM,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_ENUM,
+					      true);
+
 	return 0;
 }
 
@@ -293,7 +176,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	struct sof_abi_hdr *data = cdata->data;
 	size_t size;
-	int ret, err;
+	int ret = 0;
 
 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
 		dev_err_ratelimited(sdev->dev,
@@ -302,22 +185,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the binary data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_DATA,
-				      SOF_CTRL_TYPE_DATA_GET,
-				      scontrol->cmd,
-				      false);
-
 	size = data->size + sizeof(*data);
 	if (size > be->max) {
 		dev_err_ratelimited(sdev->dev,
@@ -331,12 +198,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 	memcpy(ucontrol->value.bytes.data, data, size);
 
 out:
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes get failed to idle %d\n",
-				    err);
 	return ret;
 }
 
@@ -350,7 +211,6 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	struct sof_abi_hdr *data = cdata->data;
 	size_t size = data->size + sizeof(*data);
-	int ret, err;
 
 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
 		dev_err_ratelimited(sdev->dev,
@@ -366,32 +226,18 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
 	/* copy from kcontrol */
 	memcpy(data, ucontrol->value.bytes.data, size);
 
 	/* notify DSP of byte control updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_DATA,
-				      SOF_CTRL_TYPE_DATA_SET,
-				      scontrol->cmd,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes put failed to idle %d\n",
-				    err);
-	return ret;
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_DATA,
+					      SOF_CTRL_TYPE_DATA_SET,
+					      scontrol->cmd,
+					      true);
+
+	return 0;
 }
 
 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
@@ -406,8 +252,6 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_tlv header;
 	const struct snd_ctl_tlv __user *tlvd =
 		(const struct snd_ctl_tlv __user *)binary_data;
-	int ret;
-	int err;
 
 	/*
 	 * The beginning of bytes data contains a header from where
@@ -453,30 +297,15 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
 	/* notify DSP of byte control updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_DATA,
-				      SOF_CTRL_TYPE_DATA_SET,
-				      scontrol->cmd,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_DATA,
+					      SOF_CTRL_TYPE_DATA_SET,
+					      scontrol->cmd,
+					      true);
 
-	return ret;
+	return 0;
 }
 
 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
@@ -492,17 +321,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_tlv __user *tlvd =
 		(struct snd_ctl_tlv __user *)binary_data;
 	int data_size;
-	int err;
-	int ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
+	int ret = 0;
 
 	/*
 	 * Decrement the limit by ext bytes header size to
@@ -514,13 +333,6 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 	cdata->data->magic = SOF_ABI_MAGIC;
 	cdata->data->abi = SOF_ABI_VERSION;
 
-	/* get all the component data from DSP */
-	ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-					    SOF_IPC_COMP_GET_DATA,
-					    SOF_CTRL_TYPE_DATA_GET,
-					    scontrol->cmd,
-					    false);
-
 	/* Prevent read of other kernel data or possibly corrupt response */
 	data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
 
@@ -543,11 +355,5 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 		ret = -EFAULT;
 
 out:
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext get failed to idle %d\n",
-				    err);
 	return ret;
 }
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 8e00f829bfdb..aaf459af89d0 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -3016,6 +3016,49 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
 	return ret;
 }
 
+/* Function to set the initial value of SOF kcontrols.
+ * The value will be stored in scontrol->control_data
+ */
+static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev)
+{
+	struct snd_sof_control *scontrol = NULL;
+	int ipc_cmd, ctrl_type;
+	int ret = 0;
+
+	list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
+
+		/* notify DSP of kcontrol values */
+		switch (scontrol->cmd) {
+		case SOF_CTRL_CMD_VOLUME:
+		case SOF_CTRL_CMD_ENUM:
+		case SOF_CTRL_CMD_SWITCH:
+			ipc_cmd = SOF_IPC_COMP_GET_VALUE;
+			ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET;
+			break;
+		case SOF_CTRL_CMD_BINARY:
+			ipc_cmd = SOF_IPC_COMP_GET_DATA;
+			ctrl_type = SOF_CTRL_TYPE_DATA_GET;
+			break;
+		default:
+			dev_err(sdev->dev,
+				"error: Invalid scontrol->cmd: %d\n",
+				scontrol->cmd);
+			return -EINVAL;
+		}
+		ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+						    ipc_cmd, ctrl_type,
+						    scontrol->cmd,
+						    false);
+		if (ret < 0) {
+			dev_warn(sdev->dev,
+				"error: kcontrol value get for widget: %d\n",
+				scontrol->comp_id);
+		}
+	}
+
+	return ret;
+}
+
 int snd_sof_complete_pipeline(struct snd_sof_dev *sdev,
 			      struct snd_sof_widget *swidget)
 {
@@ -3059,6 +3102,11 @@ static void sof_complete(struct snd_soc_component *scomp)
 			break;
 		}
 	}
+	/*
+	 * cache initial values of SOF kcontrols by reading DSP value over
+	 * IPC. It may be overwritten by alsa-mixer after booting up
+	 */
+	snd_sof_cache_kcontrol_val(sdev);
 }
 
 /* manifest - optional to inform component of manifest */
-- 
2.20.1

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

* Applied "ASoC: SOF: Add DMIC token for unmute gain ramp time" to the asoc tree
  2019-06-12 17:01 ` [PATCH 3/4] ASoC: SOF: Add DMIC token for unmute gain ramp time Pierre-Louis Bossart
@ 2019-06-13 19:05   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2019-06-13 19:05 UTC (permalink / raw)
  To: Seppo Ingalsuo; +Cc: tiwai, alsa-devel, Mark Brown, Pierre-Louis Bossart

The patch

   ASoC: SOF: Add DMIC token for unmute gain ramp time

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.3

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 7df43911e92aa2137ae77ae60efaa9d6656df3fe Mon Sep 17 00:00:00 2001
From: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Date: Wed, 12 Jun 2019 12:01:47 -0500
Subject: [PATCH] ASoC: SOF: Add DMIC token for unmute gain ramp time

The settling time of DMIC DC level is both platform and used
microphone model specific. The unmute gain ramp is used to conceal
most of the large DC level seen in beginning of capture. This patch
adds into the DMIC DAI IPC struct a new field called unmute_ramp_time
and a new token SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME. The value is the
ramp length in milliseconds (ms).

The ABI minor version is incremented for this backwards compatible
change.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/sof/dai-intel.h   | 3 ++-
 include/uapi/sound/sof/abi.h    | 2 +-
 include/uapi/sound/sof/tokens.h | 1 +
 sound/soc/sof/topology.c        | 4 ++++
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h
index 4bd83f7adddf..4bb8ee138ba7 100644
--- a/include/sound/sof/dai-intel.h
+++ b/include/sound/sof/dai-intel.h
@@ -167,9 +167,10 @@ struct sof_ipc_dai_dmic_params {
 
 	uint32_t wake_up_time;      /**< Time from clock start to data (us) */
 	uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */
+	uint32_t unmute_ramp_time;  /**< Length of logarithmic gain ramp (ms) */
 
 	/* reserved for future use */
-	uint32_t reserved[6];
+	uint32_t reserved[5];
 
 	/**< variable number of pdm controller config */
 	struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h
index 92eee681bc62..4a9c24434f42 100644
--- a/include/uapi/sound/sof/abi.h
+++ b/include/uapi/sound/sof/abi.h
@@ -26,7 +26,7 @@
 
 /* SOF ABI version major, minor and patch numbers */
 #define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 7
+#define SOF_ABI_MINOR 8
 #define SOF_ABI_PATCH 0
 
 /* SOF ABI version number. Format within 32bit word is MMmmmppp */
diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h
index 53ea94bf1c08..dc1b27daaac6 100644
--- a/include/uapi/sound/sof/tokens.h
+++ b/include/uapi/sound/sof/tokens.h
@@ -85,6 +85,7 @@
 #define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE	605
 #define SOF_TKN_INTEL_DMIC_SAMPLE_RATE		608
 #define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH	609
+#define SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS  610
 
 /* DMIC PDM */
 #define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID		700
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index bbad8053b1bc..8e00f829bfdb 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -779,6 +779,10 @@ static const struct sof_topology_token dmic_tokens[] = {
 	{SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH,
 		SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
 		offsetof(struct sof_ipc_dai_dmic_params, fifo_bits), 0},
+	{SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS,
+		SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+		offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time), 0},
+
 };
 
 /*
-- 
2.20.1

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

* Applied "ASoC: SOF: dont wake dsp up in kcontrol IO" to the asoc tree
  2019-06-12 17:01 ` [PATCH 4/4] ASoC: SOF: dont wake dsp up in kcontrol IO Pierre-Louis Bossart
@ 2019-06-13 19:05   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2019-06-13 19:05 UTC (permalink / raw)
  To: Bard Liao; +Cc: tiwai, alsa-devel, Mark Brown, Pierre-Louis Bossart

The patch

   ASoC: SOF: dont wake dsp up in kcontrol IO

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.3

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 0c888baba8e041c92c5c1882f25b8df5c29bff9f Mon Sep 17 00:00:00 2001
From: Bard Liao <yung-chuan.liao@linux.intel.com>
Date: Wed, 12 Jun 2019 12:01:48 -0500
Subject: [PATCH] ASoC: SOF: dont wake dsp up in kcontrol IO

Always get kcontrol value from cache, set kcontrol value to DSP
when DSP is active. Kcontrol values will be restored when DSP boot up.
We will set the default value of kcontrol in sof_complete to make sure
the value is align with firmware.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sof/control.c  | 270 ++++++---------------------------------
 sound/soc/sof/topology.c |  48 +++++++
 2 files changed, 86 insertions(+), 232 deletions(-)

diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c
index 84e2cbfbbcbb..a4983f90ff5b 100644
--- a/sound/soc/sof/control.c
+++ b/sound/soc/sof/control.c
@@ -39,26 +39,8 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *sm =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = sm->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the mixer data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_VOLUME,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
@@ -66,12 +48,6 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
 			ipc_to_mixer(cdata->chanv[i].value,
 				     scontrol->volume_table, sm->max + 1);
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -84,16 +60,6 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -104,18 +70,13 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of mixer updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_VOLUME,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: volume put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_VOLUME,
+					      true);
+
 	return 0;
 }
 
@@ -125,37 +86,13 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *sm =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = sm->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the mixer data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_SWITCH,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
 		ucontrol->value.integer.value[i] = cdata->chanv[i].value;
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -168,16 +105,6 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -186,18 +113,13 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of mixer updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_SWITCH,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: switch put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_SWITCH,
+					      true);
+
 	return 0;
 }
 
@@ -207,37 +129,13 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
 	struct soc_enum *se =
 		(struct soc_enum *)kcontrol->private_value;
 	struct snd_sof_control *scontrol = se->dobj.private;
-	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int err, ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the enum data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_ENUM,
-				      false);
 
 	/* read back each channel */
 	for (i = 0; i < channels; i++)
 		ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
 
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum get failed to idle %d\n",
-				    err);
 	return 0;
 }
 
@@ -250,16 +148,6 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
 	struct snd_sof_dev *sdev = scontrol->sdev;
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	unsigned int i, channels = scontrol->num_channels;
-	int ret, err;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
 
 	/* update each channel */
 	for (i = 0; i < channels; i++) {
@@ -268,18 +156,13 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
 	}
 
 	/* notify DSP of enum updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_VALUE,
-				      SOF_CTRL_TYPE_VALUE_CHAN_GET,
-				      SOF_CTRL_CMD_ENUM,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: enum put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_VALUE,
+					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
+					      SOF_CTRL_CMD_ENUM,
+					      true);
+
 	return 0;
 }
 
@@ -293,7 +176,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	struct sof_abi_hdr *data = cdata->data;
 	size_t size;
-	int ret, err;
+	int ret = 0;
 
 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
 		dev_err_ratelimited(sdev->dev,
@@ -302,22 +185,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
-	/* get all the binary data from DSP */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_GET_DATA,
-				      SOF_CTRL_TYPE_DATA_GET,
-				      scontrol->cmd,
-				      false);
-
 	size = data->size + sizeof(*data);
 	if (size > be->max) {
 		dev_err_ratelimited(sdev->dev,
@@ -331,12 +198,6 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 	memcpy(ucontrol->value.bytes.data, data, size);
 
 out:
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes get failed to idle %d\n",
-				    err);
 	return ret;
 }
 
@@ -350,7 +211,6 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 	struct sof_abi_hdr *data = cdata->data;
 	size_t size = data->size + sizeof(*data);
-	int ret, err;
 
 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
 		dev_err_ratelimited(sdev->dev,
@@ -366,32 +226,18 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
 	/* copy from kcontrol */
 	memcpy(data, ucontrol->value.bytes.data, size);
 
 	/* notify DSP of byte control updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_DATA,
-				      SOF_CTRL_TYPE_DATA_SET,
-				      scontrol->cmd,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes put failed to idle %d\n",
-				    err);
-	return ret;
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_DATA,
+					      SOF_CTRL_TYPE_DATA_SET,
+					      scontrol->cmd,
+					      true);
+
+	return 0;
 }
 
 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
@@ -406,8 +252,6 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_tlv header;
 	const struct snd_ctl_tlv __user *tlvd =
 		(const struct snd_ctl_tlv __user *)binary_data;
-	int ret;
-	int err;
 
 	/*
 	 * The beginning of bytes data contains a header from where
@@ -453,30 +297,15 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
 		return -EINVAL;
 	}
 
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext put failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
-
 	/* notify DSP of byte control updates */
-	snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-				      SOF_IPC_COMP_SET_DATA,
-				      SOF_CTRL_TYPE_DATA_SET,
-				      scontrol->cmd,
-				      true);
-
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext put failed to idle %d\n",
-				    err);
+	if (pm_runtime_active(sdev->dev))
+		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+					      SOF_IPC_COMP_SET_DATA,
+					      SOF_CTRL_TYPE_DATA_SET,
+					      scontrol->cmd,
+					      true);
 
-	return ret;
+	return 0;
 }
 
 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
@@ -492,17 +321,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_tlv __user *tlvd =
 		(struct snd_ctl_tlv __user *)binary_data;
 	int data_size;
-	int err;
-	int ret;
-
-	ret = pm_runtime_get_sync(sdev->dev);
-	if (ret < 0) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext get failed to resume %d\n",
-				    ret);
-		pm_runtime_put_noidle(sdev->dev);
-		return ret;
-	}
+	int ret = 0;
 
 	/*
 	 * Decrement the limit by ext bytes header size to
@@ -514,13 +333,6 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 	cdata->data->magic = SOF_ABI_MAGIC;
 	cdata->data->abi = SOF_ABI_VERSION;
 
-	/* get all the component data from DSP */
-	ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
-					    SOF_IPC_COMP_GET_DATA,
-					    SOF_CTRL_TYPE_DATA_GET,
-					    scontrol->cmd,
-					    false);
-
 	/* Prevent read of other kernel data or possibly corrupt response */
 	data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
 
@@ -543,11 +355,5 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 		ret = -EFAULT;
 
 out:
-	pm_runtime_mark_last_busy(sdev->dev);
-	err = pm_runtime_put_autosuspend(sdev->dev);
-	if (err < 0)
-		dev_err_ratelimited(sdev->dev,
-				    "error: bytes_ext get failed to idle %d\n",
-				    err);
 	return ret;
 }
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 8e00f829bfdb..aaf459af89d0 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -3016,6 +3016,49 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
 	return ret;
 }
 
+/* Function to set the initial value of SOF kcontrols.
+ * The value will be stored in scontrol->control_data
+ */
+static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev)
+{
+	struct snd_sof_control *scontrol = NULL;
+	int ipc_cmd, ctrl_type;
+	int ret = 0;
+
+	list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
+
+		/* notify DSP of kcontrol values */
+		switch (scontrol->cmd) {
+		case SOF_CTRL_CMD_VOLUME:
+		case SOF_CTRL_CMD_ENUM:
+		case SOF_CTRL_CMD_SWITCH:
+			ipc_cmd = SOF_IPC_COMP_GET_VALUE;
+			ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET;
+			break;
+		case SOF_CTRL_CMD_BINARY:
+			ipc_cmd = SOF_IPC_COMP_GET_DATA;
+			ctrl_type = SOF_CTRL_TYPE_DATA_GET;
+			break;
+		default:
+			dev_err(sdev->dev,
+				"error: Invalid scontrol->cmd: %d\n",
+				scontrol->cmd);
+			return -EINVAL;
+		}
+		ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
+						    ipc_cmd, ctrl_type,
+						    scontrol->cmd,
+						    false);
+		if (ret < 0) {
+			dev_warn(sdev->dev,
+				"error: kcontrol value get for widget: %d\n",
+				scontrol->comp_id);
+		}
+	}
+
+	return ret;
+}
+
 int snd_sof_complete_pipeline(struct snd_sof_dev *sdev,
 			      struct snd_sof_widget *swidget)
 {
@@ -3059,6 +3102,11 @@ static void sof_complete(struct snd_soc_component *scomp)
 			break;
 		}
 	}
+	/*
+	 * cache initial values of SOF kcontrols by reading DSP value over
+	 * IPC. It may be overwritten by alsa-mixer after booting up
+	 */
+	snd_sof_cache_kcontrol_val(sdev);
 }
 
 /* manifest - optional to inform component of manifest */
-- 
2.20.1

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

* Applied "ASoC: SOF: topology: pass volume min/max linear value to FW" to the asoc tree
  2019-06-12 17:01 ` [PATCH 2/4] ASoC: SOF: topology: pass volume min/max linear value to FW Pierre-Louis Bossart
@ 2019-06-13 19:05   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2019-06-13 19:05 UTC (permalink / raw)
  To: Zhu Yingjiang; +Cc: tiwai, alsa-devel, Mark Brown, Pierre-Louis Bossart

The patch

   ASoC: SOF: topology: pass volume min/max linear value to FW

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.3

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 65a18a46b274e64012fcf19d79ac62c8fb2a12e9 Mon Sep 17 00:00:00 2001
From: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Date: Wed, 12 Jun 2019 12:01:46 -0500
Subject: [PATCH] ASoC: SOF: topology: pass volume min/max linear value to FW

The driver currently passes the volume ramp type and length
topology tokens to firmware, but the min and max volume are
not set. This patch provides a correction to convert the
information from the topology file and pass the linear volume
min/max value to the firmware to improve transitions.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sof/topology.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 1c661dec8dd4..bbad8053b1bc 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1552,6 +1552,9 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index,
 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
 	struct snd_soc_tplg_private *private = &tw->priv;
 	struct sof_ipc_comp_volume *volume;
+	struct snd_sof_control *scontrol;
+	int min_step;
+	int max_step;
 	int ret;
 
 	volume = kzalloc(sizeof(*volume), GFP_KERNEL);
@@ -1594,6 +1597,17 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index,
 
 	swidget->private = volume;
 
+	list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
+		if (scontrol->comp_id == swidget->comp_id) {
+			min_step = scontrol->min_volume_step;
+			max_step = scontrol->max_volume_step;
+			volume->min_value = scontrol->volume_table[min_step];
+			volume->max_value = scontrol->volume_table[max_step];
+			volume->channels = scontrol->num_channels;
+			break;
+		}
+	}
+
 	ret = sof_ipc_tx_message(sdev->ipc, volume->comp.hdr.cmd, volume,
 				 sizeof(*volume), r, sizeof(*r));
 	if (ret >= 0)
-- 
2.20.1

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

* Applied "ASoC: SOF: topology: add min/max step for volume_table" to the asoc tree
  2019-06-12 17:01 ` [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table Pierre-Louis Bossart
@ 2019-06-13 19:06   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2019-06-13 19:06 UTC (permalink / raw)
  To: Zhu Yingjiang; +Cc: tiwai, alsa-devel, Mark Brown, Pierre-Louis Bossart

The patch

   ASoC: SOF: topology: add min/max step for volume_table

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.3

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 aa66fd80e0813fab0146e001b8bef8c4ffe0ba3a Mon Sep 17 00:00:00 2001
From: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Date: Wed, 12 Jun 2019 12:01:45 -0500
Subject: [PATCH] ASoC: SOF: topology: add min/max step for volume_table

add two units min_volume_step and max_volume_step to the snd_sof_control
struct, for the min and max step of the volume_table.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sof/sof-priv.h | 2 ++
 sound/soc/sof/topology.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 17f3d2a5a701..8760a4694d8f 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -297,6 +297,8 @@ struct snd_sof_pcm {
 struct snd_sof_control {
 	struct snd_sof_dev *sdev;
 	int comp_id;
+	int min_volume_step; /* min volume step for volume_table */
+	int max_volume_step; /* max volume step for volume_table */
 	int num_channels;
 	u32 readback_offset; /* offset to mmaped data if used */
 	struct sof_ipc_ctrl_data *control_data;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index a13233ae6d0e..1c661dec8dd4 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -451,6 +451,8 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
 		return -ENOMEM;
 
 	scontrol->comp_id = sdev->next_comp_id;
+	scontrol->min_volume_step = le32_to_cpu(mc->min);
+	scontrol->max_volume_step = le32_to_cpu(mc->max);
 	scontrol->num_channels = le32_to_cpu(mc->num_channels);
 
 	/* set cmd for mixer control */
-- 
2.20.1

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

end of thread, other threads:[~2019-06-13 19:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-12 17:01 [PATCH 0/4] ASoC: SOF: control/topology improvements Pierre-Louis Bossart
2019-06-12 17:01 ` [PATCH 1/4] ASoC: SOF: topology: add min/max step for volume_table Pierre-Louis Bossart
2019-06-13 19:06   ` Applied "ASoC: SOF: topology: add min/max step for volume_table" to the asoc tree Mark Brown
2019-06-12 17:01 ` [PATCH 2/4] ASoC: SOF: topology: pass volume min/max linear value to FW Pierre-Louis Bossart
2019-06-13 19:05   ` Applied "ASoC: SOF: topology: pass volume min/max linear value to FW" to the asoc tree Mark Brown
2019-06-12 17:01 ` [PATCH 3/4] ASoC: SOF: Add DMIC token for unmute gain ramp time Pierre-Louis Bossart
2019-06-13 19:05   ` Applied "ASoC: SOF: Add DMIC token for unmute gain ramp time" to the asoc tree Mark Brown
2019-06-12 17:01 ` [PATCH 4/4] ASoC: SOF: dont wake dsp up in kcontrol IO Pierre-Louis Bossart
2019-06-13 19:05   ` Applied "ASoC: SOF: dont wake dsp up in kcontrol IO" 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.