diff options
Diffstat (limited to 'sound/soc/intel/sst-baytrail-pcm.c')
-rw-r--r-- | sound/soc/intel/sst-baytrail-pcm.c | 43 |
1 files changed, 15 insertions, 28 deletions
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 599401c0c655..eab1c7d85187 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -59,6 +59,9 @@ struct sst_byt_priv_data { | |||
59 | 59 | ||
60 | /* DAI data */ | 60 | /* DAI data */ |
61 | struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; | 61 | struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; |
62 | |||
63 | /* flag indicating is stream context restore needed after suspend */ | ||
64 | bool restore_stream; | ||
62 | }; | 65 | }; |
63 | 66 | ||
64 | /* this may get called several times by oss emulation */ | 67 | /* this may get called several times by oss emulation */ |
@@ -184,7 +187,10 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
184 | sst_byt_stream_start(byt, pcm_data->stream, 0); | 187 | sst_byt_stream_start(byt, pcm_data->stream, 0); |
185 | break; | 188 | break; |
186 | case SNDRV_PCM_TRIGGER_RESUME: | 189 | case SNDRV_PCM_TRIGGER_RESUME: |
187 | schedule_work(&pcm_data->work); | 190 | if (pdata->restore_stream == true) |
191 | schedule_work(&pcm_data->work); | ||
192 | else | ||
193 | sst_byt_stream_resume(byt, pcm_data->stream); | ||
188 | break; | 194 | break; |
189 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 195 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
190 | sst_byt_stream_resume(byt, pcm_data->stream); | 196 | sst_byt_stream_resume(byt, pcm_data->stream); |
@@ -193,6 +199,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
193 | sst_byt_stream_stop(byt, pcm_data->stream); | 199 | sst_byt_stream_stop(byt, pcm_data->stream); |
194 | break; | 200 | break; |
195 | case SNDRV_PCM_TRIGGER_SUSPEND: | 201 | case SNDRV_PCM_TRIGGER_SUSPEND: |
202 | pdata->restore_stream = false; | ||
196 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 203 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
197 | sst_byt_stream_pause(byt, pcm_data->stream); | 204 | sst_byt_stream_pause(byt, pcm_data->stream); |
198 | break; | 205 | break; |
@@ -404,26 +411,10 @@ static const struct snd_soc_component_driver byt_dai_component = { | |||
404 | }; | 411 | }; |
405 | 412 | ||
406 | #ifdef CONFIG_PM | 413 | #ifdef CONFIG_PM |
407 | static int sst_byt_pcm_dev_suspend_noirq(struct device *dev) | ||
408 | { | ||
409 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | ||
410 | int ret; | ||
411 | |||
412 | dev_dbg(dev, "suspending noirq\n"); | ||
413 | |||
414 | /* at this point all streams will be stopped and context saved */ | ||
415 | ret = sst_byt_dsp_suspend_noirq(dev, sst_pdata); | ||
416 | if (ret < 0) { | ||
417 | dev_err(dev, "failed to suspend %d\n", ret); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | static int sst_byt_pcm_dev_suspend_late(struct device *dev) | 414 | static int sst_byt_pcm_dev_suspend_late(struct device *dev) |
425 | { | 415 | { |
426 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | 416 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); |
417 | struct sst_byt_priv_data *priv_data = dev_get_drvdata(dev); | ||
427 | int ret; | 418 | int ret; |
428 | 419 | ||
429 | dev_dbg(dev, "suspending late\n"); | 420 | dev_dbg(dev, "suspending late\n"); |
@@ -434,34 +425,30 @@ static int sst_byt_pcm_dev_suspend_late(struct device *dev) | |||
434 | return ret; | 425 | return ret; |
435 | } | 426 | } |
436 | 427 | ||
428 | priv_data->restore_stream = true; | ||
429 | |||
437 | return ret; | 430 | return ret; |
438 | } | 431 | } |
439 | 432 | ||
440 | static int sst_byt_pcm_dev_resume_early(struct device *dev) | 433 | static int sst_byt_pcm_dev_resume_early(struct device *dev) |
441 | { | 434 | { |
442 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | 435 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); |
436 | int ret; | ||
443 | 437 | ||
444 | dev_dbg(dev, "resume early\n"); | 438 | dev_dbg(dev, "resume early\n"); |
445 | 439 | ||
446 | /* load fw and boot DSP */ | 440 | /* load fw and boot DSP */ |
447 | return sst_byt_dsp_boot(dev, sst_pdata); | 441 | ret = sst_byt_dsp_boot(dev, sst_pdata); |
448 | } | 442 | if (ret) |
449 | 443 | return ret; | |
450 | static int sst_byt_pcm_dev_resume(struct device *dev) | ||
451 | { | ||
452 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | ||
453 | |||
454 | dev_dbg(dev, "resume\n"); | ||
455 | 444 | ||
456 | /* wait for FW to finish booting */ | 445 | /* wait for FW to finish booting */ |
457 | return sst_byt_dsp_wait_for_ready(dev, sst_pdata); | 446 | return sst_byt_dsp_wait_for_ready(dev, sst_pdata); |
458 | } | 447 | } |
459 | 448 | ||
460 | static const struct dev_pm_ops sst_byt_pm_ops = { | 449 | static const struct dev_pm_ops sst_byt_pm_ops = { |
461 | .suspend_noirq = sst_byt_pcm_dev_suspend_noirq, | ||
462 | .suspend_late = sst_byt_pcm_dev_suspend_late, | 450 | .suspend_late = sst_byt_pcm_dev_suspend_late, |
463 | .resume_early = sst_byt_pcm_dev_resume_early, | 451 | .resume_early = sst_byt_pcm_dev_resume_early, |
464 | .resume = sst_byt_pcm_dev_resume, | ||
465 | }; | 452 | }; |
466 | 453 | ||
467 | #define SST_BYT_PM_OPS (&sst_byt_pm_ops) | 454 | #define SST_BYT_PM_OPS (&sst_byt_pm_ops) |