Skip to content

Commit d641c16

Browse files
committed
ASoC/SoundWire: clean up link DMA during stop for IPC4
Merge series from Bard Liao <[email protected]>: Clean up the link DMA for playback during stop for IPC4 is required to reset the DMA read/write pointers when the stream is prepared and restarted after a call to snd_pcm_drain()/snd_pcm_drop(). The change is mainly on ASoC. We may go via ASoC tree with Vinod's Acked-by tag Ranjani Sridharan (4): ASoC: SOF: ipc4-topology: Do not set ALH node_id for aggregated DAIs ASoC: SOF: Intel: hda: Handle prepare without close for non-HDA DAI's soundwire: intel_ace2x: Send PDI stream number during prepare ASoC: SOF: Intel: hda: Always clean up link DMA during stop drivers/soundwire/intel_ace2x.c | 19 +++++----------- sound/soc/sof/intel/hda-dai-ops.c | 23 +++++++++---------- sound/soc/sof/intel/hda-dai.c | 37 +++++++++++++++++++++++++++---- sound/soc/sof/ipc4-topology.c | 15 +++++++++++-- 4 files changed, 62 insertions(+), 32 deletions(-) -- 2.43.0
2 parents da95e89 + ab55937 commit d641c16

File tree

4 files changed

+62
-32
lines changed

4 files changed

+62
-32
lines changed

drivers/soundwire/intel_ace2x.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,12 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
376376
static int intel_prepare(struct snd_pcm_substream *substream,
377377
struct snd_soc_dai *dai)
378378
{
379+
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
379380
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
380381
struct sdw_intel *sdw = cdns_to_intel(cdns);
381382
struct sdw_cdns_dai_runtime *dai_runtime;
383+
struct snd_pcm_hw_params *hw_params;
382384
int ch, dir;
383-
int ret = 0;
384385

385386
dai_runtime = cdns->dai_runtime_array[dai->id];
386387
if (!dai_runtime) {
@@ -389,12 +390,8 @@ static int intel_prepare(struct snd_pcm_substream *substream,
389390
return -EIO;
390391
}
391392

393+
hw_params = &rtd->dpcm[substream->stream].hw_params;
392394
if (dai_runtime->suspended) {
393-
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
394-
struct snd_pcm_hw_params *hw_params;
395-
396-
hw_params = &rtd->dpcm[substream->stream].hw_params;
397-
398395
dai_runtime->suspended = false;
399396

400397
/*
@@ -415,15 +412,11 @@ static int intel_prepare(struct snd_pcm_substream *substream,
415412
/* the SHIM will be configured in the callback functions */
416413

417414
sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi);
418-
419-
/* Inform DSP about PDI stream number */
420-
ret = intel_params_stream(sdw, substream, dai,
421-
hw_params,
422-
sdw->instance,
423-
dai_runtime->pdi->intel_alh_id);
424415
}
425416

426-
return ret;
417+
/* Inform DSP about PDI stream number */
418+
return intel_params_stream(sdw, substream, dai, hw_params, sdw->instance,
419+
dai_runtime->pdi->intel_alh_id);
427420
}
428421

