aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/davinci/davinci-mcasp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r--sound/soc/davinci/davinci-mcasp.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 0eed9b1b24e1..ea3ad747d092 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -154,9 +154,9 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
154 154
155static void mcasp_start_rx(struct davinci_mcasp *mcasp) 155static void mcasp_start_rx(struct davinci_mcasp *mcasp)
156{ 156{
157 /* Start clocks */
157 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); 158 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
158 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); 159 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
159
160 /* 160 /*
161 * When ASYNC == 0 the transmit and receive sections operate 161 * When ASYNC == 0 the transmit and receive sections operate
162 * synchronously from the transmit clock and frame sync. We need to make 162 * synchronously from the transmit clock and frame sync. We need to make
@@ -167,47 +167,36 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
167 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 167 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
168 } 168 }
169 169
170 /* Activate serializer(s) */
170 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); 171 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
171 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0); 172 /* Release RX state machine */
172
173 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
174 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
175 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
176
177 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); 173 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
174 /* Release Frame Sync generator */
178 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); 175 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
179
180 if (mcasp_is_synchronous(mcasp)) 176 if (mcasp_is_synchronous(mcasp))
181 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); 177 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
182} 178}
183 179
184static void mcasp_start_tx(struct davinci_mcasp *mcasp) 180static void mcasp_start_tx(struct davinci_mcasp *mcasp)
185{ 181{
186 u8 offset = 0, i;
187 u32 cnt; 182 u32 cnt;
188 183
184 /* Start clocks */
189 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 185 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
190 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 186 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
187 /* Activate serializer(s) */
191 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); 188 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
192 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
193 189
194 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); 190 /* wait for XDATA to be cleared */
195 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
196 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
197 for (i = 0; i < mcasp->num_serializer; i++) {
198 if (mcasp->serial_dir[i] == TX_MODE) {
199 offset = i;
200 break;
201 }
202 }
203
204 /* wait for TX ready */
205 cnt = 0; 191 cnt = 0;
206 while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) & 192 while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) &
207 TXSTATE) && (cnt < 100000)) 193 ~XRDATA) && (cnt < 100000))
208 cnt++; 194 cnt++;
209 195
210 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); 196 /* Release TX state machine */
197 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
198 /* Release Frame Sync generator */
199 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
211} 200}
212 201
213static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) 202static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
@@ -244,6 +233,12 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
244 233
245 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); 234 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
246 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); 235 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
236
237 if (mcasp->rxnumevt) { /* disable FIFO */
238 u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
239
240 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
241 }
247} 242}
248 243
249static void mcasp_stop_tx(struct davinci_mcasp *mcasp) 244static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
@@ -259,27 +254,22 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
259 254
260 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); 255 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
261 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); 256 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
257
258 if (mcasp->txnumevt) { /* disable FIFO */
259 u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
260
261 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
262 }
262} 263}
263 264
264static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) 265static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
265{ 266{
266 u32 reg;
267
268 mcasp->streams--; 267 mcasp->streams--;
269 268
270 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 269 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
271 if (mcasp->txnumevt) { /* disable FIFO */
272 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
273 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
274 }
275 mcasp_stop_tx(mcasp); 270 mcasp_stop_tx(mcasp);
276 } else { 271 else
277 if (mcasp->rxnumevt) { /* disable FIFO */
278 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
279 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
280 }
281 mcasp_stop_rx(mcasp); 272 mcasp_stop_rx(mcasp);
282 }
283} 273}
284 274
285static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 275static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
@@ -500,8 +490,17 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
500 * both left and right channels), so it has to be divided by number of 490 * both left and right channels), so it has to be divided by number of
501 * tdm-slots (for I2S - divided by 2). 491 * tdm-slots (for I2S - divided by 2).
502 */ 492 */
503 if (mcasp->bclk_lrclk_ratio) 493 if (mcasp->bclk_lrclk_ratio) {
504 word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots; 494 u32 slot_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots;
495
496 /*
497 * When we have more bclk then it is needed for the data, we
498 * need to use the rotation to move the received samples to have
499 * correct alignment.
500 */
501 rx_rotate = (slot_length - word_length) / 4;
502 word_length = slot_length;
503 }
505 504
506 /* mapping of the XSSZ bit-field as described in the datasheet */ 505 /* mapping of the XSSZ bit-field as described in the datasheet */
507 fmt = (word_length >> 1) - 1; 506 fmt = (word_length >> 1) - 1;
@@ -971,6 +970,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
971 }, 970 },
972 .ops = &davinci_mcasp_dai_ops, 971 .ops = &davinci_mcasp_dai_ops,
973 972
973 .symmetric_samplebits = 1,
974 }, 974 },
975 { 975 {
976 .name = "davinci-mcasp.1", 976 .name = "davinci-mcasp.1",
@@ -1235,6 +1235,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1235 ret = pm_runtime_get_sync(&pdev->dev); 1235 ret = pm_runtime_get_sync(&pdev->dev);
1236 if (IS_ERR_VALUE(ret)) { 1236 if (IS_ERR_VALUE(ret)) {
1237 dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); 1237 dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
1238 pm_runtime_disable(&pdev->dev);
1238 return ret; 1239 return ret;
1239 } 1240 }
1240 1241