diff options
author | Markus Pargmann <mpa@pengutronix.de> | 2013-12-20 08:11:34 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-01-08 12:20:32 -0500 |
commit | 6de8387905a69568489284b4660737eebb0db8cf (patch) | |
tree | 9f4badac9f24bfea2fd4e160468e919a7fa0d01a /sound/soc/fsl | |
parent | 4e6ec0d98c045cb2c0c6550c65c4afae208872e9 (diff) |
ASoC: fsl-ssi: Move RX/TX configuration to seperate functions
This patch defines the appropriate register values for different
oparation modes and IP versions. We have to handle DMA/FIQ, AC97,
DEBUG-IRQs and offline/online configuration support.
With this patch we cleanup some driver code that was not reference
manual conform and try to cleanup the whole trigger function to seperate
the actual register values from the enable/disable logic, which is now
hidden in fsl_ssi_config helpers.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 89 |
1 files changed, 46 insertions, 43 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index a85268bb4507..a96ab4e60652 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -108,13 +108,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
108 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) | 108 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | /* SIER bitflag of interrupts to enable */ | ||
112 | #define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \ | ||
113 | CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \ | ||
114 | CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \ | ||
115 | CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \ | ||
116 | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN) | ||
117 | |||
118 | #define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \ | 111 | #define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \ |
119 | CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \ | 112 | CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \ |
120 | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN) | 113 | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN) |
@@ -584,6 +577,41 @@ static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) | |||
584 | fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); | 577 | fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); |
585 | } | 578 | } |
586 | 579 | ||
580 | /* | ||
581 | * Setup rx/tx register values used to enable/disable the streams. These will | ||
582 | * be used later in fsl_ssi_config to setup the streams without the need to | ||
583 | * check for all different SSI modes. | ||
584 | */ | ||
585 | static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private) | ||
586 | { | ||
587 | struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val; | ||
588 | |||
589 | reg->rx.sier = CCSR_SSI_SIER_RFF0_EN; | ||
590 | reg->rx.srcr = CCSR_SSI_SRCR_RFEN0; | ||
591 | reg->rx.scr = 0; | ||
592 | reg->tx.sier = CCSR_SSI_SIER_TFE0_EN; | ||
593 | reg->tx.stcr = CCSR_SSI_STCR_TFEN0; | ||
594 | reg->tx.scr = 0; | ||
595 | |||
596 | if (!ssi_private->imx_ac97) { | ||
597 | reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE; | ||
598 | reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN; | ||
599 | reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE; | ||
600 | reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN; | ||
601 | } | ||
602 | |||
603 | if (ssi_private->use_dma) { | ||
604 | reg->rx.sier |= CCSR_SSI_SIER_RDMAE; | ||
605 | reg->tx.sier |= CCSR_SSI_SIER_TDMAE; | ||
606 | } else { | ||
607 | reg->rx.sier |= CCSR_SSI_SIER_RIE; | ||
608 | reg->tx.sier |= CCSR_SSI_SIER_TIE; | ||
609 | } | ||
610 | |||
611 | reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS; | ||
612 | reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS; | ||
613 | } | ||
614 | |||
587 | static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) | 615 | static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) |
588 | { | 616 | { |
589 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 617 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
@@ -620,6 +648,8 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
620 | u8 wm; | 648 | u8 wm; |
621 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | 649 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; |
622 | 650 | ||
651 | fsl_ssi_setup_reg_vals(ssi_private); | ||
652 | |||
623 | if (ssi_private->imx_ac97) | 653 | if (ssi_private->imx_ac97) |
624 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; | 654 | ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; |
625 | else | 655 | else |
@@ -643,13 +673,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | |||
643 | ssi_private->i2s_mode | | 673 | ssi_private->i2s_mode | |
644 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | 674 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); |
645 | 675 | ||
646 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | 676 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI | |
647 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | 677 | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr); |
648 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | 678 | |
679 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI | | ||
680 | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
649 | 681 | ||
650 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
651 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
652 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
653 | /* | 682 | /* |
654 | * The DC and PM bits are only used if the SSI is the clock master. | 683 | * The DC and PM bits are only used if the SSI is the clock master. |
655 | */ | 684 | */ |
@@ -1023,51 +1052,26 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1023 | { | 1052 | { |
1024 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1053 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1025 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 1054 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
1026 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
1027 | unsigned int sier_bits; | ||
1028 | unsigned long flags; | 1055 | unsigned long flags; |
1029 | 1056 | ||
1030 | /* | ||
1031 | * Enable only the interrupts and DMA requests | ||
1032 | * that are needed for the channel. As the fiq | ||
1033 | * is polling for this bits, we have to ensure | ||
1034 | * that this are aligned with the preallocated | ||
1035 | * buffers | ||
1036 | */ | ||
1037 | |||
1038 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1039 | if (ssi_private->use_dma) | ||
1040 | sier_bits = SIER_FLAGS; | ||
1041 | else | ||
1042 | sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; | ||
1043 | } else { | ||
1044 | if (ssi_private->use_dma) | ||
1045 | sier_bits = SIER_FLAGS; | ||
1046 | else | ||
1047 | sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; | ||
1048 | } | ||
1049 | |||
1050 | switch (cmd) { | 1057 | switch (cmd) { |
1051 | case SNDRV_PCM_TRIGGER_START: | 1058 | case SNDRV_PCM_TRIGGER_START: |
1052 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 1059 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
1053 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1060 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1054 | write_ssi_mask(&ssi->scr, 0, | 1061 | fsl_ssi_tx_config(ssi_private, true); |
1055 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); | ||
1056 | else | 1062 | else |
1057 | write_ssi_mask(&ssi->scr, 0, | 1063 | fsl_ssi_rx_config(ssi_private, true); |
1058 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); | ||
1059 | break; | 1064 | break; |
1060 | 1065 | ||
1061 | case SNDRV_PCM_TRIGGER_STOP: | 1066 | case SNDRV_PCM_TRIGGER_STOP: |
1062 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1067 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1063 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1068 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1064 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); | 1069 | fsl_ssi_tx_config(ssi_private, false); |
1065 | else | 1070 | else |
1066 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 1071 | fsl_ssi_rx_config(ssi_private, false); |
1067 | 1072 | ||
1068 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & | 1073 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & |
1069 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) { | 1074 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) { |
1070 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
1071 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); | 1075 | spin_lock_irqsave(&ssi_private->baudclk_lock, flags); |
1072 | ssi_private->baudclk_locked = false; | 1076 | ssi_private->baudclk_locked = false; |
1073 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); | 1077 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); |
@@ -1078,7 +1082,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1078 | return -EINVAL; | 1082 | return -EINVAL; |
1079 | } | 1083 | } |
1080 | 1084 | ||
1081 | write_ssi(sier_bits, &ssi->sier); | ||
1082 | 1085 | ||
1083 | return 0; | 1086 | return 0; |
1084 | } | 1087 | } |