aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2013-12-20 08:11:34 -0500
committerMark Brown <broonie@linaro.org>2014-01-08 12:20:32 -0500
commit6de8387905a69568489284b4660737eebb0db8cf (patch)
tree9f4badac9f24bfea2fd4e160468e919a7fa0d01a /sound/soc/fsl
parent4e6ec0d98c045cb2c0c6550c65c4afae208872e9 (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.c89
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 */
585static 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
587static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) 615static 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}