Commit 31be5337 authored by Seppo Ingalsuo's avatar Seppo Ingalsuo Committed by Mark Brown

ASoC: SOF: Intel: Change DMIC load IPC to fixed length

This patch changes the flexible array member pdm[] into a fixed
array of four that is the max. number of stereo PDM controllers
in the current Intel platforms. The change simplifies DMIC DAI
load code and aligns the IPC with other DAI types.

The change is compatible with old and new firmware with similar
change. The ABI minor version is increased due to change in
IPC headers.
Signed-off-by: default avatarSeppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Link: https://lore.kernel.org/r/20200415202816.934-18-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 79a4ff94
...@@ -49,6 +49,9 @@ ...@@ -49,6 +49,9 @@
/* bclk idle */ /* bclk idle */
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5) #define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5)
/* DMIC max. four controllers for eight microphone channels */
#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4
/* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */ /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */
struct sof_ipc_dai_ssp_params { struct sof_ipc_dai_ssp_params {
struct sof_ipc_hdr hdr; struct sof_ipc_hdr hdr;
...@@ -175,7 +178,8 @@ struct sof_ipc_dai_dmic_params { ...@@ -175,7 +178,8 @@ struct sof_ipc_dai_dmic_params {
uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */
uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */
uint32_t num_pdm_active; /**< Number of active pdm controllers */ uint32_t num_pdm_active; /**< Number of active pdm controllers. */
/**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */
uint32_t wake_up_time; /**< Time from clock start to data (us) */ 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 min_clock_on_time; /**< Min. time that clk is kept on (us) */
...@@ -184,8 +188,8 @@ struct sof_ipc_dai_dmic_params { ...@@ -184,8 +188,8 @@ struct sof_ipc_dai_dmic_params {
/* reserved for future use */ /* reserved for future use */
uint32_t reserved[5]; uint32_t reserved[5];
/**< variable number of pdm controller config */ /**< PDM controllers configuration */
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL];
} __packed; } __packed;
#endif #endif
...@@ -2891,18 +2891,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2891,18 +2891,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
{ {
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct snd_soc_tplg_private *private = &cfg->priv; struct snd_soc_tplg_private *private = &cfg->priv;
struct sof_ipc_dai_config *ipc_config;
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_fw_version *v = &ready->version;
u32 size; size_t size = sizeof(*config);
int ret, j; int ret, j;
/* /* Ensure the entire DMIC config struct is zeros */
* config is only used for the common params in dmic_params structure
* that does not include the PDM controller config array
* Set the common params to 0.
*/
memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params)); memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params));
/* get DMIC tokens */ /* get DMIC tokens */
...@@ -2915,33 +2910,16 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2915,33 +2910,16 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
return ret; return ret;
} }
/*
* allocate memory for dmic dai config accounting for the
* variable number of active pdm controllers
* This will be the ipc payload for setting dai config
*/
size = sizeof(*config) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl) *
config->dmic.num_pdm_active;
ipc_config = kzalloc(size, GFP_KERNEL);
if (!ipc_config)
return -ENOMEM;
/* copy the common dai config and dmic params */
memcpy(ipc_config, config, sizeof(*config));
/* /*
* alloc memory for private member * alloc memory for private member
* Used to track the pdm config array index currently being parsed * Used to track the pdm config array index currently being parsed
*/ */
sdev->private = kzalloc(sizeof(u32), GFP_KERNEL); sdev->private = kzalloc(sizeof(u32), GFP_KERNEL);
if (!sdev->private) { if (!sdev->private)
kfree(ipc_config);
return -ENOMEM; return -ENOMEM;
}
/* get DMIC PDM tokens */ /* get DMIC PDM tokens */
ret = sof_parse_tokens(scomp, &ipc_config->dmic.pdm[0], dmic_pdm_tokens, ret = sof_parse_tokens(scomp, &config->dmic.pdm[0], dmic_pdm_tokens,
ARRAY_SIZE(dmic_pdm_tokens), private->array, ARRAY_SIZE(dmic_pdm_tokens), private->array,
le32_to_cpu(private->size)); le32_to_cpu(private->size));
if (ret != 0) { if (ret != 0) {
...@@ -2951,44 +2929,42 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2951,44 +2929,42 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
} }
/* set IPC header size */ /* set IPC header size */
ipc_config->hdr.size = size; config->hdr.size = size;
/* debug messages */ /* debug messages */
dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n",
ipc_config->dai_index, ipc_config->dmic.driver_ipc_version); config->dai_index, config->dmic.driver_ipc_version);
dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n",
ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max, config->dmic.pdmclk_min, config->dmic.pdmclk_max,
ipc_config->dmic.duty_min); config->dmic.duty_min);
dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n",
ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs, config->dmic.duty_max, config->dmic.fifo_fs,
ipc_config->dmic.num_pdm_active); config->dmic.num_pdm_active);
dev_dbg(scomp->dev, "fifo word length %hd\n", dev_dbg(scomp->dev, "fifo word length %hd\n", config->dmic.fifo_bits);
ipc_config->dmic.fifo_bits);
for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) { for (j = 0; j < config->dmic.num_pdm_active; j++) {
dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n", dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n",
ipc_config->dmic.pdm[j].id, config->dmic.pdm[j].id,
ipc_config->dmic.pdm[j].enable_mic_a, config->dmic.pdm[j].enable_mic_a,
ipc_config->dmic.pdm[j].enable_mic_b); config->dmic.pdm[j].enable_mic_b);
dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n", dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n",
ipc_config->dmic.pdm[j].id, config->dmic.pdm[j].id,
ipc_config->dmic.pdm[j].polarity_mic_a, config->dmic.pdm[j].polarity_mic_a,
ipc_config->dmic.pdm[j].polarity_mic_b); config->dmic.pdm[j].polarity_mic_b);
dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n", dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n",
ipc_config->dmic.pdm[j].id, config->dmic.pdm[j].id,
ipc_config->dmic.pdm[j].clk_edge, config->dmic.pdm[j].clk_edge,
ipc_config->dmic.pdm[j].skew); config->dmic.pdm[j].skew);
} }
if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) {
/* this takes care of backwards compatible handling of fifo_bits_b */ /* this takes care of backwards compatible handling of fifo_bits_b */
ipc_config->dmic.reserved_2 = ipc_config->dmic.fifo_bits; config->dmic.reserved_2 = config->dmic.fifo_bits;
} }
/* send message to DSP */ /* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc, ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size,
ipc_config->hdr.cmd, ipc_config, size, &reply, &reply, sizeof(reply));
sizeof(reply));
if (ret < 0) { if (ret < 0) {
dev_err(scomp->dev, dev_err(scomp->dev,
...@@ -2998,14 +2974,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2998,14 +2974,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
} }
/* set config for all DAI's with name matching the link name */ /* set config for all DAI's with name matching the link name */
ret = sof_set_dai_config(sdev, size, link, ipc_config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n", dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n",
config->dai_index); config->dai_index);
err: err:
kfree(sdev->private); kfree(sdev->private);
kfree(ipc_config);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment