Skip to content

Commit 4abf19c

Browse files
committed
ASoC: SOF: Intel: hda: reserve link/host DMA channels with same ID
The sequence of PCM ops upon starting a PCM stream in SOF is as follows (Showing only the hw_params and trigger ops): Host hw_params -> Link hw_params -> Host START -> Link START For HDA streams, the host DMA channel would be assigned during host hw_params and the corresponding link DMA channel would be assigned in link hw_params. But for non-HDA streams such as I2S, DMIC and trace DMA, only the host DMA is used. Therefore, the link DMA channel corresponding to the host DMA channel will not be assigned as there is no link hw_params as shown in the sequence above The recommended HDA HW programming sequence requires that the host DMA channel and link DMA channel with the same ID be coupled before DMA format setting and decoupled right after. This would lead to issues with concurrent usecases when the host DMA and link DMA channels for a HDA stream do not match. Therefore, when the link DMA channel corresponding to the host DMA channel for non-HDA streams must be reserved by setting link_locked in the host START trigger op to prevent it from being assigned to another stream. Similar logic applies to hostless streams, where the link DMA is in use but the host DMA is not in use. The host DMA channel corresponding to the link DMA channel must be reserved to prevent it from being assigned to another stream. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 043e5a3 commit 4abf19c

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

sound/soc/sof/intel/hda-dai.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
145145
{
146146
struct hdac_ext_stream *link_dev =
147147
snd_soc_dai_get_dma_data(dai, substream);
148+
struct hdac_stream stream = link_dev->hstream;
149+
148150
int ret;
149151

150152
dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
@@ -161,11 +163,25 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
161163
/* fallthrough */
162164
case SNDRV_PCM_TRIGGER_START:
163165
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
166+
/*
167+
* The recommended HDA HW programming sequence requires host
168+
* DMA and link DMA with the same IDs to be coupled before
169+
* setting the DMA format. For PCM streams, the host
170+
* DMA channel corresponding to the link DMA channel would
171+
* be assigned. But hostless pipelines (Ex: tone) do not use
172+
* host DMA. So, the host DMA channel with the same ID as the
173+
* link DMA must be reserved to prevent it from being assigned
174+
* to another stream.
175+
*/
176+
stream.opened = 1;
164177
snd_hdac_ext_link_stream_start(link_dev);
165178
break;
166-
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
167179
case SNDRV_PCM_TRIGGER_SUSPEND:
168180
case SNDRV_PCM_TRIGGER_STOP:
181+
stream.opened = 0;
182+
183+
/* fallthrough */
184+
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
169185
snd_hdac_ext_link_stream_clear(link_dev);
170186
break;
171187
default:

sound/soc/sof/intel/hda-stream.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,23 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
213213
/* cmd must be for audio stream */
214214
switch (cmd) {
215215
case SNDRV_PCM_TRIGGER_RESUME:
216-
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
217216
case SNDRV_PCM_TRIGGER_START:
217+
/*
218+
* The recommended HDA HW programming sequence requires host
219+
* DMA and link DMA with the same IDs to be coupled before
220+
* setting the DMA format. Both HDA and non-HDA streams utilize
221+
* host DMA but non-HDA streams (ex: I2S, DMIC etc) do not use
222+
* link DMA. In the case of HDA streams, the link hw_params
223+
* ioctl would handle handle locking the link DMA channel in
224+
* use. But for non-HDA streams, since link DMA is not used,
225+
* the link DMA channel with the same ID as the host DMA must
226+
* be reserved to prevent it from being assigned to another
227+
* stream.
228+
*/
229+
stream->link_locked = 1;
230+
231+
/* fallthrough */
232+
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
218233
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
219234
1 << hstream->index,
220235
1 << hstream->index);
@@ -229,8 +244,12 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
229244
hstream->running = true;
230245
break;
231246
case SNDRV_PCM_TRIGGER_SUSPEND:
232-
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
233247
case SNDRV_PCM_TRIGGER_STOP:
248+
/* unlock link DMA channel */
249+
stream->link_locked = 0;
250+
251+
/* fallthrough */
252+
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
234253
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
235254
sd_offset,
236255
SOF_HDA_SD_CTL_DMA_START |
@@ -241,6 +260,7 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
241260
SOF_HDA_CL_DMA_SD_INT_MASK);
242261

243262
hstream->running = false;
263+
244264
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
245265
1 << hstream->index, 0x0);
246266
break;

sound/soc/sof/intel/hda-trace.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
5151
return -ENODEV;
5252
}
5353

54+
/*
55+
* The recommended HDA HW programming sequence requires host DMA and
56+
* link DMA with the same IDs to be coupled before setting the
57+
* DMA format. Therefore, even though trace utilizes only host DMA
58+
* in decoupled mode, the link DMA channel with the same ID must be
59+
* reserved to avoid it being assigned to another stream.
60+
*/
61+
hda->dtrace_stream->link_locked = 1;
62+
5463
*stream_tag = hda->dtrace_stream->hstream.stream_tag;
5564

5665
/*
@@ -78,6 +87,7 @@ int hda_dsp_trace_release(struct snd_sof_dev *sdev)
7887
hda_dsp_stream_put(sdev,
7988
SNDRV_PCM_STREAM_CAPTURE,
8089
hstream->stream_tag);
90+
hda->dtrace_stream->link_locked = 0;
8191
hda->dtrace_stream = NULL;
8292
return 0;
8393
}

0 commit comments

Comments
 (0)