Skip to content

Commit 2b009fa

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: Intel: hda: Unify DAI drv ops for IPC3 and IPC4
Define the post_trigger DMA op for IPC3 and unify the DAI driver ops for IPC3 and IPC4 for HDA DAI's. Also, use the post_trigger op to stop the paused streams properly in the hda_dai_suspend() function. This fixes the suspend while paused case for IPC4 because previously we weren't resetting the pipeline when suspending the system with some paused streams. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://lore.kernel.org/r/20230307140435.2808-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 4b2ee4c commit 2b009fa

File tree

3 files changed

+62
-148
lines changed

3 files changed

+62
-148
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,37 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
277277
.post_trigger = hda_ipc4_post_trigger
278278
};
279279

280+
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
281+
struct snd_pcm_substream *substream, int cmd)
282+
{
283+
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
284+
285+
switch (cmd) {
286+
case SNDRV_PCM_TRIGGER_SUSPEND:
287+
case SNDRV_PCM_TRIGGER_STOP:
288+
{
289+
struct snd_sof_dai_config_data data = { 0 };
290+
291+
data.dai_data = DMA_CHAN_INVALID;
292+
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
293+
}
294+
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
295+
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
296+
default:
297+
break;
298+
}
299+
300+
return 0;
301+
}
302+
280303
static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = {
281304
.get_hext_stream = hda_get_hext_stream,
282305
.assign_hext_stream = hda_assign_hext_stream,
283306
.release_hext_stream = hda_release_hext_stream,
284307
.setup_hext_stream = hda_setup_hext_stream,
285308
.reset_hext_stream = hda_reset_hext_stream,
309+
.trigger = hda_trigger,
310+
.post_trigger = hda_ipc3_post_trigger,
286311
};
287312

288313
#endif

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

Lines changed: 35 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@ static bool hda_use_tplg_nhlt;
2727
module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
2828
MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
2929

30-
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
31-
32-
static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
33-
struct snd_sof_dai_config_data *data)
30+
int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
31+
struct snd_sof_dai_config_data *data)
3432
{
3533
struct snd_sof_widget *swidget = w->dobj.private;
3634
struct snd_soc_component *component = swidget->scomp;
@@ -50,6 +48,8 @@ static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
5048
return 0;
5149
}
5250

51+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
52+
5353
static const struct hda_dai_widget_dma_ops *
5454
hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
5555
{
@@ -181,44 +181,6 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_
181181
return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai);
182182
}
183183

184-
static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai,
185-
int cmd)
186-
{
187-
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
188-
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
189-
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component);
190-
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
191-
struct hdac_ext_stream *hext_stream;
192-
int ret;
193-
194-
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
195-
196-
if (!hext_stream)
197-
return 0;
198-
199-
switch (cmd) {
200-
case SNDRV_PCM_TRIGGER_START:
201-
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
202-
snd_hdac_ext_stream_start(hext_stream);
203-
break;
204-
case SNDRV_PCM_TRIGGER_SUSPEND:
205-
case SNDRV_PCM_TRIGGER_STOP:
206-
snd_hdac_ext_stream_clear(hext_stream);
207-
ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai);
208-
if (ret < 0)
209-
return ret;
210-
211-
break;
212-
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
213-
snd_hdac_ext_stream_clear(hext_stream);
214-
215-
break;
216-
default:
217-
return -EINVAL;
218-
}
219-
return 0;
220-
}
221-
222184
static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
223185
{
224186
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component);
@@ -239,20 +201,6 @@ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_
239201
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai);
240202
}
241203

242-
static int hda_dai_widget_update(struct snd_soc_dapm_widget *w,
243-
int channel, bool widget_setup)
244-
{
245-
struct snd_sof_dai_config_data data;
246-
247-
data.dai_data = channel;
248-
249-
/* set up/free DAI widget and send DAI_CONFIG IPC */
250-
if (widget_setup)
251-
return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data);
252-
253-
return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data);
254-
}
255-
256204
static int hda_dai_hw_params(struct snd_pcm_substream *substream,
257205
struct snd_pcm_hw_params *params,
258206
struct snd_soc_dai *dai)
@@ -314,61 +262,11 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
314262
return hda_dai_config(w, flags, &data);
315263
}
316264

