diff options
Diffstat (limited to 'sound/soc/mxs/mxs-saif.c')
-rw-r--r-- | sound/soc/mxs/mxs-saif.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b56b8a0e8deb..54e622acac33 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
494 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | 494 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); |
495 | struct mxs_saif *master_saif; | 495 | struct mxs_saif *master_saif; |
496 | u32 delay; | 496 | u32 delay; |
497 | int ret; | ||
497 | 498 | ||
498 | master_saif = mxs_saif_get_master(saif); | 499 | master_saif = mxs_saif_get_master(saif); |
499 | if (!master_saif) | 500 | if (!master_saif) |
@@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
503 | case SNDRV_PCM_TRIGGER_START: | 504 | case SNDRV_PCM_TRIGGER_START: |
504 | case SNDRV_PCM_TRIGGER_RESUME: | 505 | case SNDRV_PCM_TRIGGER_RESUME: |
505 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 506 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
507 | if (saif->state == MXS_SAIF_STATE_RUNNING) | ||
508 | return 0; | ||
509 | |||
506 | dev_dbg(cpu_dai->dev, "start\n"); | 510 | dev_dbg(cpu_dai->dev, "start\n"); |
507 | 511 | ||
508 | clk_enable(master_saif->clk); | 512 | ret = clk_enable(master_saif->clk); |
509 | if (!master_saif->mclk_in_use) | 513 | if (ret) { |
510 | __raw_writel(BM_SAIF_CTRL_RUN, | 514 | dev_err(saif->dev, "Failed to enable master clock\n"); |
511 | master_saif->base + SAIF_CTRL + MXS_SET_ADDR); | 515 | return ret; |
516 | } | ||
512 | 517 | ||
513 | /* | 518 | /* |
514 | * If the saif's master is not himself, we also need to enable | 519 | * If the saif's master is not himself, we also need to enable |
515 | * itself clk for its internal basic logic to work. | 520 | * itself clk for its internal basic logic to work. |
516 | */ | 521 | */ |
517 | if (saif != master_saif) { | 522 | if (saif != master_saif) { |
518 | clk_enable(saif->clk); | 523 | ret = clk_enable(saif->clk); |
524 | if (ret) { | ||
525 | dev_err(saif->dev, "Failed to enable master clock\n"); | ||
526 | clk_disable(master_saif->clk); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
519 | __raw_writel(BM_SAIF_CTRL_RUN, | 530 | __raw_writel(BM_SAIF_CTRL_RUN, |
520 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | 531 | saif->base + SAIF_CTRL + MXS_SET_ADDR); |
521 | } | 532 | } |
522 | 533 | ||
534 | if (!master_saif->mclk_in_use) | ||
535 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
536 | master_saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
537 | |||
523 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 538 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
524 | /* | 539 | /* |
525 | * write data to saif data register to trigger | 540 | * write data to saif data register to trigger |
@@ -543,6 +558,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
543 | } | 558 | } |
544 | 559 | ||
545 | master_saif->ongoing = 1; | 560 | master_saif->ongoing = 1; |
561 | saif->state = MXS_SAIF_STATE_RUNNING; | ||
546 | 562 | ||
547 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", | 563 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", |
548 | __raw_readl(saif->base + SAIF_CTRL), | 564 | __raw_readl(saif->base + SAIF_CTRL), |
@@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
555 | case SNDRV_PCM_TRIGGER_SUSPEND: | 571 | case SNDRV_PCM_TRIGGER_SUSPEND: |
556 | case SNDRV_PCM_TRIGGER_STOP: | 572 | case SNDRV_PCM_TRIGGER_STOP: |
557 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 573 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
574 | if (saif->state == MXS_SAIF_STATE_STOPPED) | ||
575 | return 0; | ||
576 | |||
558 | dev_dbg(cpu_dai->dev, "stop\n"); | 577 | dev_dbg(cpu_dai->dev, "stop\n"); |
559 | 578 | ||
560 | /* wait a while for the current sample to complete */ | 579 | /* wait a while for the current sample to complete */ |
@@ -575,6 +594,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
575 | } | 594 | } |
576 | 595 | ||
577 | master_saif->ongoing = 0; | 596 | master_saif->ongoing = 0; |
597 | saif->state = MXS_SAIF_STATE_STOPPED; | ||
578 | 598 | ||
579 | break; | 599 | break; |
580 | default: | 600 | default: |
@@ -768,8 +788,8 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
768 | dev_warn(&pdev->dev, "failed to init clocks\n"); | 788 | dev_warn(&pdev->dev, "failed to init clocks\n"); |
769 | } | 789 | } |
770 | 790 | ||
771 | ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, | 791 | ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component, |
772 | &mxs_saif_dai, 1); | 792 | &mxs_saif_dai, 1); |
773 | if (ret) { | 793 | if (ret) { |
774 | dev_err(&pdev->dev, "register DAI failed\n"); | 794 | dev_err(&pdev->dev, "register DAI failed\n"); |
775 | return ret; | 795 | return ret; |
@@ -778,21 +798,15 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
778 | ret = mxs_pcm_platform_register(&pdev->dev); | 798 | ret = mxs_pcm_platform_register(&pdev->dev); |
779 | if (ret) { | 799 | if (ret) { |
780 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | 800 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); |
781 | goto failed_pdev_alloc; | 801 | return ret; |
782 | } | 802 | } |
783 | 803 | ||
784 | return 0; | 804 | return 0; |
785 | |||
786 | failed_pdev_alloc: | ||
787 | snd_soc_unregister_component(&pdev->dev); | ||
788 | |||
789 | return ret; | ||
790 | } | 805 | } |
791 | 806 | ||
792 | static int mxs_saif_remove(struct platform_device *pdev) | 807 | static int mxs_saif_remove(struct platform_device *pdev) |
793 | { | 808 | { |
794 | mxs_pcm_platform_unregister(&pdev->dev); | 809 | mxs_pcm_platform_unregister(&pdev->dev); |
795 | snd_soc_unregister_component(&pdev->dev); | ||
796 | 810 | ||
797 | return 0; | 811 | return 0; |
798 | } | 812 | } |