summaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-07-11 06:49:45 -0400
committerMark Brown <broonie@kernel.org>2019-07-22 08:10:39 -0400
commit5be6155b50bbf7083b4bfa219e4ce6d1491f42f0 (patch)
tree656bfd07932899af084833f62e965ce404eb65e9 /sound/soc/fsl
parent4dc057a786dc23fd1ed70e6bcab691c0f26daa1e (diff)
ASoC: fsl_esai: Wrap some operations to be functions
Extract the operation to be functions, to improve the readability. In this patch, fsl_esai_hw_init, fsl_esai_register_restore, fsl_esai_trigger_start and fsl_esai_trigger_stop are extracted. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Acked-by: Nicolin Chen <nicoleotsuka@gmail.com> Link: https://lore.kernel.org/r/804d7e75ae7e06a913479912b578b3538ca7cd3f.1562842206.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_esai.c188
1 files changed, 117 insertions, 71 deletions
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 10d2210c91ef..ab460d6d7432 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -35,6 +35,7 @@
35 * @fifo_depth: depth of tx/rx FIFO 35 * @fifo_depth: depth of tx/rx FIFO
36 * @slot_width: width of each DAI slot 36 * @slot_width: width of each DAI slot
37 * @slots: number of slots 37 * @slots: number of slots
38 * @channels: channel num for tx or rx
38 * @hck_rate: clock rate of desired HCKx clock 39 * @hck_rate: clock rate of desired HCKx clock
39 * @sck_rate: clock rate of desired SCKx clock 40 * @sck_rate: clock rate of desired SCKx clock
40 * @hck_dir: the direction of HCKx pads 41 * @hck_dir: the direction of HCKx pads
@@ -57,6 +58,7 @@ struct fsl_esai {
57 u32 slots; 58 u32 slots;
58 u32 tx_mask; 59 u32 tx_mask;
59 u32 rx_mask; 60 u32 rx_mask;
61 u32 channels[2];
60 u32 hck_rate[2]; 62 u32 hck_rate[2];
61 u32 sck_rate[2]; 63 u32 sck_rate[2];
62 bool hck_dir[2]; 64 bool hck_dir[2];
@@ -543,64 +545,132 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
543 return 0; 545 return 0;
544} 546}
545 547
548static int fsl_esai_hw_init(struct fsl_esai *esai_priv)
549{
550 struct platform_device *pdev = esai_priv->pdev;
551 int ret;
552
553 /* Reset ESAI unit */
554 ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
555 ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
556 ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
557 if (ret) {
558 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
559 return ret;
560 }
561
562 /*
563 * We need to enable ESAI so as to access some of its registers.
564 * Otherwise, we would fail to dump regmap from user space.
565 */
566 ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
567 ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
568 ESAI_ECR_ESAIEN);
569 if (ret) {
570 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
571 return ret;
572 }
573
574 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
575 ESAI_PRRC_PDC_MASK, 0);
576 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
577 ESAI_PCRC_PC_MASK, 0);
578
579 return 0;
580}
581
582static int fsl_esai_register_restore(struct fsl_esai *esai_priv)
583{
584 int ret;
585
586 /* FIFO reset for safety */
587 regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR,
588 ESAI_xFCR_xFR, ESAI_xFCR_xFR);
589 regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR,
590 ESAI_xFCR_xFR, ESAI_xFCR_xFR);
591
592 regcache_mark_dirty(esai_priv->regmap);
593 ret = regcache_sync(esai_priv->regmap);
594 if (ret)
595 return ret;
596
597 /* FIFO reset done */
598 regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
599 regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
600
601 return 0;
602}
603
604static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx)
605{
606 u8 i, channels = esai_priv->channels[tx];
607 u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
608 u32 mask;
609
610 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
611 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
612
613 /* Write initial words reqiured by ESAI as normal procedure */
614 for (i = 0; tx && i < channels; i++)
615 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
616
617 /*
618 * When set the TE/RE in the end of enablement flow, there
619 * will be channel swap issue for multi data line case.
620 * In order to workaround this issue, we switch the bit
621 * enablement sequence to below sequence
622 * 1) clear the xSMB & xSMA: which is done in probe and
623 * stop state.
624 * 2) set TE/RE
625 * 3) set xSMB
626 * 4) set xSMA: xSMA is the last one in this flow, which
627 * will trigger esai to start.
628 */
629 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
630 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
631 tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
632 mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
633
634 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
635 ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
636 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
637 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
638}
639
640static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx)
641{
642 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
643 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
644 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
645 ESAI_xSMA_xS_MASK, 0);
646 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
647 ESAI_xSMB_xS_MASK, 0);
648
649 /* Disable and reset FIFO */
650 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
651 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
652 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
653 ESAI_xFCR_xFR, 0);
654}
655
546static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, 656static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
547 struct snd_soc_dai *dai) 657 struct snd_soc_dai *dai)
548{ 658{
549 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 659 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
550 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 660 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
551 u8 i, channels = substream->runtime->channels; 661
552 u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); 662 esai_priv->channels[tx] = substream->runtime->channels;
553 u32 mask;
554 663
555 switch (cmd) { 664 switch (cmd) {
556 case SNDRV_PCM_TRIGGER_START: 665 case SNDRV_PCM_TRIGGER_START:
557 case SNDRV_PCM_TRIGGER_RESUME: 666 case SNDRV_PCM_TRIGGER_RESUME:
558 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 667 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
559 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 668 fsl_esai_trigger_start(esai_priv, tx);
560 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
561
562 /* Write initial words reqiured by ESAI as normal procedure */
563 for (i = 0; tx && i < channels; i++)
564 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
565
566 /*
567 * When set the TE/RE in the end of enablement flow, there
568 * will be channel swap issue for multi data line case.
569 * In order to workaround this issue, we switch the bit
570 * enablement sequence to below sequence
571 * 1) clear the xSMB & xSMA: which is done in probe and
572 * stop state.
573 * 2) set TE/RE
574 * 3) set xSMB
575 * 4) set xSMA: xSMA is the last one in this flow, which
576 * will trigger esai to start.
577 */
578 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
579 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
580 tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
581 mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
582
583 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
584 ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
585 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
586 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
587
588 break; 669 break;
589 case SNDRV_PCM_TRIGGER_SUSPEND: 670 case SNDRV_PCM_TRIGGER_SUSPEND:
590 case SNDRV_PCM_TRIGGER_STOP: 671 case SNDRV_PCM_TRIGGER_STOP:
591 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 672 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
592 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 673 fsl_esai_trigger_stop(esai_priv, tx);
593 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
594 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
595 ESAI_xSMA_xS_MASK, 0);
596 regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
597 ESAI_xSMB_xS_MASK, 0);
598
599 /* Disable and reset FIFO */
600 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
601 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
602 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
603 ESAI_xFCR_xFR, 0);
604 break; 674 break;
605 default: 675 default:
606 return -EINVAL; 676 return -EINVAL;
@@ -866,22 +936,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
866 936
867 dev_set_drvdata(&pdev->dev, esai_priv); 937 dev_set_drvdata(&pdev->dev, esai_priv);
868 938
869 /* Reset ESAI unit */ 939 ret = fsl_esai_hw_init(esai_priv);
870 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); 940 if (ret)
871 if (ret) {
872 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
873 return ret;
874 }
875
876 /*
877 * We need to enable ESAI so as to access some of its registers.
878 * Otherwise, we would fail to dump regmap from user space.
879 */
880 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
881 if (ret) {
882 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
883 return ret; 941 return ret;
884 }
885 942
886 esai_priv->tx_mask = 0xFFFFFFFF; 943 esai_priv->tx_mask = 0xFFFFFFFF;
887 esai_priv->rx_mask = 0xFFFFFFFF; 944 esai_priv->rx_mask = 0xFFFFFFFF;
@@ -955,20 +1012,10 @@ static int fsl_esai_runtime_resume(struct device *dev)
955 1012
956 regcache_cache_only(esai->regmap, false); 1013 regcache_cache_only(esai->regmap, false);
957 1014
958 /* FIFO reset for safety */ 1015 ret = fsl_esai_register_restore(esai);
959 regmap_update_bits(esai->regmap, REG_ESAI_TFCR,
960 ESAI_xFCR_xFR, ESAI_xFCR_xFR);
961 regmap_update_bits(esai->regmap, REG_ESAI_RFCR,
962 ESAI_xFCR_xFR, ESAI_xFCR_xFR);
963
964 ret = regcache_sync(esai->regmap);
965 if (ret) 1016 if (ret)
966 goto err_regcache_sync; 1017 goto err_regcache_sync;
967 1018
968 /* FIFO reset done */
969 regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
970 regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
971
972 return 0; 1019 return 0;
973 1020
974err_regcache_sync: 1021err_regcache_sync:
@@ -991,7 +1038,6 @@ static int fsl_esai_runtime_suspend(struct device *dev)
991 struct fsl_esai *esai = dev_get_drvdata(dev); 1038 struct fsl_esai *esai = dev_get_drvdata(dev);
992 1039
993 regcache_cache_only(esai->regmap, true); 1040 regcache_cache_only(esai->regmap, true);
994 regcache_mark_dirty(esai->regmap);
995 1041
996 if (!IS_ERR(esai->fsysclk)) 1042 if (!IS_ERR(esai->fsysclk))
997 clk_disable_unprepare(esai->fsysclk); 1043 clk_disable_unprepare(esai->fsysclk);