317-
static int hda_dai_hw_free_ipc(int stream, /* direction */
318-
struct snd_soc_dai *dai)
319-
{
320-
struct snd_soc_dapm_widget *w;
321-
322-
w = snd_soc_dai_get_widget(dai, stream);
323-
324-
/* free the link DMA channel in the FW and the DAI widget */
325-
return hda_dai_widget_update(w, DMA_CHAN_INVALID, false);
326-
}
327-
328-
static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream,
329-
int cmd, struct snd_soc_dai *dai)
330-
{
331-
struct snd_soc_dapm_widget *w;
332-
int ret;
333-
334-
dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
335-
dai->name, substream->stream);
336-
337-
ret = hda_link_dma_trigger(substream, dai, cmd);
338-
if (ret < 0)
339-
return ret;
340-
341-
w = snd_soc_dai_get_widget(dai, substream->stream);
342-
343-
switch (cmd) {
344-
case SNDRV_PCM_TRIGGER_SUSPEND:
345-
case SNDRV_PCM_TRIGGER_STOP:
346-
/*
347-
* free DAI widget during stop/suspend to keep widget use_count's balanced.
348-
*/
349-
ret = hda_dai_hw_free_ipc(substream->stream, dai);
350-
if (ret < 0)
351-
return ret;
352-
353-
break;
354-
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
355-
ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
356-
if (ret < 0)
357-
return ret;
358-
break;
359-
360-
default:
361-
break;
362-
}
363-
return 0;
364-
}
365-
366265
/*
367266
* In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes
368267
* (over IPC channel) and DMA state change (direct host register changes).
369268
*/
370-
static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream,
371-
int cmd, struct snd_soc_dai *dai)
269+
static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
372270
{
373271
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
374272
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
@@ -437,10 +335,10 @@ static int hda_dai_hw_free(struct snd_pcm_substream *substream,
437335
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
438336
}
439337

440-
static const struct snd_soc_dai_ops ipc3_hda_dai_ops = {
338+
static const struct snd_soc_dai_ops hda_dai_ops = {
441339
.hw_params = hda_dai_hw_params,
442340
.hw_free = hda_dai_hw_free,
443-
.trigger = ipc3_hda_dai_trigger,
341+
.trigger = hda_dai_trigger,
444342
.prepare = hda_dai_prepare,
445343
};
446344

@@ -463,73 +361,62 @@ static int hda_dai_suspend(struct hdac_bus *bus)
463361
* explicitly during suspend.
464362
*/
465363
if (hext_stream->link_substream) {
466-
struct snd_soc_dai *cpu_dai;
364+
const struct hda_dai_widget_dma_ops *ops;
365+
struct snd_sof_widget *swidget;
366+
struct snd_soc_dapm_widget *w;
467367
struct snd_soc_dai *codec_dai;
368+
struct snd_soc_dai *cpu_dai;
369+
struct snd_sof_dev *sdev;
370+
struct snd_sof_dai *sdai;
468371

469372
rtd = asoc_substream_to_rtd(hext_stream->link_substream);
470373
cpu_dai = asoc_rtd_to_cpu(rtd, 0);
471374
codec_dai = asoc_rtd_to_codec(rtd, 0);
375+
w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction);
376+
swidget = w->dobj.private;
377+
sdev = snd_soc_component_get_drvdata(swidget->scomp);
378+
sdai = swidget->private;
379+
ops = sdai->platform_private;
472380

473381
ret = hda_link_dma_cleanup(hext_stream->link_substream,
474382
hext_stream,
475383
cpu_dai, codec_dai);
476384
if (ret < 0)
477385
return ret;
478386

479-
/* for consistency with TRIGGER_SUSPEND we free DAI resources */
480-
ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai);
481-
if (ret < 0)
482-
return ret;
387+
/* for consistency with TRIGGER_SUSPEND */
388+
if (ops->post_trigger) {
389+
ret = ops->post_trigger(sdev, cpu_dai,
390+
hext_stream->link_substream,
391+
SNDRV_PCM_TRIGGER_SUSPEND);
392+
if (ret < 0)
393+
return ret;
394+
}
483395
}
484396
}
485397

486398
return 0;
487399
}
488400

489-
static const struct snd_soc_dai_ops ipc4_hda_dai_ops = {
490-
.hw_params = hda_dai_hw_params,
491-
.hw_free = hda_dai_hw_free,
492-
.trigger = ipc4_hda_dai_trigger,
493-
.prepare = hda_dai_prepare,
494-
};
495-
496401
#endif
497402

498403
void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
499404
{
500405
int i;
501406

502-
switch (sdev->pdata->ipc_type) {
503-
case SOF_IPC:
504-
for (i = 0; i < ops->num_drv; i++) {
505-
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
506-
if (strstr(ops->drv[i].name, "iDisp") ||
507-
strstr(ops->drv[i].name, "Analog") ||
508-
strstr(ops->drv[i].name, "Digital"))
509-
ops->drv[i].ops = &ipc3_hda_dai_ops;
510-
#endif
511-
}
512-
break;
513-
case SOF_INTEL_IPC4:
514-
{
515-
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
516-
517-
for (i = 0; i < ops->num_drv; i++) {
407+
for (i = 0; i < ops->num_drv; i++) {
518408
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
519-
if (strstr(ops->drv[i].name, "iDisp") ||
520-
strstr(ops->drv[i].name, "Analog") ||
521-
strstr(ops->drv[i].name, "Digital"))
522-
ops->drv[i].ops = &ipc4_hda_dai_ops;
409+
if (strstr(ops->drv[i].name, "iDisp") ||
410+
strstr(ops->drv[i].name, "Analog") ||
411+
strstr(ops->drv[i].name, "Digital"))
412+
ops->drv[i].ops = &hda_dai_ops;
523413
#endif
524-
}
414+
}
525415

526-
if (!hda_use_tplg_nhlt)
527-
ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
416+
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) {
417+
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
528418

529-
break;
530-
}
531-
default:
532-
break;
419+
ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
533420
}
534421
}
535422

sound/soc/sof/intel/hda.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,5 +962,7 @@ struct hda_dai_widget_dma_ops {
962962

963963
const struct hda_dai_widget_dma_ops *
964964
hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
965+
int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
966+
struct snd_sof_dai_config_data *data);
965967

966968
#endif

0 commit comments

Comments
 (0)