Skip to content

Commit 31cdf00

Browse files
committed
ASoC: SOF: Intel: hda-dai: improve SSP DAI handling for dynamic pipelines
In order to keep the widget use_count balanced, make sure the DAI widgets are allocated once in hw_params and released in hw_free. A 'setup' status flag is used to deal with cases where the .hw_params callback is invoked multiple times, and likewise with cases where hw_free is invoked without hw_params being called first (which can happen if the FE hw_params fails). In addition, this patch frees the widgets in the suspend transition, and reallocates them in the .prepare callback. The 'setup' flag helps in this case differentiate between resume (setup needed) and xruns (setup not needed). This balanced operation was not needed previously but will be required when SOF dynamic pipelines are enabled. Co-developed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
1 parent ca3abbe commit 31cdf00

1 file changed

Lines changed: 80 additions & 2 deletions

File tree

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

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = {
442442

443443
#endif
444444

445+
/* only one flag used so far to harden hw_params/hw_free/trigger/prepare */
446+
struct ssp_dai_dma_data {
447+
bool setup;
448+
};
449+
445450
static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
446451
bool setup)
447452
{
@@ -471,22 +476,95 @@ static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd
471476
return hda_ctrl_dai_widget_free(w);
472477
}
473478

479+
static int ssp_dai_startup(struct snd_pcm_substream *substream,
480+
struct snd_soc_dai *dai)
481+
{
482+
struct ssp_dai_dma_data *dma_data;
483+
484+
dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
485+
if (!dma_data)
486+
return -ENOMEM;
487+
488+
snd_soc_dai_set_dma_data(dai, substream, dma_data);
489+
490+
return 0;
491+
}
492+
493+
static int ssp_dai_setup(struct snd_pcm_substream *substream,
494+
struct snd_soc_dai *dai,
495+
bool setup)
496+
{
497+
struct ssp_dai_dma_data *dma_data;
498+
int ret = 0;
499+
500+
dma_data = snd_soc_dai_get_dma_data(dai, substream);
501+
if (!dma_data) {
502+
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
503+
return -EIO;
504+
}
505+
506+
if (dma_data->setup != setup) {
507+
ret = ssp_dai_setup_or_free(substream, dai, setup);
508+
if (!ret)
509+
dma_data->setup = setup;
510+
}
511+
return ret;
512+
}
513+
474514
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
475515
struct snd_pcm_hw_params *params,
476516
struct snd_soc_dai *dai)
477517
{
478-
return ssp_dai_setup_or_free(substream, dai, true);
518+
/* params are ignored for now */
519+
return ssp_dai_setup(substream, dai, true);
520+
}
521+
522+
static int ssp_dai_prepare(struct snd_pcm_substream *substream,
523+
struct snd_soc_dai *dai)
524+
{
525+
/*
526+
* the SSP will only be reconfigured during resume operations and
527+
* not in case of xruns
528+
*/
529+
return ssp_dai_setup(substream, dai, true);
530+
}
531+
532+
static int ssp_dai_trigger(struct snd_pcm_substream *substream,
533+
int cmd, struct snd_soc_dai *dai)
534+
{
535+
if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
536+
return 0;
537+
538+
return ssp_dai_setup(substream, dai, false);
479539
}
480540

481541
static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
482542
struct snd_soc_dai *dai)
483543
{
484-
return ssp_dai_setup_or_free(substream, dai, false);
544+
return ssp_dai_setup(substream, dai, false);
545+
}
546+
547+
static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
548+
struct snd_soc_dai *dai)
549+
{
550+
struct ssp_dai_dma_data *dma_data;
551+
552+
dma_data = snd_soc_dai_get_dma_data(dai, substream);
553+
if (!dma_data) {
554+
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
555+
return;
556+
}
557+
snd_soc_dai_set_dma_data(dai, substream, NULL);
558+
kfree(dma_data);
485559
}
486560

487561
static const struct snd_soc_dai_ops ssp_dai_ops = {
562+
.startup = ssp_dai_startup,
488563
.hw_params = ssp_dai_hw_params,
564+
.prepare = ssp_dai_prepare,
565+
.trigger = ssp_dai_trigger,
489566
.hw_free = ssp_dai_hw_free,
567+
.shutdown = ssp_dai_shutdown,
490568
};
491569

492570
/*

0 commit comments

Comments
 (0)