diff options
author | Vinod Koul <vinod.koul@intel.com> | 2014-10-31 03:08:20 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-10-31 08:46:45 -0400 |
commit | d62f2a08b9d657344b2e271e8274f9d8f746e543 (patch) | |
tree | d6e6a73b8f824be8afcd27ebb23edece55e94b1c | |
parent | 1a6db0bd26a72027d6a5ea006d64d4021fd0326e (diff) |
ASoC: Intel: sst: add runtime power management handling
This patch adds the runtime pm handlers, the driver already has code for
get/put for runtime pm and only these handlers being missing.
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@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/sst/sst.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c index fa3421706e4e..7b8a110b213d 100644 --- a/sound/soc/intel/sst/sst.c +++ b/sound/soc/intel/sst/sst.c | |||
@@ -152,6 +152,23 @@ static irqreturn_t intel_sst_irq_thread_mrfld(int irq, void *context) | |||
152 | return IRQ_HANDLED; | 152 | return IRQ_HANDLED; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int sst_save_dsp_context_v2(struct intel_sst_drv *sst) | ||
156 | { | ||
157 | int ret = 0; | ||
158 | |||
159 | ret = sst_prepare_and_post_msg(sst, SST_TASK_ID_MEDIA, IPC_CMD, | ||
160 | IPC_PREP_D3, PIPE_RSVD, 0, NULL, NULL, | ||
161 | true, true, false, true); | ||
162 | |||
163 | if (ret < 0) { | ||
164 | dev_err(sst->dev, "not suspending FW!!, Err: %d\n", ret); | ||
165 | return -EIO; | ||
166 | } | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | |||
155 | static struct intel_sst_ops mrfld_ops = { | 172 | static struct intel_sst_ops mrfld_ops = { |
156 | .interrupt = intel_sst_interrupt_mrfld, | 173 | .interrupt = intel_sst_interrupt_mrfld, |
157 | .irq_thread = intel_sst_irq_thread_mrfld, | 174 | .irq_thread = intel_sst_irq_thread_mrfld, |
@@ -160,6 +177,7 @@ static struct intel_sst_ops mrfld_ops = { | |||
160 | .reset = intel_sst_reset_dsp_mrfld, | 177 | .reset = intel_sst_reset_dsp_mrfld, |
161 | .post_message = sst_post_message_mrfld, | 178 | .post_message = sst_post_message_mrfld, |
162 | .process_reply = sst_process_reply_mrfld, | 179 | .process_reply = sst_process_reply_mrfld, |
180 | .save_dsp_context = sst_save_dsp_context_v2, | ||
163 | .alloc_stream = sst_alloc_stream_mrfld, | 181 | .alloc_stream = sst_alloc_stream_mrfld, |
164 | .post_download = sst_post_download_mrfld, | 182 | .post_download = sst_post_download_mrfld, |
165 | }; | 183 | }; |
@@ -418,6 +436,50 @@ static void intel_sst_remove(struct pci_dev *pci) | |||
418 | pci_set_drvdata(pci, NULL); | 436 | pci_set_drvdata(pci, NULL); |
419 | } | 437 | } |
420 | 438 | ||
439 | static int intel_sst_runtime_suspend(struct device *dev) | ||
440 | { | ||
441 | int ret = 0; | ||
442 | struct intel_sst_drv *ctx = dev_get_drvdata(dev); | ||
443 | |||
444 | if (ctx->sst_state == SST_RESET) { | ||
445 | dev_dbg(dev, "LPE is already in RESET state, No action\n"); | ||
446 | return 0; | ||
447 | } | ||
448 | /* save fw context */ | ||
449 | if (ctx->ops->save_dsp_context(ctx)) | ||
450 | return -EBUSY; | ||
451 | |||
452 | /* Move the SST state to Reset */ | ||
453 | sst_set_fw_state_locked(ctx, SST_RESET); | ||
454 | |||
455 | synchronize_irq(ctx->irq_num); | ||
456 | flush_workqueue(ctx->post_msg_wq); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | static int intel_sst_runtime_resume(struct device *dev) | ||
462 | { | ||
463 | int ret = 0; | ||
464 | struct intel_sst_drv *ctx = dev_get_drvdata(dev); | ||
465 | |||
466 | mutex_lock(&ctx->sst_lock); | ||
467 | if (ctx->sst_state == SST_RESET) { | ||
468 | ret = sst_load_fw(ctx); | ||
469 | if (ret) { | ||
470 | dev_err(dev, "FW download fail %d\n", ret); | ||
471 | ctx->sst_state = SST_RESET; | ||
472 | } | ||
473 | } | ||
474 | mutex_unlock(&ctx->sst_lock); | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | static const struct dev_pm_ops intel_sst_pm = { | ||
479 | .runtime_suspend = intel_sst_runtime_suspend, | ||
480 | .runtime_resume = intel_sst_runtime_resume, | ||
481 | }; | ||
482 | |||
421 | /* PCI Routines */ | 483 | /* PCI Routines */ |
422 | static struct pci_device_id intel_sst_ids[] = { | 484 | static struct pci_device_id intel_sst_ids[] = { |
423 | { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, | 485 | { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, |
@@ -429,6 +491,11 @@ static struct pci_driver sst_driver = { | |||
429 | .id_table = intel_sst_ids, | 491 | .id_table = intel_sst_ids, |
430 | .probe = intel_sst_probe, | 492 | .probe = intel_sst_probe, |
431 | .remove = intel_sst_remove, | 493 | .remove = intel_sst_remove, |
494 | #ifdef CONFIG_PM | ||
495 | .driver = { | ||
496 | .pm = &intel_sst_pm, | ||
497 | }, | ||
498 | #endif | ||
432 | }; | 499 | }; |
433 | 500 | ||
434 | module_pci_driver(sst_driver); | 501 | module_pci_driver(sst_driver); |