Commit c03d5821 authored by Mark Brown's avatar Mark Brown

Merge series "SOF topology parsing updates" from Ranjani Sridharan...

Merge series "SOF topology parsing updates" from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

This series includes updates in the topology parser for DAIs
and their config.

The first three patches address the problem of sending the DAI
config to the DSP when there are multiple DAIs associated with
a DAI link.

The last patch deals with setting the default trigger order
for all links. Exceptions needed for HDA links are moved to
the DAI link fixup() callback.

Bard Liao (3):
  ASoC: SOF: topology: send ipc for all found DAIs in sof_set_dai_config
  ASoC: topology: set component dai_index to ipc dai config dai_index
  ASoC: SOF: topology: replace sof_link_hda_process by
    sof_set_dai_config

randerwang (1):
  ASoC: SOF: Intel: change trigger sequence to fix pop noise when
    stopping playback on sdw platforms

 sound/soc/sof/pcm.c      |  12 ++-
 sound/soc/sof/topology.c | 167 ++++++++++-----------------------------
 2 files changed, 51 insertions(+), 128 deletions(-)

--
2.17.1
parents f9dfa8f2 fd045558
...@@ -639,6 +639,7 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -639,6 +639,7 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dai *dai = struct snd_sof_dai *dai =
snd_sof_find_dai(component, (char *)rtd->dai_link->name); snd_sof_find_dai(component, (char *)rtd->dai_link->name);
struct snd_soc_dpcm *dpcm;
/* no topology exists for this BE, try a common configuration */ /* no topology exists for this BE, try a common configuration */
if (!dai) { if (!dai) {
...@@ -702,7 +703,16 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -702,7 +703,16 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
} }
break; break;
case SOF_DAI_INTEL_HDA: case SOF_DAI_INTEL_HDA:
/* do nothing for HDA dai_link */ /*
* HDaudio does not follow the default trigger
* sequence due to firmware implementation
*/
for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
struct snd_soc_pcm_runtime *fe = dpcm->fe;
fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
SND_SOC_DPCM_TRIGGER_POST;
}
break; break;
case SOF_DAI_INTEL_ALH: case SOF_DAI_INTEL_ALH:
/* do nothing for ALH dai_link */ /* do nothing for ALH dai_link */
......
...@@ -2673,7 +2673,11 @@ static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, ...@@ -2673,7 +2673,11 @@ static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config,
} }
} }
/* set config for all DAI's with name matching the link name */ /*
* Send IPC and set the same config for all DAIs with name matching the link
* name. Note that the function can only be used for the case that all DAIs
* have a common DAI config for now.
*/
static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size,
struct snd_soc_dai_link *link, struct snd_soc_dai_link *link,
struct sof_ipc_dai_config *config) struct sof_ipc_dai_config *config)
...@@ -2686,6 +2690,27 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, ...@@ -2686,6 +2690,27 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size,
continue; continue;
if (strcmp(link->name, dai->name) == 0) { if (strcmp(link->name, dai->name) == 0) {
struct sof_ipc_reply reply;
int ret;
/*
* the same dai config will be applied to all DAIs in
* the same dai link. We have to ensure that the ipc
* dai config's dai_index match to the component's
* dai_index.
*/
config->dai_index = dai->comp_dai.dai_index;
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size,
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev, "error: failed to set DAI config for %s index %d\n",
dai->name, config->dai_index);
return ret;
}
dai->dai_config = kmemdup(config, size, GFP_KERNEL); dai->dai_config = kmemdup(config, size, GFP_KERNEL);
if (!dai->dai_config) if (!dai->dai_config)
return -ENOMEM; return -ENOMEM;
...@@ -2718,7 +2743,6 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, ...@@ -2718,7 +2743,6 @@ static int sof_link_ssp_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_reply reply;
u32 size = sizeof(*config); u32 size = sizeof(*config);
int ret; int ret;
...@@ -2767,17 +2791,6 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, ...@@ -2767,17 +2791,6 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index,
return -EINVAL; return -EINVAL;
} }
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(scomp->dev, "error: failed to set DAI config for SSP%d\n",
config->dai_index);
return ret;
}
/* 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, config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
...@@ -2795,7 +2808,6 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, ...@@ -2795,7 +2808,6 @@ static int sof_link_sai_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_reply reply;
u32 size = sizeof(*config); u32 size = sizeof(*config);
int ret; int ret;
...@@ -2835,17 +2847,6 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, ...@@ -2835,17 +2847,6 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index,
return -EINVAL; return -EINVAL;
} }
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(scomp->dev, "error: failed to set DAI config for SAI%d\n",
config->dai_index);
return ret;
}
/* 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, config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
...@@ -2863,7 +2864,6 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, ...@@ -2863,7 +2864,6 @@ static int sof_link_esai_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_reply reply;
u32 size = sizeof(*config); u32 size = sizeof(*config);
int ret; int ret;
...@@ -2904,16 +2904,6 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, ...@@ -2904,16 +2904,6 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index,
return -EINVAL; return -EINVAL;
} }
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(scomp->dev, "error: failed to set DAI config for ESAI%d\n",
config->dai_index);
return ret;
}
/* 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, config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
...@@ -2931,7 +2921,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2931,7 +2921,6 @@ 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_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;
size_t size = sizeof(*config); size_t size = sizeof(*config);
...@@ -3007,17 +2996,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -3007,17 +2996,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
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))
config->dmic.fifo_bits_b = config->dmic.fifo_bits; config->dmic.fifo_bits_b = config->dmic.fifo_bits;
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size,
&reply, sizeof(reply));
if (ret < 0) {
dev_err(scomp->dev,
"error: failed to set DAI config for DMIC%d\n",
config->dai_index);
goto err;
}
/* 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, config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
...@@ -3030,66 +3008,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -3030,66 +3008,6 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
return ret; return ret;
} }
/*
* for hda link, playback and capture are supported by different dai
* in FW. Here get the dai_index, set dma channel of each dai
* and send config to FW. In FW, each dai sets config by dai_index
*/
static int sof_link_hda_process(struct snd_sof_dev *sdev,
struct snd_soc_dai_link *link,
struct sof_ipc_dai_config *config)
{
struct sof_ipc_reply reply;
u32 size = sizeof(*config);
struct snd_sof_dai *sof_dai;
int found = 0;
int ret;
list_for_each_entry(sof_dai, &sdev->dai_list, list) {
if (!sof_dai->name)
continue;
if (strcmp(link->name, sof_dai->name) == 0) {
config->dai_index = sof_dai->comp_dai.dai_index;
found = 1;
config->hda.link_dma_ch = DMA_CHAN_INVALID;
/* save config in dai component */
sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL);
if (!sof_dai->dai_config)
return -ENOMEM;
sof_dai->cpu_dai_name = link->cpus->dai_name;
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size,
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev, "error: failed to set DAI config for direction:%d of HDA dai %d\n",
sof_dai->comp_dai.direction,
config->dai_index);
return ret;
}
}
}
/*
* machine driver may define a dai link with playback and capture
* dai enabled, but the dai link in topology would support both, one
* or none of them. Here print a warning message to notify user
*/
if (!found) {
dev_warn(sdev->dev, "warning: failed to find dai for dai link %s",
link->name);
}
return 0;
}
static int sof_link_hda_load(struct snd_soc_component *scomp, int index, static int sof_link_hda_load(struct snd_soc_component *scomp, int index,
struct snd_soc_dai_link *link, struct snd_soc_dai_link *link,
struct snd_soc_tplg_link_config *cfg, struct snd_soc_tplg_link_config *cfg,
...@@ -3126,7 +3044,9 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, ...@@ -3126,7 +3044,9 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index,
return -EINVAL; return -EINVAL;
} }
ret = sof_link_hda_process(sdev, link, config); config->hda.link_dma_ch = DMA_CHAN_INVALID;
ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
dev_err(scomp->dev, "error: failed to process hda dai link %s", dev_err(scomp->dev, "error: failed to process hda dai link %s",
link->name); link->name);
...@@ -3142,7 +3062,6 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, ...@@ -3142,7 +3062,6 @@ static int sof_link_alh_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_reply reply;
u32 size = sizeof(*config); u32 size = sizeof(*config);
int ret; int ret;
...@@ -3158,20 +3077,6 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, ...@@ -3158,20 +3077,6 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index,
/* init IPC */ /* init IPC */
config->hdr.size = size; config->hdr.size = size;
dev_dbg(scomp->dev, "ALH config rate %d channels %d\n",
config->alh.rate, config->alh.channels);
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(scomp->dev, "error: failed to set DAI config for ALH %d\n",
config->dai_index);
return ret;
}
/* 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, config); ret = sof_set_dai_config(sdev, size, link, config);
if (ret < 0) if (ret < 0)
...@@ -3206,9 +3111,17 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, ...@@ -3206,9 +3111,17 @@ static int sof_link_load(struct snd_soc_component *scomp, int index,
if (!link->no_pcm) { if (!link->no_pcm) {
link->nonatomic = true; link->nonatomic = true;
/* set trigger order */ /*
link->trigger[0] = SND_SOC_DPCM_TRIGGER_POST; * set default trigger order for all links. Exceptions to
link->trigger[1] = SND_SOC_DPCM_TRIGGER_POST; * the rule will be handled in sof_pcm_dai_link_fixup()
* For playback, the sequence is the following: start FE,
* start BE, stop BE, stop FE; for Capture the sequence is
* inverted start BE, start FE, stop FE, stop BE
*/
link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
SND_SOC_DPCM_TRIGGER_PRE;
link->trigger[SNDRV_PCM_STREAM_CAPTURE] =
SND_SOC_DPCM_TRIGGER_POST;
/* nothing more to do for FE dai links */ /* nothing more to do for FE dai links */
return 0; return 0;
......
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