Commit bdf4ad3f authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown

ASoC: SOF: Intel: hda: assign link DMA channel at run-time

The recommended HDA HW programming sequence for setting
the DMA format requires that the link DMA and host DMA
channels be coupled before setting the format. This
change means that host DMA or link DMA channels be
reserved even if only one is used.

Statically assigned link DMA channels would mean that
all the corresponding host DMA channels will need to be
reserved, leaving only a few channels available at run-time.
So, the suggestion here is to switch to dynamically assigning
both host DMA channels and link DMA channels are run-time.

The host DMA channel is assigned when the pcm
is opened as before. While choosing the link DMA channel,
if the host DMA channel corresponding to the link DMA channel
is already taken, the proposed method checks to make
sure that the BE is connected to the FE that has been assigned
this host DMA channel. Once the link DMA channel is assigned,
an IPC is sent to the DSP to set the link DMA channel.

The link DMA channel is freed during hw_free() and also in the
SUSPEND trigger callback. It will be re-assigned when hw_params
are set upon resume.
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1b7e1956
This diff is collapsed.
...@@ -60,6 +60,8 @@ ...@@ -60,6 +60,8 @@
(IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \
IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST))
#define DMA_CHAN_INVALID 0xFFFFFFFF
struct snd_sof_dev; struct snd_sof_dev;
struct snd_sof_ipc_msg; struct snd_sof_ipc_msg;
struct snd_sof_ipc; struct snd_sof_ipc;
......
...@@ -2591,9 +2591,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, ...@@ -2591,9 +2591,7 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
*/ */
static int sof_link_hda_process(struct snd_sof_dev *sdev, static int sof_link_hda_process(struct snd_sof_dev *sdev,
struct snd_soc_dai_link *link, struct snd_soc_dai_link *link,
struct sof_ipc_dai_config *config, struct sof_ipc_dai_config *config)
int tx_slot,
int rx_slot)
{ {
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
u32 size = sizeof(*config); u32 size = sizeof(*config);
...@@ -2606,22 +2604,11 @@ static int sof_link_hda_process(struct snd_sof_dev *sdev, ...@@ -2606,22 +2604,11 @@ static int sof_link_hda_process(struct snd_sof_dev *sdev,
continue; continue;
if (strcmp(link->name, sof_dai->name) == 0) { if (strcmp(link->name, sof_dai->name) == 0) {
if (sof_dai->comp_dai.direction ==
SNDRV_PCM_STREAM_PLAYBACK) {
if (!link->dpcm_playback)
return -EINVAL;
config->hda.link_dma_ch = tx_slot;
} else {
if (!link->dpcm_capture)
return -EINVAL;
config->hda.link_dma_ch = rx_slot;
}
config->dai_index = sof_dai->comp_dai.dai_index; config->dai_index = sof_dai->comp_dai.dai_index;
found = 1; found = 1;
config->hda.link_dma_ch = DMA_CHAN_INVALID;
/* save config in dai component */ /* save config in dai component */
sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL); sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL);
if (!sof_dai->dai_config) if (!sof_dai->dai_config)
...@@ -2667,10 +2654,6 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, ...@@ -2667,10 +2654,6 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index,
struct snd_soc_tplg_private *private = &cfg->priv; struct snd_soc_tplg_private *private = &cfg->priv;
struct snd_soc_dai *dai; struct snd_soc_dai *dai;
u32 size = sizeof(*config); u32 size = sizeof(*config);
u32 tx_num = 0;
u32 tx_slot = 0;
u32 rx_num = 0;
u32 rx_slot = 0;
int ret; int ret;
/* init IPC */ /* init IPC */
...@@ -2694,22 +2677,7 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, ...@@ -2694,22 +2677,7 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index,
return -EINVAL; return -EINVAL;
} }
if (link->dpcm_playback) ret = sof_link_hda_process(sdev, link, config);
tx_num = 1;
if (link->dpcm_capture)
rx_num = 1;
ret = snd_soc_dai_get_channel_map(dai, &tx_num, &tx_slot,
&rx_num, &rx_slot);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to get dma channel for HDA%d\n",
config->dai_index);
return ret;
}
ret = sof_link_hda_process(sdev, link, config, tx_slot, rx_slot);
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "error: failed to process hda dai link %s", dev_err(sdev->dev, "error: failed to process hda dai link %s",
link->name); link->name);
...@@ -2837,17 +2805,6 @@ static int sof_link_hda_unload(struct snd_sof_dev *sdev, ...@@ -2837,17 +2805,6 @@ static int sof_link_hda_unload(struct snd_sof_dev *sdev,
return -EINVAL; return -EINVAL;
} }
/*
* FIXME: this call to hw_free is mainly to release the link DMA ID.
* This is abusing the API and handling SOC internals is not
* recommended. This part will be reworked.
*/
if (dai->driver->ops->hw_free)
ret = dai->driver->ops->hw_free(NULL, dai);
if (ret < 0)
dev_err(sdev->dev, "error: failed to free hda resource for %s\n",
link->name);
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