1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "ccm-imx31.h"
27 #include "sdma-imx31.h"
28 #include "mmu-imx31.h"
30 #define DMA_PLAY_CH_NUM 2
31 #define DMA_REC_CH_NUM 1
32 #define DMA_PLAY_CH_PRIORITY 6
33 #define DMA_REC_CH_PRIORITY 6
35 static struct buffer_descriptor dma_play_bd NOCACHEBSS_ATTR
;
37 static void play_dma_callback(void);
38 static struct channel_descriptor dma_play_cd
=
41 .callback
= play_dma_callback
,
42 .shp_addr
= SDMA_PER_ADDR_SSI2_TX1
,
43 .wml
= SDMA_SSI_TXFIFO_WML
*2,
44 .per_type
= SDMA_PER_SSI_SHP
, /* SSI2 shared with SDMA core */
45 .tran_type
= SDMA_TRAN_EMI_2_PER
,
46 .event_id1
= SDMA_REQ_SSI2_TX1
,
49 /* The pcm locking relies on the fact the interrupt handlers run to completion
50 * before lower-priority modes proceed. We don't have to touch hardware
51 * registers. Disabling SDMA interrupt would disable DMA callbacks systemwide
52 * and that is not something that is desireable.
54 * Lock explanation [++.locked]:
55 * Trivial, just increment .locked.
57 * Unlock explanation [if (--.locked == 0 && .state != 0)]:
58 * If int occurred and saw .locked as nonzero, we'll get a pending
59 * and it will have taken no action other than to set the flag to the
60 * value of .state. If it saw zero for .locked, it will have proceeded
61 * normally into the pcm callbacks. If cb set the pending flag, it has
62 * to be called to kickstart the callback mechanism and DMA. If the unlock
63 * came after a stop, we won't be in the block and DMA will be off. If
64 * we're still doing transfers, cb will see 0 for .locked and if pending,
65 * it won't be called by DMA again. */
69 int callback_pending
; /* DMA interrupt happened while locked */
73 static struct dma_data dma_play_data
=
75 /* Initialize to an unlocked, stopped state */
77 .callback_pending
= 0,
81 static void play_dma_callback(void)
87 if (dma_play_data
.locked
!= 0)
89 /* Callback is locked out */
90 dma_play_data
.callback_pending
= dma_play_data
.state
;
94 rror
= dma_play_bd
.mode
.status
& BD_RROR
;
96 pcm_play_get_more_callback(rror
? NULL
: &start
, &size
);
101 /* Flush any pending cache writes */
102 clean_dcache_range(start
, size
);
103 dma_play_bd
.buf_addr
= (void *)addr_virt_to_phys((unsigned long)start
);
104 dma_play_bd
.mode
.count
= size
;
105 dma_play_bd
.mode
.command
= TRANSFER_16BIT
;
106 dma_play_bd
.mode
.status
= BD_DONE
| BD_WRAP
| BD_INTR
;
107 sdma_channel_run(DMA_PLAY_CH_NUM
);
110 void pcm_play_lock(void)
112 ++dma_play_data
.locked
;
115 void pcm_play_unlock(void)
117 if (--dma_play_data
.locked
== 0 && dma_play_data
.state
!= 0)
119 int oldstatus
= disable_irq_save();
120 int pending
= dma_play_data
.callback_pending
;
121 dma_play_data
.callback_pending
= 0;
122 restore_irq(oldstatus
);
129 void pcm_dma_apply_settings(void)
131 audiohw_set_frequency(pcm_fsel
);
134 void pcm_play_dma_init(void)
136 /* Init channel information */
137 sdma_channel_init(DMA_PLAY_CH_NUM
, &dma_play_cd
, &dma_play_bd
);
138 sdma_channel_set_priority(DMA_PLAY_CH_NUM
, DMA_PLAY_CH_PRIORITY
);
140 ccm_module_clock_gating(CG_SSI1
, CGM_ON_RUN_WAIT
);
141 ccm_module_clock_gating(CG_SSI2
, CGM_ON_RUN_WAIT
);
143 /* Reset & disable SSIs */
144 SSI_SCR1
&= ~SSI_SCR_SSIEN
;
145 SSI_SCR2
&= ~SSI_SCR_SSIEN
;
150 /* Set up audio mux */
152 /* Port 2 (internally connected to SSI2)
153 * All clocking is output sourced from port 4 */
154 AUDMUX_PTCR2
= AUDMUX_PTCR_TFS_DIR
| AUDMUX_PTCR_TFSEL_PORT4
|
155 AUDMUX_PTCR_TCLKDIR
| AUDMUX_PTCR_TCSEL_PORT4
|
158 /* Receive data from port 4 */
159 AUDMUX_PDCR2
= AUDMUX_PDCR_RXDSEL_PORT4
;
160 /* All clock lines are inputs sourced from the master mode codec and
161 * sent back to SSI2 through port 2 */
162 AUDMUX_PTCR4
= AUDMUX_PTCR_SYN
;
164 /* Receive data from port 2 */
165 AUDMUX_PDCR4
= AUDMUX_PDCR_RXDSEL_PORT2
;
167 /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to
168 * provide MCLK to the codec */
169 /* TX clocks are inputs taken from SSI2 */
170 /* RX clocks are outputs taken from PORT4 */
171 AUDMUX_PTCR1
= AUDMUX_PTCR_RFS_DIR
| AUDMUX_PTCR_RFSSEL_PORT4
|
172 AUDMUX_PTCR_RCLKDIR
| AUDMUX_PTCR_RCSEL_PORT4
;
173 /* RX data taken from PORT4 */
174 AUDMUX_PDCR1
= AUDMUX_PDCR_RXDSEL_PORT4
;
176 /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */
177 AUDMUX_PTCR5
= AUDMUX_PTCR_TCLKDIR
| AUDMUX_PTCR_TCSEL_PORT1
;
182 /* SSI2 - SoC software interface for all I2S data out */
183 SSI_SCR2
= SSI_SCR_SYN
| SSI_SCR_I2S_MODE_SLAVE
;
184 SSI_STCR2
= SSI_STCR_TXBIT0
| SSI_STCR_TSCKP
| SSI_STCR_TFSI
|
185 SSI_STCR_TEFS
| SSI_STCR_TFEN0
;
187 /* 16 bits per word, 2 words per frame */
188 SSI_STCCR2
= SSI_STRCCR_WL16
| ((2-1) << SSI_STRCCR_DC_POS
) |
189 ((4-1) << SSI_STRCCR_PM_POS
);
191 /* Transmit low watermark */
192 SSI_SFCSR2
= (SSI_SFCSR2
& ~SSI_SFCSR_TFWM0
) |
193 ((8-SDMA_SSI_TXFIFO_WML
) << SSI_SFCSR_TFWM0_POS
);
196 /* SSI1 - provides MCLK to codec. Receives data from codec. */
197 SSI_STCR1
= SSI_STCR_TXDIR
;
200 * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] =
201 * 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] =
202 * 677737600 / 4 = 169344000 Hz
204 * 45.4.2.2 DIV2, PSR, and PM Bit Description states:
205 * Bits DIV2, PSR, and PM should not be all set to zero at the same
208 * The hardware seems to force a divide by 4 even if all bits are
209 * zero but comply by setting DIV2 and the others to zero.
211 SSI_STCCR1
= SSI_STRCCR_DIV2
| ((1-1) << SSI_STRCCR_PM_POS
);
213 /* SSI1 - receive - asynchronous clocks */
214 SSI_SCR1
= SSI_SCR_I2S_MODE_SLAVE
;
216 SSI_SRCR1
= SSI_SRCR_RXBIT0
| SSI_SRCR_RSCKP
| SSI_SRCR_RFSI
|
219 /* 16 bits per word, 2 words per frame */
220 SSI_SRCCR1
= SSI_STRCCR_WL16
| ((2-1) << SSI_STRCCR_DC_POS
) |
221 ((4-1) << SSI_STRCCR_PM_POS
);
223 /* Receive high watermark */
224 SSI_SFCSR1
= (SSI_SFCSR1
& ~SSI_SFCSR_RFWM0
) |
225 (SDMA_SSI_RXFIFO_WML
<< SSI_SFCSR_RFWM0_POS
);
228 /* Enable SSI1 (codec clock) */
229 SSI_SCR1
|= SSI_SCR_SSIEN
;
234 void pcm_postinit(void)
239 static void play_start_pcm(void)
241 /* Stop transmission (if in progress) */
242 SSI_SCR2
&= ~SSI_SCR_TE
;
244 SSI_SCR2
|= SSI_SCR_SSIEN
; /* Enable SSI */
245 SSI_STCR2
|= SSI_STCR_TFEN0
; /* Enable TX FIFO */
247 dma_play_data
.state
= 1; /* Check callback on unlock */
249 /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE).
250 * No actual solution was offered but this appears to work. */
256 SSI_SIER2
|= SSI_SIER_TDMAE
; /* Enable DMA req. */
257 SSI_SCR2
|= SSI_SCR_TE
; /* Start transmitting */
260 static void play_stop_pcm(void)
262 SSI_SIER2
&= ~SSI_SIER_TDMAE
; /* Disable DMA req. */
264 /* Set state before pending to prevent race with interrupt */
265 dma_play_data
.state
= 0;
267 /* Wait for FIFO to empty */
268 while (SSI_SFCSR_TFCNT0
& SSI_SFCSR2
);
270 SSI_STCR2
&= ~SSI_STCR_TFEN0
; /* Disable TX */
271 SSI_SCR2
&= ~(SSI_SCR_TE
| SSI_SCR_SSIEN
); /* Disable transmission, SSI */
273 /* Clear any pending callback */
274 dma_play_data
.callback_pending
= 0;
277 void pcm_play_dma_start(const void *addr
, size_t size
)
279 sdma_channel_stop(DMA_PLAY_CH_NUM
);
281 /* Disable transmission */
282 SSI_STCR2
&= ~SSI_STCR_TFEN0
;
283 SSI_SCR2
&= ~(SSI_SCR_TE
| SSI_SCR_SSIEN
);
285 if (!sdma_channel_reset(DMA_PLAY_CH_NUM
))
288 clean_dcache_range(addr
, size
);
289 dma_play_bd
.buf_addr
=
290 (void *)addr_virt_to_phys((unsigned long)(void *)addr
);
291 dma_play_bd
.mode
.count
= size
;
292 dma_play_bd
.mode
.command
= TRANSFER_16BIT
;
293 dma_play_bd
.mode
.status
= BD_DONE
| BD_WRAP
| BD_INTR
;
296 sdma_channel_run(DMA_PLAY_CH_NUM
);
299 void pcm_play_dma_stop(void)
301 sdma_channel_stop(DMA_PLAY_CH_NUM
);
305 void pcm_play_dma_pause(bool pause
)
309 sdma_channel_pause(DMA_PLAY_CH_NUM
);
315 sdma_channel_run(DMA_PLAY_CH_NUM
);
319 /* Return the number of bytes waiting - full L-R sample pairs only */
320 size_t pcm_get_bytes_waiting(void)
322 static unsigned long dsa NOCACHEBSS_ATTR
;
326 /* read burst dma source address register in channel context */
327 sdma_read_words(&dsa
, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM
)+0x0b, 1);
329 oldstatus
= disable_irq_save();
330 offs
= dsa
- (unsigned long)dma_play_bd
.buf_addr
;
331 size
= dma_play_bd
.mode
.count
;
332 restore_irq(oldstatus
);
334 /* Be addresses are coherent (no buffer change during read) */
335 if (offs
>= 0 && offs
< size
)
337 return (size
- offs
) & ~3;
343 /* Return a pointer to the samples and the number of them in *count */
344 const void * pcm_play_dma_get_peak_buffer(int *count
)
346 static unsigned long dsa NOCACHEBSS_ATTR
;
351 /* read burst dma source address register in channel context */
352 sdma_read_words(&dsa
, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM
)+0x0b, 1);
354 oldstatus
= disable_irq_save();
356 offs
= addr
- (unsigned long)dma_play_bd
.buf_addr
;
357 size
= dma_play_bd
.mode
.count
;
358 restore_irq(oldstatus
);
360 /* Be addresses are coherent (no buffer change during read) */
361 if (offs
>= 0 && offs
< size
)
363 *count
= (size
- offs
) >> 2;
364 return (void *)((addr
+ 2) & ~3);
371 void * pcm_dma_addr(void *addr
)
373 return (void *)addr_virt_to_phys((unsigned long)addr
);
376 #ifdef HAVE_RECORDING
377 static struct buffer_descriptor dma_rec_bd NOCACHEBSS_ATTR
;
379 static void rec_dma_callback(void);
380 static struct channel_descriptor dma_rec_cd
=
383 .callback
= rec_dma_callback
,
384 .shp_addr
= SDMA_PER_ADDR_SSI1_RX1
,
385 .wml
= SDMA_SSI_RXFIFO_WML
*2,
386 .per_type
= SDMA_PER_SSI
,
387 .tran_type
= SDMA_TRAN_PER_2_EMI
,
388 .event_id1
= SDMA_REQ_SSI1_RX1
,
391 static struct dma_data dma_rec_data
=
393 /* Initialize to an unlocked, stopped state */
395 .callback_pending
= 0,
399 static void rec_dma_callback(void)
405 if (dma_rec_data
.locked
!= 0)
407 dma_rec_data
.callback_pending
= dma_rec_data
.state
;
408 return; /* Callback is locked out */
411 if (dma_rec_bd
.mode
.status
& BD_RROR
)
412 status
= DMA_REC_ERROR_DMA
;
414 pcm_rec_more_ready_callback(status
, &start
, &size
);
419 /* Invalidate - buffer must be coherent */
420 dump_dcache_range(start
, size
);
422 start
= (void *)addr_virt_to_phys((unsigned long)start
);
424 dma_rec_bd
.buf_addr
= start
;
425 dma_rec_bd
.mode
.count
= size
;
426 dma_rec_bd
.mode
.command
= TRANSFER_16BIT
;
427 dma_rec_bd
.mode
.status
= BD_DONE
| BD_WRAP
| BD_INTR
;
429 sdma_channel_run(DMA_REC_CH_NUM
);
432 void pcm_rec_lock(void)
434 ++dma_rec_data
.locked
;
437 void pcm_rec_unlock(void)
439 if (--dma_rec_data
.locked
== 0 && dma_rec_data
.state
!= 0)
441 int oldstatus
= disable_irq_save();
442 int pending
= dma_rec_data
.callback_pending
;
443 dma_rec_data
.callback_pending
= 0;
444 restore_irq(oldstatus
);
451 void pcm_rec_dma_stop(void)
453 SSI_SIER1
&= ~SSI_SIER_RDMAE
; /* Disable DMA req. */
455 /* Set state before pending to prevent race with interrupt */
456 dma_rec_data
.state
= 0;
458 /* Stop receiving data */
459 sdma_channel_stop(DMA_REC_CH_NUM
);
461 imx31_regclr32(&SSI_SIER1
, SSI_SIER_RDMAE
);
463 SSI_SCR1
&= ~SSI_SCR_RE
; /* Disable RX */
464 SSI_SRCR1
&= ~SSI_SRCR_RFEN0
; /* Disable RX FIFO */
466 /* Clear any pending callback */
467 dma_rec_data
.callback_pending
= 0;
470 void pcm_rec_dma_start(void *addr
, size_t size
)
474 if (!sdma_channel_reset(DMA_REC_CH_NUM
))
477 /* Invalidate - buffer must be coherent */
478 dump_dcache_range(addr
, size
);
480 addr
= (void *)addr_virt_to_phys((unsigned long)addr
);
481 dma_rec_bd
.buf_addr
= addr
;
482 dma_rec_bd
.mode
.count
= size
;
483 dma_rec_bd
.mode
.command
= TRANSFER_16BIT
;
484 dma_rec_bd
.mode
.status
= BD_DONE
| BD_WRAP
| BD_INTR
;
486 dma_rec_data
.state
= 1; /* Check callback on unlock */
488 SSI_SRCR1
|= SSI_SRCR_RFEN0
; /* Enable RX FIFO */
490 /* Ensure clear FIFO */
491 while (SSI_SFCSR1
& SSI_SFCSR_RFCNT0
)
495 SSI_SCR1
|= SSI_SCR_RE
;
496 SSI_SIER1
|= SSI_SIER_RDMAE
; /* Enable DMA req. */
498 sdma_channel_run(DMA_REC_CH_NUM
);
501 void pcm_rec_dma_close(void)
504 sdma_channel_close(DMA_REC_CH_NUM
);
507 void pcm_rec_dma_init(void)
511 /* Init channel information */
512 sdma_channel_init(DMA_REC_CH_NUM
, &dma_rec_cd
, &dma_rec_bd
);
513 sdma_channel_set_priority(DMA_REC_CH_NUM
, DMA_REC_CH_PRIORITY
);
516 const void * pcm_rec_dma_get_peak_buffer(void)
518 static unsigned long pda NOCACHEBSS_ATTR
;
519 unsigned long buf
, end
, bufend
;
522 /* read burst dma destination address register in channel context */
523 sdma_read_words(&pda
, CHANNEL_CONTEXT_ADDR(DMA_REC_CH_NUM
)+0x0a, 1);
525 oldstatus
= disable_irq_save();
527 buf
= (unsigned long)dma_rec_bd
.buf_addr
;
528 bufend
= buf
+ dma_rec_bd
.mode
.count
;
529 restore_irq(oldstatus
);
531 /* Be addresses are coherent (no buffer change during read) */
532 if (end
>= buf
&& end
< bufend
)
533 return (void *)(end
& ~3);
538 #endif /* HAVE_RECORDING */