diff options
author | Jeeja KP <jeeja.kp@intel.com> | 2016-06-03 18:29:34 +0530 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-06-07 14:19:11 +0100 |
commit | 2004432f946e985fe98b67d515c52d69747016f9 (patch) | |
tree | e6b9221499ceaf6f7675f70678ec1dab8182aef0 | |
parent | de15996eab99b352926fb956d472d24d46c60309 (diff) |
ASoC: Intel: Skylake: Reset DSP pipe when host/link DMA is reset
In case of XRUN recovery PCM prepare will be called. In this case
Host/Link DMAs are reset and reconfigured, hence the corresponding
FE/BE pipe needs to be reset in order to get to a clean state.
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/intel/skylake/skl-messages.c | 23 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-pcm.c | 17 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.h | 5 |
3 files changed, 44 insertions, 1 deletions
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 226db84ba20f..c6824036fc24 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -1130,6 +1130,29 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) return 0; } +/* + * Reset the pipeline by sending set pipe state IPC this will reset the DMA + * from the DSP side + */ +int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +{ + int ret; + + /* If pipe was not created in FW, do not try to pause or delete */ + if (pipe->state < SKL_PIPE_PAUSED) + return 0; + + ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); + if (ret < 0) { + dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret); + return ret; + } + + pipe->state = SKL_PIPE_RESET; + + return 0; +} + /* Algo parameter set helper function */ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg) diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 7c81b31748ff..ff0491716e06 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -227,16 +227,25 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); + struct skl *skl = get_skl_ctx(dai->dev); unsigned int format_val; int err; + struct skl_module_cfg *mconfig; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); + mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); + format_val = skl_get_format(substream, dai); dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", hdac_stream(stream)->stream_tag, format_val); snd_hdac_stream_reset(hdac_stream(stream)); + /* In case of XRUN recovery, reset the FW pipe to clean state */ + if (mconfig && (substream->runtime->status->state == + SNDRV_PCM_STATE_XRUN)) + skl_reset_pipe(skl->skl_sst, mconfig->pipe); + err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); if (err < 0) return err; @@ -521,6 +530,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, struct skl_dma_params *dma_params; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct hdac_ext_link *link; + struct skl *skl = get_skl_ctx(dai->dev); + struct skl_module_cfg *mconfig = NULL; dma_params = (struct skl_dma_params *) snd_soc_dai_get_dma_data(codec_dai, substream); @@ -535,6 +546,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, snd_hdac_ext_link_stream_reset(link_dev); + /* In case of XRUN recovery, reset the FW pipe to clean state */ + mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); + if (mconfig && (substream->runtime->status->state == + SNDRV_PCM_STATE_XRUN)) + skl_reset_pipe(skl->skl_sst, mconfig->pipe); + snd_hdac_ext_link_stream_setup(link_dev, format_val); snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index e4b399cd7868..d4a58bcd8c7d 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -244,7 +244,8 @@ enum skl_pipe_state { SKL_PIPE_INVALID = 0, SKL_PIPE_CREATED = 1, SKL_PIPE_PAUSED = 2, - SKL_PIPE_STARTED = 3 + SKL_PIPE_STARTED = 3, + SKL_PIPE_RESET = 4 }; struct skl_pipe_module { @@ -357,6 +358,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); + int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg |