aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVinod Koul <vinod.koul@intel.com>2015-02-24 01:09:44 -0500
committerMark Brown <broonie@kernel.org>2015-02-24 03:00:34 -0500
commit4a8448d4289d7210053a43f9f21e42929beb159b (patch)
treeacc3cb3ca21c065cd473a35bf0f394193b2815b5
parent5c88b4e91d3b6a3d701d7b134fa945e6309e7068 (diff)
ASoC: Intel: add pm support in sst ipc driver
This adds support for system pm support. We need to save the dsp memory which gets lost on suspend and restore that on resume 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.c128
-rw-r--r--sound/soc/intel/sst/sst.h9
2 files changed, 137 insertions, 0 deletions
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c
index 8a8d56a146e7..8f938112a01f 100644
--- a/sound/soc/intel/sst/sst.c
+++ b/sound/soc/intel/sst/sst.c
@@ -415,6 +415,83 @@ static int intel_sst_runtime_suspend(struct device *dev)
415 return ret; 415 return ret;
416} 416}
417 417
418static int intel_sst_suspend(struct device *dev)
419{
420 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
421 struct sst_fw_save *fw_save;
422 int i, ret = 0;
423
424 /* check first if we are already in SW reset */
425 if (ctx->sst_state == SST_RESET)
426 return 0;
427
428 /*
429 * check if any stream is active and running
430 * they should already by suspend by soc_suspend
431 */
432 for (i = 1; i <= ctx->info.max_streams; i++) {
433 struct stream_info *stream = &ctx->streams[i];
434
435 if (stream->status == STREAM_RUNNING) {
436 dev_err(dev, "stream %d is running, cant susupend, abort\n", i);
437 return -EBUSY;
438 }
439 }
440 synchronize_irq(ctx->irq_num);
441 flush_workqueue(ctx->post_msg_wq);
442
443 /* Move the SST state to Reset */
444 sst_set_fw_state_locked(ctx, SST_RESET);
445
446 /* tell DSP we are suspending */
447 if (ctx->ops->save_dsp_context(ctx))
448 return -EBUSY;
449
450 /* save the memories */
451 fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
452 if (!fw_save)
453 return -ENOMEM;
454 fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
455 if (!fw_save->iram) {
456 ret = -ENOMEM;
457 goto iram;
458 }
459 fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
460 if (!fw_save->dram) {
461 ret = -ENOMEM;
462 goto dram;
463 }
464 fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
465 if (!fw_save->sram) {
466 ret = -ENOMEM;
467 goto sram;
468 }
469
470 fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
471 if (!fw_save->ddr) {
472 ret = -ENOMEM;
473 goto ddr;
474 }
475
476 memcpy32_fromio(fw_save->iram, ctx->iram, ctx->iram_end - ctx->iram_base);
477 memcpy32_fromio(fw_save->dram, ctx->dram, ctx->dram_end - ctx->dram_base);
478 memcpy32_fromio(fw_save->sram, ctx->mailbox, SST_MAILBOX_SIZE);
479 memcpy32_fromio(fw_save->ddr, ctx->ddr, ctx->ddr_end - ctx->ddr_base);
480
481 ctx->fw_save = fw_save;
482 ctx->ops->reset(ctx);
483 return 0;
484ddr:
485 kfree(fw_save->sram);
486sram:
487 kfree(fw_save->dram);
488dram:
489 kfree(fw_save->iram);
490iram:
491 kfree(fw_save);
492 return ret;
493}
494
418static int intel_sst_runtime_resume(struct device *dev) 495static int intel_sst_runtime_resume(struct device *dev)
419{ 496{
420 int ret = 0; 497 int ret = 0;
@@ -430,7 +507,58 @@ static int intel_sst_runtime_resume(struct device *dev)
430 return ret; 507 return ret;
431} 508}
432 509
510static int intel_sst_resume(struct device *dev)
511{
512 struct intel_sst_drv *ctx = dev_get_drvdata(dev);
513 struct sst_fw_save *fw_save = ctx->fw_save;
514 int ret = 0;
515 struct sst_block *block;
516
517 if (!fw_save)
518 return intel_sst_runtime_resume(dev);
519
520 sst_set_fw_state_locked(ctx, SST_FW_LOADING);
521
522 /* we have to restore the memory saved */
523 ctx->ops->reset(ctx);
524
525 ctx->fw_save = NULL;
526
527 memcpy32_toio(ctx->iram, fw_save->iram, ctx->iram_end - ctx->iram_base);
528 memcpy32_toio(ctx->dram, fw_save->dram, ctx->dram_end - ctx->dram_base);
529 memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
530 memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
531
532 kfree(fw_save->sram);
533 kfree(fw_save->dram);
534 kfree(fw_save->iram);
535 kfree(fw_save->ddr);
536 kfree(fw_save);
537
538 block = sst_create_block(ctx, 0, FW_DWNL_ID);
539 if (block == NULL)
540 return -ENOMEM;
541
542
543 /* start and wait for ack */
544 ctx->ops->start(ctx);
545 ret = sst_wait_timeout(ctx, block);
546 if (ret) {
547 dev_err(ctx->dev, "fw download failed %d\n", ret);
548 /* FW download failed due to timeout */
549 ret = -EBUSY;
550
551 } else {
552 sst_set_fw_state_locked(ctx, SST_FW_RUNNING);
553 }
554
555 sst_free_block(ctx, block);
556 return ret;
557}
558
433const struct dev_pm_ops intel_sst_pm = { 559const struct dev_pm_ops intel_sst_pm = {
560 .suspend = intel_sst_suspend,
561 .resume = intel_sst_resume,
434 .runtime_suspend = intel_sst_runtime_suspend, 562 .runtime_suspend = intel_sst_runtime_suspend,
435 .runtime_resume = intel_sst_runtime_resume, 563 .runtime_resume = intel_sst_runtime_resume,
436}; 564};
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h
index f793780a50a2..3f493862e98d 100644
--- a/sound/soc/intel/sst/sst.h
+++ b/sound/soc/intel/sst/sst.h
@@ -337,6 +337,13 @@ struct sst_shim_regs64 {
337 u64 csr2; 337 u64 csr2;
338}; 338};
339 339
340struct sst_fw_save {
341 void *iram;
342 void *dram;
343 void *sram;
344 void *ddr;
345};
346
340/** 347/**
341 * struct intel_sst_drv - driver ops 348 * struct intel_sst_drv - driver ops
342 * 349 *
@@ -428,6 +435,8 @@ struct intel_sst_drv {
428 * persistent till worker thread gets called 435 * persistent till worker thread gets called
429 */ 436 */
430 char firmware_name[FW_NAME_SIZE]; 437 char firmware_name[FW_NAME_SIZE];
438
439 struct sst_fw_save *fw_save;
431}; 440};
432 441
433/* misc definitions */ 442/* misc definitions */