ASoC: SOF: Intel: hda: couple host and link DMA during FE hw_free
Host and link DMA are decoupled during FE hw_params. So, they must be coupled in hw_free if the link DMA channel is idle. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
7077a07a72
commit
93146bc22f
|
@ -61,6 +61,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
|
|||
.pcm_open = hda_dsp_pcm_open,
|
||||
.pcm_close = hda_dsp_pcm_close,
|
||||
.pcm_hw_params = hda_dsp_pcm_hw_params,
|
||||
.pcm_hw_free = hda_dsp_stream_hw_free,
|
||||
.pcm_trigger = hda_dsp_pcm_trigger,
|
||||
.pcm_pointer = hda_dsp_pcm_pointer,
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
|
|||
.pcm_open = hda_dsp_pcm_open,
|
||||
.pcm_close = hda_dsp_pcm_close,
|
||||
.pcm_hw_params = hda_dsp_pcm_hw_params,
|
||||
.pcm_hw_free = hda_dsp_stream_hw_free,
|
||||
.pcm_trigger = hda_dsp_pcm_trigger,
|
||||
.pcm_pointer = hda_dsp_pcm_pointer,
|
||||
|
||||
|
|
|
@ -438,6 +438,26 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct hdac_stream *stream = substream->runtime->private_data;
|
||||
struct hdac_ext_stream *link_dev = container_of(stream,
|
||||
struct hdac_ext_stream,
|
||||
hstream);
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
u32 mask = 0x1 << stream->index;
|
||||
|
||||
spin_lock(&bus->reg_lock);
|
||||
/* couple host and link DMA if link DMA channel is idle */
|
||||
if (!link_dev->link_locked)
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR,
|
||||
SOF_HDA_REG_PP_PPCTL, mask, 0);
|
||||
spin_unlock(&bus->reg_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
irqreturn_t hda_dsp_stream_interrupt(int irq, void *context)
|
||||
{
|
||||
struct hdac_bus *bus = context;
|
||||
|
|
|
@ -468,6 +468,8 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
|
|||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params);
|
||||
int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream);
|
||||
int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream, int cmd);
|
||||
snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
|
||||
|
|
|
@ -287,6 +287,17 @@ snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* host stream hw free */
|
||||
static inline int
|
||||
snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
|
||||
return sof_ops(sdev)->pcm_hw_free(sdev, substream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* host stream trigger */
|
||||
static inline int
|
||||
snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
|
||||
|
|
|
@ -251,6 +251,13 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
|
|||
|
||||
cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
|
||||
if (ret < 0)
|
||||
dev_err(sdev->dev, "error: platform hw free failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,10 @@ struct snd_sof_dsp_ops {
|
|||
struct snd_pcm_hw_params *params,
|
||||
struct sof_ipc_stream_params *ipc_params); /* optional */
|
||||
|
||||
/* host stream hw_free */
|
||||
int (*pcm_hw_free)(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream); /* optional */
|
||||
|
||||
/* host stream trigger */
|
||||
int (*pcm_trigger)(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream,
|
||||
|
|
Loading…
Reference in New Issue