diff options
| -rw-r--r-- | sound/soc/intel/sst-haswell-pcm.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index ba585a75878d..50fea077898b 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
| @@ -99,6 +99,7 @@ struct hsw_pcm_data { | |||
| 99 | struct snd_compr_stream *cstream; | 99 | struct snd_compr_stream *cstream; |
| 100 | unsigned int wpos; | 100 | unsigned int wpos; |
| 101 | struct mutex mutex; | 101 | struct mutex mutex; |
| 102 | bool allocated; | ||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | /* private data for the driver */ | 105 | /* private data for the driver */ |
| @@ -113,6 +114,8 @@ struct hsw_priv_data { | |||
| 113 | struct hsw_pcm_data pcm[HSW_PCM_COUNT]; | 114 | struct hsw_pcm_data pcm[HSW_PCM_COUNT]; |
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 117 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); | ||
| 118 | |||
| 116 | static inline u32 hsw_mixer_to_ipc(unsigned int value) | 119 | static inline u32 hsw_mixer_to_ipc(unsigned int value) |
| 117 | { | 120 | { |
| 118 | if (value >= ARRAY_SIZE(volume_map)) | 121 | if (value >= ARRAY_SIZE(volume_map)) |
| @@ -322,6 +325,29 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 322 | u8 channels; | 325 | u8 channels; |
| 323 | int ret; | 326 | int ret; |
| 324 | 327 | ||
| 328 | /* check if we are being called a subsequent time */ | ||
| 329 | if (pcm_data->allocated) { | ||
| 330 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); | ||
| 331 | if (ret < 0) | ||
| 332 | dev_dbg(rtd->dev, "error: reset stream failed %d\n", | ||
| 333 | ret); | ||
| 334 | |||
| 335 | ret = sst_hsw_stream_free(hsw, pcm_data->stream); | ||
| 336 | if (ret < 0) { | ||
| 337 | dev_dbg(rtd->dev, "error: free stream failed %d\n", | ||
| 338 | ret); | ||
| 339 | return ret; | ||
| 340 | } | ||
| 341 | pcm_data->allocated = false; | ||
| 342 | |||
| 343 | pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, | ||
| 344 | hsw_notify_pointer, pcm_data); | ||
| 345 | if (pcm_data->stream == NULL) { | ||
| 346 | dev_err(rtd->dev, "error: failed to create stream\n"); | ||
| 347 | return -EINVAL; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 325 | /* stream direction */ | 351 | /* stream direction */ |
| 326 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 352 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 327 | path_id = SST_HSW_STREAM_PATH_SSP0_OUT; | 353 | path_id = SST_HSW_STREAM_PATH_SSP0_OUT; |
| @@ -475,6 +501,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 475 | dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); | 501 | dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); |
| 476 | return ret; | 502 | return ret; |
| 477 | } | 503 | } |
| 504 | pcm_data->allocated = true; | ||
| 478 | 505 | ||
| 479 | ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); | 506 | ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); |
| 480 | if (ret < 0) | 507 | if (ret < 0) |
| @@ -607,6 +634,7 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream) | |||
| 607 | dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); | 634 | dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); |
| 608 | goto out; | 635 | goto out; |
| 609 | } | 636 | } |
| 637 | pcm_data->allocated = 0; | ||
| 610 | pcm_data->stream = NULL; | 638 | pcm_data->stream = NULL; |
| 611 | 639 | ||
| 612 | out: | 640 | out: |