429422
static int

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

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -346,20 +346,21 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
346346
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
347347
snd_hdac_ext_stream_start(hext_stream);
348348
break;
349-
case SNDRV_PCM_TRIGGER_SUSPEND:
350-
case SNDRV_PCM_TRIGGER_STOP:
351349
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
352-
snd_hdac_ext_stream_clear(hext_stream);
353-
354350
/*
355-
* Save the LLP registers in case the stream is
356-
* restarting due PAUSE_RELEASE, or START without a pcm
357-
* close/open since in this case the LLP register is not reset
358-
* to 0 and the delay calculation will return with invalid
359-
* results.
351+
* Save the LLP registers since in case of PAUSE the LLP
352+
* register are not reset to 0, the delay calculation will use
353+
* the saved offsets for compensating the delay calculation.
360354
*/
361355
hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
362356
hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
357+
snd_hdac_ext_stream_clear(hext_stream);
358+
break;
359+
case SNDRV_PCM_TRIGGER_SUSPEND:
360+
case SNDRV_PCM_TRIGGER_STOP:
361+
hext_stream->pplcllpl = 0;
362+
hext_stream->pplcllpu = 0;
363+
snd_hdac_ext_stream_clear(hext_stream);
363364
break;
364365
default:
365366
dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
@@ -512,7 +513,6 @@ static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = {
512513
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
513514
struct snd_pcm_substream *substream, int cmd)
514515
{
515-
struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
516516
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
517517

518518
switch (cmd) {
@@ -527,9 +527,6 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
527527
if (ret < 0)
528528
return ret;
529529

530-
if (cmd == SNDRV_PCM_TRIGGER_STOP)
531-
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
532-
533530
break;
534531
}
535532
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:

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

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
302302
}
303303

304304
switch (cmd) {
305+
case SNDRV_PCM_TRIGGER_STOP:
305306
case SNDRV_PCM_TRIGGER_SUSPEND:
306307
ret = hda_link_dma_cleanup(substream, hext_stream, dai);
307308
if (ret < 0) {
@@ -370,14 +371,20 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
370371
return -EINVAL;
371372
}
372373

374+
sdev = widget_to_sdev(w);
375+
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
376+
377+
/* nothing more to do if the link is already prepared */
378+
if (hext_stream && hext_stream->link_prepared)
379+
return 0;
380+
373381
/* use HDaudio stream handling */
374382
ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
375383
if (ret < 0) {
376384
dev_err(cpu_dai->dev, "%s: hda_dai_hw_params_data failed: %d\n", __func__, ret);
377385
return ret;
378386
}
379387

380-
sdev = widget_to_sdev(w);
381388
if (sdev->dspless_mode_selected)
382389
return 0;
383390

@@ -482,6 +489,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
482489
int ret;
483490
int i;
484491

492+
ops = hda_dai_get_ops(substream, cpu_dai);
493+
if (!ops) {
494+
dev_err(cpu_dai->dev, "DAI widget ops not set\n");
495+
return -EINVAL;
496+
}
497+
498+
sdev = widget_to_sdev(w);
499+
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
500+
501+
/* nothing more to do if the link is already prepared */
502+
if (hext_stream && hext_stream->link_prepared)
503+
return 0;
504+
505+
/*
506+
* reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted
507+
* due to xruns or after a call to snd_pcm_drain/drop()
508+
*/
509+
ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
510+
0, 0, substream->stream);
511+
if (ret < 0) {
512+
dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n",
513+
__func__, ret);
514+
return ret;
515+
}
516+
485517
data.dai_index = (link_id << 8) | cpu_dai->id;
486518
data.dai_node_id = intel_alh_id;
487519
ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
@@ -490,10 +522,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
490522
return ret;
491523
}
492524

493-
ops = hda_dai_get_ops(substream, cpu_dai);
494-
sdev = widget_to_sdev(w);
495525
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
496-
497526
if (!hext_stream)
498527
return -ENODEV;
499528

sound/soc/sof/ipc4-topology.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3129,9 +3129,20 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
31293129
* group_id during copier's ipc_prepare op.
31303130
*/
31313131
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
3132+
struct sof_ipc4_alh_configuration_blob *blob;
3133+
3134+
blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
31323135
ipc4_copier->dai_index = data->dai_node_id;
3133-
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
3134-
copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id);
3136+
3137+
/*
3138+
* no need to set the node_id for aggregated DAI's. These will be assigned
3139+
* a group_id during widget ipc_prepare
3140+
*/
3141+
if (blob->alh_cfg.device_count == 1) {
3142+
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
3143+
copier_data->gtw_cfg.node_id |=
3144+
SOF_IPC4_NODE_INDEX(data->dai_node_id);
3145+
}
31353146
}
31363147

31373148
break;

0 commit comments

Comments
 (0)