summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2016-12-29 06:34:04 -0500
committerMark Brown <broonie@kernel.org>2016-12-31 13:36:13 -0500
commitdc938ddb56283a0b71d987e7ecd4be90390985d6 (patch)
tree946a1022a635186347c48712d62c58b8426b6d9f /sound
parentbe2c92eb64023e294d6bb9232578963670bb121b (diff)
ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device
This patch adds calls to pm_runtime_get/put to ensure that any access to I2S registers is done with proper (active) runtime PM state of I2S device. Till now the driver enabled runtime PM, but didn't manage the state during driver operation. The driver worked fine only because the runtime PM callbacks managed device clock, which was enabled all the time because of the additional enable call in the driver's probe function. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/samsung/i2s.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 10b19a4afe86..8d8965e7107c 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -477,6 +477,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
477 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; 477 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
478 u32 mod, mask, val = 0; 478 u32 mod, mask, val = 0;
479 unsigned long flags; 479 unsigned long flags;
480 int ret = 0;
481
482 pm_runtime_get_sync(dai->dev);
480 483
481 spin_lock_irqsave(i2s->lock, flags); 484 spin_lock_irqsave(i2s->lock, flags);
482 mod = readl(i2s->addr + I2SMOD); 485 mod = readl(i2s->addr + I2SMOD);
@@ -501,7 +504,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
501 && (mod & cdcon_mask))))) { 504 && (mod & cdcon_mask))))) {
502 dev_err(&i2s->pdev->dev, 505 dev_err(&i2s->pdev->dev,
503 "%s:%d Other DAI busy\n", __func__, __LINE__); 506 "%s:%d Other DAI busy\n", __func__, __LINE__);
504 return -EAGAIN; 507 ret = -EAGAIN;
508 goto err;
505 } 509 }
506 510
507 if (dir == SND_SOC_CLOCK_IN) 511 if (dir == SND_SOC_CLOCK_IN)
@@ -529,7 +533,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
529 } else { 533 } else {
530 i2s->rclk_srcrate = 534 i2s->rclk_srcrate =
531 clk_get_rate(i2s->op_clk); 535 clk_get_rate(i2s->op_clk);
532 return 0; 536 goto done;
533 } 537 }
534 } 538 }
535 539
@@ -540,8 +544,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
540 i2s->op_clk = clk_get(&i2s->pdev->dev, 544 i2s->op_clk = clk_get(&i2s->pdev->dev,
541 "i2s_opclk0"); 545 "i2s_opclk0");
542 546
543 if (WARN_ON(IS_ERR(i2s->op_clk))) 547 if (WARN_ON(IS_ERR(i2s->op_clk))) {
544 return PTR_ERR(i2s->op_clk); 548 ret = PTR_ERR(i2s->op_clk);
549 goto err;
550 }
545 551
546 clk_prepare_enable(i2s->op_clk); 552 clk_prepare_enable(i2s->op_clk);
547 i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); 553 i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
@@ -555,12 +561,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
555 || (clk_id && !(mod & rsrc_mask))) { 561 || (clk_id && !(mod & rsrc_mask))) {
556 dev_err(&i2s->pdev->dev, 562 dev_err(&i2s->pdev->dev,
557 "%s:%d Other DAI busy\n", __func__, __LINE__); 563 "%s:%d Other DAI busy\n", __func__, __LINE__);
558 return -EAGAIN; 564 ret = -EAGAIN;
565 goto err;
559 } else { 566 } else {
560 /* Call can't be on the active DAI */ 567 /* Call can't be on the active DAI */
561 i2s->op_clk = other->op_clk; 568 i2s->op_clk = other->op_clk;
562 i2s->rclk_srcrate = other->rclk_srcrate; 569 i2s->rclk_srcrate = other->rclk_srcrate;
563 return 0; 570 goto done;
564 } 571 }
565 572
566 if (clk_id == 1) 573 if (clk_id == 1)
@@ -568,7 +575,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
568 break; 575 break;
569 default: 576 default:
570 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); 577 dev_err(&i2s->pdev->dev, "We don't serve that!\n");
571 return -EINVAL; 578 ret = -EINVAL;
579 goto err;
572 } 580 }
573 581
574 spin_lock_irqsave(i2s->lock, flags); 582 spin_lock_irqsave(i2s->lock, flags);
@@ -576,8 +584,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
576 mod = (mod & ~mask) | val; 584 mod = (mod & ~mask) | val;
577 writel(mod, i2s->addr + I2SMOD); 585 writel(mod, i2s->addr + I2SMOD);
578 spin_unlock_irqrestore(i2s->lock, flags); 586 spin_unlock_irqrestore(i2s->lock, flags);
587done:
588 pm_runtime_put(dai->dev);
579 589
580 return 0; 590 return 0;
591err:
592 pm_runtime_put(dai->dev);
593 return ret;
581} 594}
582 595
583static int i2s_set_fmt(struct snd_soc_dai *dai, 596static int i2s_set_fmt(struct snd_soc_dai *dai,
@@ -646,6 +659,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
646 return -EINVAL; 659 return -EINVAL;
647 } 660 }
648 661
662 pm_runtime_get_sync(dai->dev);
649 spin_lock_irqsave(i2s->lock, flags); 663 spin_lock_irqsave(i2s->lock, flags);
650 mod = readl(i2s->addr + I2SMOD); 664 mod = readl(i2s->addr + I2SMOD);
651 /* 665 /*
@@ -655,6 +669,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
655 if (any_active(i2s) && 669 if (any_active(i2s) &&
656 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { 670 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
657 spin_unlock_irqrestore(i2s->lock, flags); 671 spin_unlock_irqrestore(i2s->lock, flags);
672 pm_runtime_put(dai->dev);
658 dev_err(&i2s->pdev->dev, 673 dev_err(&i2s->pdev->dev,
659 "%s:%d Other DAI busy\n", __func__, __LINE__); 674 "%s:%d Other DAI busy\n", __func__, __LINE__);
660 return -EAGAIN; 675 return -EAGAIN;
@@ -664,6 +679,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
664 mod |= tmp; 679 mod |= tmp;
665 writel(mod, i2s->addr + I2SMOD); 680 writel(mod, i2s->addr + I2SMOD);
666 spin_unlock_irqrestore(i2s->lock, flags); 681 spin_unlock_irqrestore(i2s->lock, flags);
682 pm_runtime_put(dai->dev);
667 683
668 return 0; 684 return 0;
669} 685}
@@ -675,6 +691,8 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
675 u32 mod, mask = 0, val = 0; 691 u32 mod, mask = 0, val = 0;
676 unsigned long flags; 692 unsigned long flags;
677 693
694 WARN_ON(!pm_runtime_active(dai->dev));
695
678 if (!is_secondary(i2s)) 696 if (!is_secondary(i2s))
679 mask |= (MOD_DC2_EN | MOD_DC1_EN); 697 mask |= (MOD_DC2_EN | MOD_DC1_EN);
680 698
@@ -763,6 +781,8 @@ static int i2s_startup(struct snd_pcm_substream *substream,
763 struct i2s_dai *other = get_other_dai(i2s); 781 struct i2s_dai *other = get_other_dai(i2s);
764 unsigned long flags; 782 unsigned long flags;
765 783
784 pm_runtime_get_sync(dai->dev);
785
766 spin_lock_irqsave(&lock, flags); 786 spin_lock_irqsave(&lock, flags);
767 787
768 i2s->mode |= DAI_OPENED; 788 i2s->mode |= DAI_OPENED;
@@ -800,6 +820,8 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
800 i2s->bfs = 0; 820 i2s->bfs = 0;
801 821
802 spin_unlock_irqrestore(&lock, flags); 822 spin_unlock_irqrestore(&lock, flags);
823
824 pm_runtime_put(dai->dev);
803} 825}
804 826
805static int config_setup(struct i2s_dai *i2s) 827static int config_setup(struct i2s_dai *i2s)
@@ -874,6 +896,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
874 case SNDRV_PCM_TRIGGER_START: 896 case SNDRV_PCM_TRIGGER_START:
875 case SNDRV_PCM_TRIGGER_RESUME: 897 case SNDRV_PCM_TRIGGER_RESUME:
876 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 898 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
899 pm_runtime_get_sync(dai->dev);
877 spin_lock_irqsave(i2s->lock, flags); 900 spin_lock_irqsave(i2s->lock, flags);
878 901
879 if (config_setup(i2s)) { 902 if (config_setup(i2s)) {
@@ -902,6 +925,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
902 } 925 }
903 926
904 spin_unlock_irqrestore(i2s->lock, flags); 927 spin_unlock_irqrestore(i2s->lock, flags);
928 pm_runtime_put(dai->dev);
905 break; 929 break;
906 } 930 }
907 931
@@ -916,13 +940,16 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai,
916 940
917 switch (div_id) { 941 switch (div_id) {
918 case SAMSUNG_I2S_DIV_BCLK: 942 case SAMSUNG_I2S_DIV_BCLK:
943 pm_runtime_get_sync(dai->dev);
919 if ((any_active(i2s) && div && (get_bfs(i2s) != div)) 944 if ((any_active(i2s) && div && (get_bfs(i2s) != div))
920 || (other && other->bfs && (other->bfs != div))) { 945 || (other && other->bfs && (other->bfs != div))) {
946 pm_runtime_put(dai->dev);
921 dev_err(&i2s->pdev->dev, 947 dev_err(&i2s->pdev->dev,
922 "%s:%d Other DAI busy\n", __func__, __LINE__); 948 "%s:%d Other DAI busy\n", __func__, __LINE__);
923 return -EAGAIN; 949 return -EAGAIN;
924 } 950 }
925 i2s->bfs = div; 951 i2s->bfs = div;
952 pm_runtime_put(dai->dev);
926 break; 953 break;
927 default: 954 default:
928 dev_err(&i2s->pdev->dev, 955 dev_err(&i2s->pdev->dev,
@@ -941,6 +968,8 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
941 snd_pcm_sframes_t delay; 968 snd_pcm_sframes_t delay;
942 const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; 969 const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
943 970
971 WARN_ON(!pm_runtime_active(dai->dev));
972
944 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 973 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
945 delay = FIC_RXCOUNT(reg); 974 delay = FIC_RXCOUNT(reg);
946 else if (is_secondary(i2s)) 975 else if (is_secondary(i2s))
@@ -984,6 +1013,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
984 struct i2s_dai *other = get_other_dai(i2s); 1013 struct i2s_dai *other = get_other_dai(i2s);
985 unsigned long flags; 1014 unsigned long flags;
986 1015
1016 pm_runtime_get_sync(dai->dev);
1017
987 if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ 1018 if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */
988 snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback, 1019 snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback,
989 NULL); 1020 NULL);
@@ -1016,6 +1047,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
1016 if (!is_opened(other)) 1047 if (!is_opened(other))
1017 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, 1048 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
1018 0, SND_SOC_CLOCK_IN); 1049 0, SND_SOC_CLOCK_IN);
1050 pm_runtime_put(dai->dev);
1019 1051
1020 return 0; 1052 return 0;
1021} 1053}
@@ -1025,6 +1057,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
1025 struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); 1057 struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai);
1026 unsigned long flags; 1058 unsigned long flags;
1027 1059
1060 pm_runtime_get_sync(dai->dev);
1061
1028 if (!is_secondary(i2s)) { 1062 if (!is_secondary(i2s)) {
1029 if (i2s->quirks & QUIRK_NEED_RSTCLR) { 1063 if (i2s->quirks & QUIRK_NEED_RSTCLR) {
1030 spin_lock_irqsave(i2s->lock, flags); 1064 spin_lock_irqsave(i2s->lock, flags);
@@ -1033,6 +1067,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
1033 } 1067 }
1034 } 1068 }
1035 1069
1070 pm_runtime_put(dai->dev);
1071
1036 return 0; 1072 return 0;
1037} 1073}
1038 1074
@@ -1322,7 +1358,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1322 1358
1323 dev_set_drvdata(&pdev->dev, pri_dai); 1359 dev_set_drvdata(&pdev->dev, pri_dai);
1324 1360
1325 1361 pm_runtime_set_active(&pdev->dev);
1326 pm_runtime_enable(&pdev->dev); 1362 pm_runtime_enable(&pdev->dev);
1327 1363
1328 ret = i2s_register_clock_provider(pdev); 1364 ret = i2s_register_clock_provider(pdev);
@@ -1345,10 +1381,12 @@ static int samsung_i2s_remove(struct platform_device *pdev)
1345 pri_dai->sec_dai = NULL; 1381 pri_dai->sec_dai = NULL;
1346 sec_dai->pri_dai = NULL; 1382 sec_dai->pri_dai = NULL;
1347 1383
1384 pm_runtime_get_sync(&pdev->dev);
1348 pm_runtime_disable(&pdev->dev); 1385 pm_runtime_disable(&pdev->dev);
1349 1386
1350 i2s_unregister_clock_provider(pdev); 1387 i2s_unregister_clock_provider(pdev);
1351 clk_disable_unprepare(pri_dai->clk); 1388 clk_disable_unprepare(pri_dai->clk);
1389 pm_runtime_put_noidle(&pdev->dev);
1352 1390
1353 return 0; 1391 return 0;
1354} 1392}