diff options
author | Jeeja KP <jeeja.kp@intel.com> | 2016-06-03 08:59:34 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-06-07 09:19:11 -0400 |
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) | |||
1130 | return 0; | 1130 | return 0; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | /* | ||
1134 | * Reset the pipeline by sending set pipe state IPC this will reset the DMA | ||
1135 | * from the DSP side | ||
1136 | */ | ||
1137 | int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | ||
1138 | { | ||
1139 | int ret; | ||
1140 | |||
1141 | /* If pipe was not created in FW, do not try to pause or delete */ | ||
1142 | if (pipe->state < SKL_PIPE_PAUSED) | ||
1143 | return 0; | ||
1144 | |||
1145 | ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); | ||
1146 | if (ret < 0) { | ||
1147 | dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret); | ||
1148 | return ret; | ||
1149 | } | ||
1150 | |||
1151 | pipe->state = SKL_PIPE_RESET; | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1133 | /* Algo parameter set helper function */ | 1156 | /* Algo parameter set helper function */ |
1134 | int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, | 1157 | int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, |
1135 | u32 param_id, struct skl_module_cfg *mcfg) | 1158 | 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, | |||
227 | struct snd_soc_dai *dai) | 227 | struct snd_soc_dai *dai) |
228 | { | 228 | { |
229 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | 229 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); |
230 | struct skl *skl = get_skl_ctx(dai->dev); | ||
230 | unsigned int format_val; | 231 | unsigned int format_val; |
231 | int err; | 232 | int err; |
233 | struct skl_module_cfg *mconfig; | ||
232 | 234 | ||
233 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | 235 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); |
234 | 236 | ||
237 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); | ||
238 | |||
235 | format_val = skl_get_format(substream, dai); | 239 | format_val = skl_get_format(substream, dai); |
236 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", | 240 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", |
237 | hdac_stream(stream)->stream_tag, format_val); | 241 | hdac_stream(stream)->stream_tag, format_val); |
238 | snd_hdac_stream_reset(hdac_stream(stream)); | 242 | snd_hdac_stream_reset(hdac_stream(stream)); |
239 | 243 | ||
244 | /* In case of XRUN recovery, reset the FW pipe to clean state */ | ||
245 | if (mconfig && (substream->runtime->status->state == | ||
246 | SNDRV_PCM_STATE_XRUN)) | ||
247 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); | ||
248 | |||
240 | err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); | 249 | err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); |
241 | if (err < 0) | 250 | if (err < 0) |
242 | return err; | 251 | return err; |
@@ -521,6 +530,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, | |||
521 | struct skl_dma_params *dma_params; | 530 | struct skl_dma_params *dma_params; |
522 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 531 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
523 | struct hdac_ext_link *link; | 532 | struct hdac_ext_link *link; |
533 | struct skl *skl = get_skl_ctx(dai->dev); | ||
534 | struct skl_module_cfg *mconfig = NULL; | ||
524 | 535 | ||
525 | dma_params = (struct skl_dma_params *) | 536 | dma_params = (struct skl_dma_params *) |
526 | snd_soc_dai_get_dma_data(codec_dai, substream); | 537 | snd_soc_dai_get_dma_data(codec_dai, substream); |
@@ -535,6 +546,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, | |||
535 | 546 | ||
536 | snd_hdac_ext_link_stream_reset(link_dev); | 547 | snd_hdac_ext_link_stream_reset(link_dev); |
537 | 548 | ||
549 | /* In case of XRUN recovery, reset the FW pipe to clean state */ | ||
550 | mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); | ||
551 | if (mconfig && (substream->runtime->status->state == | ||
552 | SNDRV_PCM_STATE_XRUN)) | ||
553 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); | ||
554 | |||
538 | snd_hdac_ext_link_stream_setup(link_dev, format_val); | 555 | snd_hdac_ext_link_stream_setup(link_dev, format_val); |
539 | 556 | ||
540 | snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); | 557 | 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 { | |||
244 | SKL_PIPE_INVALID = 0, | 244 | SKL_PIPE_INVALID = 0, |
245 | SKL_PIPE_CREATED = 1, | 245 | SKL_PIPE_CREATED = 1, |
246 | SKL_PIPE_PAUSED = 2, | 246 | SKL_PIPE_PAUSED = 2, |
247 | SKL_PIPE_STARTED = 3 | 247 | SKL_PIPE_STARTED = 3, |
248 | SKL_PIPE_RESET = 4 | ||
248 | }; | 249 | }; |
249 | 250 | ||
250 | struct skl_pipe_module { | 251 | struct skl_pipe_module { |
@@ -357,6 +358,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | |||
357 | 358 | ||
358 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 359 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); |
359 | 360 | ||
361 | int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
362 | |||
360 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); | 363 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); |
361 | 364 | ||
362 | int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg | 365 | int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg |