diff options
author | Shengjiu Wang <shengjiu.wang@nxp.com> | 2019-07-11 06:49:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-07-22 08:10:39 -0400 |
commit | 5be6155b50bbf7083b4bfa219e4ce6d1491f42f0 (patch) | |
tree | 656bfd07932899af084833f62e965ce404eb65e9 /sound/soc/fsl | |
parent | 4dc057a786dc23fd1ed70e6bcab691c0f26daa1e (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.c | 188 |
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 | ||
548 | static 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 | |||
582 | static 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 | |||
604 | static 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 | |||
640 | static 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 | |||
546 | static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | 656 | static 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 | ||
974 | err_regcache_sync: | 1021 | err_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); |