aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/davinci
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2013-11-14 04:35:33 -0500
committerMark Brown <broonie@linaro.org>2013-12-10 06:22:16 -0500
commit4dcb5a0bffaa7dc51e738c4f651a31993b1eb08b (patch)
treeb9edaf3a1a28c8e0610012cd58a6d9680352be43 /sound/soc/davinci
parentcbc7956c81eea644c0d99aee43f1632897703300 (diff)
ASoC: davinci-mcasp: Fix synchronous master receive mode
In synchronous mode both transmit and receive sections are using the TX clocks. In setup like this the TX clocks need to be enabled when capture is running. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/davinci')
-rw-r--r--sound/soc/davinci/davinci-mcasp.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 35a6292889a5..93f2e294d649 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -48,6 +48,7 @@ struct davinci_mcasp {
48 u8 *serial_dir; 48 u8 *serial_dir;
49 u8 version; 49 u8 version;
50 u16 bclk_lrclk_ratio; 50 u16 bclk_lrclk_ratio;
51 int streams;
51 52
52 /* McASP FIFO related */ 53 /* McASP FIFO related */
53 u8 txnumevt; 54 u8 txnumevt;
@@ -110,10 +111,31 @@ static void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
110 printk(KERN_ERR "GBLCTL write error\n"); 111 printk(KERN_ERR "GBLCTL write error\n");
111} 112}
112 113
114static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
115{
116 u32 rxfmctl = mcasp_get_reg(mcasp->base + DAVINCI_MCASP_RXFMCTL_REG);
117 u32 aclkxctl = mcasp_get_reg(mcasp->base + DAVINCI_MCASP_ACLKXCTL_REG);
118
119 return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
120}
121
113static void mcasp_start_rx(struct davinci_mcasp *mcasp) 122static void mcasp_start_rx(struct davinci_mcasp *mcasp)
114{ 123{
115 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); 124 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
116 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); 125 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
126
127 /*
128 * When ASYNC == 0 the transmit and receive sections operate
129 * synchronously from the transmit clock and frame sync. We need to make
130 * sure that the TX signlas are enabled when starting reception.
131 */
132 if (mcasp_is_synchronous(mcasp)) {
133 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG,
134 TXHCLKRST);
135 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG,
136 TXCLKRST);
137 }
138
117 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); 139 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
118 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_RXBUF_REG, 0); 140 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_RXBUF_REG, 0);
119 141
@@ -123,6 +145,10 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
123 145
124 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); 146 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
125 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); 147 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
148
149 if (mcasp_is_synchronous(mcasp))
150 mcasp_set_ctl_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG,
151 TXFSRST);
126} 152}
127 153
128static void mcasp_start_tx(struct davinci_mcasp *mcasp) 154static void mcasp_start_tx(struct davinci_mcasp *mcasp)
@@ -158,6 +184,8 @@ static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
158{ 184{
159 u32 reg; 185 u32 reg;
160 186
187 mcasp->streams++;
188
161 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 189 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
162 if (mcasp->txnumevt) { /* enable FIFO */ 190 if (mcasp->txnumevt) { /* enable FIFO */
163 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; 191 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
@@ -177,13 +205,29 @@ static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
177 205
178static void mcasp_stop_rx(struct davinci_mcasp *mcasp) 206static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
179{ 207{
208 /*
209 * In synchronous mode stop the TX clocks if no other stream is
210 * running
211 */
212 if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
213 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
214
180 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, 0); 215 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
181 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); 216 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
182} 217}
183 218
184static void mcasp_stop_tx(struct davinci_mcasp *mcasp) 219static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
185{ 220{
186 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG, 0); 221 u32 val = 0;
222
223 /*
224 * In synchronous mode keep TX clocks running if the capture stream is
225 * still running.
226 */
227 if (mcasp_is_synchronous(mcasp) && mcasp->streams)
228 val = TXHCLKRST | TXCLKRST | TXFSRST;
229
230 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_GBLCTLX_REG, val);
187 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); 231 mcasp_set_reg(mcasp->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
188} 232}
189 233
@@ -191,6 +235,8 @@ static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
191{ 235{
192 u32 reg; 236 u32 reg;
193 237
238 mcasp->streams--;
239
194 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 240 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
195 if (mcasp->txnumevt) { /* disable FIFO */ 241 if (mcasp->txnumevt) { /* disable FIFO */
196 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; 242 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;