f74b16740012362860b83ca3303f6b959f709e3b
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / pcm-gigabeat-s.c
blobf74b16740012362860b83ca3303f6b959f709e3b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include <stdlib.h>
22 #include "system.h"
23 #include "kernel.h"
24 #include "audio.h"
25 #include "sound.h"
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;
36 static struct channel_descriptor dma_play_cd NOCACHEBSS_ATTR;
38 /* The pcm locking relies on the fact the interrupt handlers run to completion
39 * before lower-priority modes proceed. We don't have to touch hardware
40 * registers. Disabling SDMA interrupt would disable DMA callbacks systemwide
41 * and that is not something that is desireable.
43 * Lock explanation [++.locked]:
44 * Trivial, just increment .locked.
46 * Unlock explanation [if (--.locked == 0 && .state != 0)]:
47 * If int occurred and saw .locked as nonzero, we'll get a pending
48 * and it will have taken no action other than to set the flag to the
49 * value of .state. If it saw zero for .locked, it will have proceeded
50 * normally into the pcm callbacks. If cb set the pending flag, it has
51 * to be called to kickstart the callback mechanism and DMA. If the unlock
52 * came after a stop, we won't be in the block and DMA will be off. If
53 * we're still doing transfers, cb will see 0 for .locked and if pending,
54 * it won't be called by DMA again. */
55 struct dma_data
57 int locked;
58 int callback_pending; /* DMA interrupt happened while locked */
59 int state;
62 static struct dma_data dma_play_data =
64 /* Initialize to an unlocked, stopped state */
65 .locked = 0,
66 .callback_pending = 0,
67 .state = 0
70 static void play_dma_callback(void)
72 void *start;
73 size_t size;
74 bool rror;
76 if (dma_play_data.locked != 0)
78 /* Callback is locked out */
79 dma_play_data.callback_pending = dma_play_data.state;
80 return;
83 rror = dma_play_bd.mode.status & BD_RROR;
85 pcm_play_get_more_callback(rror ? NULL : &start, &size);
87 if (size == 0)
88 return;
90 /* Flush any pending cache writes */
91 clean_dcache_range(start, size);
92 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
93 dma_play_bd.mode.count = size;
94 dma_play_bd.mode.command = TRANSFER_16BIT;
95 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
96 sdma_channel_run(DMA_PLAY_CH_NUM);
99 void pcm_play_lock(void)
101 ++dma_play_data.locked;
104 void pcm_play_unlock(void)
106 if (--dma_play_data.locked == 0 && dma_play_data.state != 0)
108 int oldstatus = disable_irq_save();
109 int pending = dma_play_data.callback_pending;
110 dma_play_data.callback_pending = 0;
111 restore_irq(oldstatus);
113 if (pending != 0)
114 play_dma_callback();
118 void pcm_dma_apply_settings(void)
120 audiohw_set_frequency(pcm_fsel);
123 void pcm_play_dma_init(void)
125 /* Init channel information */
126 dma_play_cd.bd_count = 1;
127 dma_play_cd.callback = play_dma_callback;
128 dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI2_TX1;
129 dma_play_cd.wml = SDMA_SSI_TXFIFO_WML*2;
130 dma_play_cd.per_type = SDMA_PER_SSI_SHP; /* SSI2 shared with SDMA core */
131 dma_play_cd.tran_type = SDMA_TRAN_EMI_2_PER;
132 dma_play_cd.event_id1 = SDMA_REQ_SSI2_TX1;
134 sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd);
135 sdma_channel_set_priority(DMA_PLAY_CH_NUM, DMA_PLAY_CH_PRIORITY);
137 ccm_module_clock_gating(CG_SSI1, CGM_ON_RUN_WAIT);
138 ccm_module_clock_gating(CG_SSI2, CGM_ON_RUN_WAIT);
140 /* Reset & disable SSIs */
141 SSI_SCR1 &= ~SSI_SCR_SSIEN;
142 SSI_SCR2 &= ~SSI_SCR_SSIEN;
144 SSI_SIER1 = 0;
145 SSI_SIER2 = 0;
147 /* Set up audio mux */
149 /* Port 2 (internally connected to SSI2)
150 * All clocking is output sourced from port 4 */
151 AUDMUX_PTCR2 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 |
152 AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 |
153 AUDMUX_PTCR_SYN;
155 /* Receive data from port 4 */
156 AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4;
157 /* All clock lines are inputs sourced from the master mode codec and
158 * sent back to SSI2 through port 2 */
159 AUDMUX_PTCR4 = AUDMUX_PTCR_SYN;
161 /* Receive data from port 2 */
162 AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2;
164 /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to
165 * provide MCLK to the codec */
166 /* TX clocks are inputs taken from SSI2 */
167 /* RX clocks are outputs taken from PORT4 */
168 AUDMUX_PTCR1 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 |
169 AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4;
170 /* RX data taken from PORT4 */
171 AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4;
173 /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */
174 AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT1;
175 AUDMUX_PDCR5 = 0;
177 /* Setup SSIs */
179 /* SSI2 - SoC software interface for all I2S data out */
180 SSI_SCR2 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE;
181 SSI_STCR2 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI |
182 SSI_STCR_TEFS | SSI_STCR_TFEN0;
184 /* 16 bits per word, 2 words per frame */
185 SSI_STCCR2 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) |
186 ((4-1) << SSI_STRCCR_PM_POS);
188 /* Transmit low watermark */
189 SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_TFWM0) |
190 ((8-SDMA_SSI_TXFIFO_WML) << SSI_SFCSR_TFWM0_POS);
191 SSI_STMSK2 = 0;
193 /* SSI1 - provides MCLK to codec. Receives data from codec. */
194 SSI_STCR1 = SSI_STCR_TXDIR;
196 /* f(INT_BIT_CLK) =
197 * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] =
198 * 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] =
199 * 677737600 / 4 = 169344000 Hz
201 * 45.4.2.2 DIV2, PSR, and PM Bit Description states:
202 * Bits DIV2, PSR, and PM should not be all set to zero at the same
203 * time.
205 * The hardware seems to force a divide by 4 even if all bits are
206 * zero but comply by setting DIV2 and the others to zero.
208 SSI_STCCR1 = SSI_STRCCR_DIV2 | ((1-1) << SSI_STRCCR_PM_POS);
210 /* SSI1 - receive - asynchronous clocks */
211 SSI_SCR1 = SSI_SCR_I2S_MODE_SLAVE;
213 SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI |
214 SSI_SRCR_REFS;
216 /* 16 bits per word, 2 words per frame */
217 SSI_SRCCR1 = SSI_STRCCR_WL16 | ((2-1) << SSI_STRCCR_DC_POS) |
218 ((4-1) << SSI_STRCCR_PM_POS);
220 /* Receive high watermark */
221 SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_RFWM0) |
222 (SDMA_SSI_RXFIFO_WML << SSI_SFCSR_RFWM0_POS);
223 SSI_SRMSK1 = 0;
225 /* Enable SSI1 (codec clock) */
226 SSI_SCR1 |= SSI_SCR_SSIEN;
228 audiohw_init();
231 void pcm_postinit(void)
233 audiohw_postinit();
236 static void play_start_pcm(void)
238 /* Stop transmission (if in progress) */
239 SSI_SCR2 &= ~SSI_SCR_TE;
241 SSI_SCR2 |= SSI_SCR_SSIEN; /* Enable SSI */
242 SSI_STCR2 |= SSI_STCR_TFEN0; /* Enable TX FIFO */
244 dma_play_data.state = 1; /* Check callback on unlock */
246 /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE).
247 * No actual solution was offered but this appears to work. */
248 SSI_STX0_2 = 0;
249 SSI_STX0_2 = 0;
250 SSI_STX0_2 = 0;
251 SSI_STX0_2 = 0;
253 SSI_SIER2 |= SSI_SIER_TDMAE; /* Enable DMA req. */
254 SSI_SCR2 |= SSI_SCR_TE; /* Start transmitting */
257 static void play_stop_pcm(void)
259 SSI_SIER2 &= ~SSI_SIER_TDMAE; /* Disable DMA req. */
261 /* Set state before pending to prevent race with interrupt */
262 dma_play_data.state = 0;
264 /* Wait for FIFO to empty */
265 while (SSI_SFCSR_TFCNT0 & SSI_SFCSR2);
267 SSI_STCR2 &= ~SSI_STCR_TFEN0; /* Disable TX */
268 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); /* Disable transmission, SSI */
270 /* Clear any pending callback */
271 dma_play_data.callback_pending = 0;
274 void pcm_play_dma_start(const void *addr, size_t size)
276 sdma_channel_stop(DMA_PLAY_CH_NUM);
278 /* Disable transmission */
279 SSI_STCR2 &= ~SSI_STCR_TFEN0;
280 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN);
282 if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
283 return;
285 clean_dcache_range(addr, size);
286 dma_play_bd.buf_addr =
287 (void *)addr_virt_to_phys((unsigned long)(void *)addr);
288 dma_play_bd.mode.count = size;
289 dma_play_bd.mode.command = TRANSFER_16BIT;
290 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
292 play_start_pcm();
293 sdma_channel_run(DMA_PLAY_CH_NUM);
296 void pcm_play_dma_stop(void)
298 sdma_channel_stop(DMA_PLAY_CH_NUM);
299 play_stop_pcm();
302 void pcm_play_dma_pause(bool pause)
304 if (pause)
306 sdma_channel_pause(DMA_PLAY_CH_NUM);
307 play_stop_pcm();
309 else
311 play_start_pcm();
312 sdma_channel_run(DMA_PLAY_CH_NUM);
316 /* Return the number of bytes waiting - full L-R sample pairs only */
317 size_t pcm_get_bytes_waiting(void)
319 static unsigned long dsa NOCACHEBSS_ATTR;
320 long offs, size;
321 int oldstatus;
323 /* read burst dma source address register in channel context */
324 sdma_read_words(&dsa, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM)+0x0b, 1);
326 oldstatus = disable_irq_save();
327 offs = dsa - (unsigned long)dma_play_bd.buf_addr;
328 size = dma_play_bd.mode.count;
329 restore_irq(oldstatus);
331 /* Be addresses are coherent (no buffer change during read) */
332 if (offs >= 0 && offs < size)
334 return (size - offs) & ~3;
337 return 0;
340 /* Return a pointer to the samples and the number of them in *count */
341 const void * pcm_play_dma_get_peak_buffer(int *count)
343 static unsigned long dsa NOCACHEBSS_ATTR;
344 unsigned long addr;
345 long offs, size;
346 int oldstatus;
348 /* read burst dma source address register in channel context */
349 sdma_read_words(&dsa, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM)+0x0b, 1);
351 oldstatus = disable_irq_save();
352 addr = dsa;
353 offs = addr - (unsigned long)dma_play_bd.buf_addr;
354 size = dma_play_bd.mode.count;
355 restore_irq(oldstatus);
357 /* Be addresses are coherent (no buffer change during read) */
358 if (offs >= 0 && offs < size)
360 *count = (size - offs) >> 2;
361 return (void *)((addr + 2) & ~3);
364 *count = 0;
365 return NULL;
368 void * pcm_dma_addr(void *addr)
370 return (void *)addr_virt_to_phys((unsigned long)addr);
373 #ifdef HAVE_RECORDING
374 static struct buffer_descriptor dma_rec_bd NOCACHEBSS_ATTR;
375 static struct channel_descriptor dma_rec_cd NOCACHEBSS_ATTR;
377 static struct dma_data dma_rec_data =
379 /* Initialize to an unlocked, stopped state */
380 .locked = 0,
381 .callback_pending = 0,
382 .state = 0
385 static void rec_dma_callback(void)
387 int status = 0;
388 void *start;
389 size_t size;
391 if (dma_rec_data.locked != 0)
393 dma_rec_data.callback_pending = dma_rec_data.state;
394 return; /* Callback is locked out */
397 if (dma_rec_bd.mode.status & BD_RROR)
398 status = DMA_REC_ERROR_DMA;
400 pcm_rec_more_ready_callback(status, &start, &size);
402 if (size == 0)
403 return;
405 /* Invalidate - buffer must be coherent */
406 dump_dcache_range(start, size);
408 start = (void *)addr_virt_to_phys((unsigned long)start);
410 dma_rec_bd.buf_addr = start;
411 dma_rec_bd.mode.count = size;
412 dma_rec_bd.mode.command = TRANSFER_16BIT;
413 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
415 sdma_channel_run(DMA_REC_CH_NUM);
418 void pcm_rec_lock(void)
420 ++dma_rec_data.locked;
423 void pcm_rec_unlock(void)
425 if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0)
427 int oldstatus = disable_irq_save();
428 int pending = dma_rec_data.callback_pending;
429 dma_rec_data.callback_pending = 0;
430 restore_irq(oldstatus);
432 if (pending != 0)
433 rec_dma_callback();
437 void pcm_rec_dma_stop(void)
439 SSI_SIER1 &= ~SSI_SIER_RDMAE; /* Disable DMA req. */
441 /* Set state before pending to prevent race with interrupt */
442 dma_rec_data.state = 0;
444 /* Stop receiving data */
445 sdma_channel_stop(DMA_REC_CH_NUM);
447 imx31_regclr32(&SSI_SIER1, SSI_SIER_RDMAE);
449 SSI_SCR1 &= ~SSI_SCR_RE; /* Disable RX */
450 SSI_SRCR1 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */
452 /* Clear any pending callback */
453 dma_rec_data.callback_pending = 0;
456 void pcm_rec_dma_start(void *addr, size_t size)
458 pcm_rec_dma_stop();
460 if (!sdma_channel_reset(DMA_REC_CH_NUM))
461 return;
463 /* Invalidate - buffer must be coherent */
464 dump_dcache_range(addr, size);
466 addr = (void *)addr_virt_to_phys((unsigned long)addr);
467 dma_rec_bd.buf_addr = addr;
468 dma_rec_bd.mode.count = size;
469 dma_rec_bd.mode.command = TRANSFER_16BIT;
470 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
472 dma_rec_data.state = 1; /* Check callback on unlock */
474 SSI_SRCR1 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */
476 /* Ensure clear FIFO */
477 while (SSI_SFCSR1 & SSI_SFCSR_RFCNT0)
478 SSI_SRX0_1;
480 /* Enable receive */
481 SSI_SCR1 |= SSI_SCR_RE;
482 SSI_SIER1 |= SSI_SIER_RDMAE; /* Enable DMA req. */
484 sdma_channel_run(DMA_REC_CH_NUM);
487 void pcm_rec_dma_close(void)
489 pcm_rec_dma_stop();
490 sdma_channel_close(DMA_REC_CH_NUM);
493 void pcm_rec_dma_init(void)
495 pcm_rec_dma_stop();
497 /* Init channel information */
498 dma_rec_cd.bd_count = 1;
499 dma_rec_cd.callback = rec_dma_callback;
500 dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI1_RX1;
501 dma_rec_cd.wml = SDMA_SSI_RXFIFO_WML*2;
502 dma_rec_cd.per_type = SDMA_PER_SSI;
503 dma_rec_cd.tran_type = SDMA_TRAN_PER_2_EMI;
504 dma_rec_cd.event_id1 = SDMA_REQ_SSI1_RX1;
506 sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd);
507 sdma_channel_set_priority(DMA_REC_CH_NUM, DMA_REC_CH_PRIORITY);
510 const void * pcm_rec_dma_get_peak_buffer(void)
512 static unsigned long pda NOCACHEBSS_ATTR;
513 unsigned long buf, end, bufend;
514 int oldstatus;
516 /* read burst dma destination address register in channel context */
517 sdma_read_words(&pda, CHANNEL_CONTEXT_ADDR(DMA_REC_CH_NUM)+0x0a, 1);
519 oldstatus = disable_irq_save();
520 end = pda;
521 buf = (unsigned long)dma_rec_bd.buf_addr;
522 bufend = buf + dma_rec_bd.mode.count;
523 restore_irq(oldstatus);
525 /* Be addresses are coherent (no buffer change during read) */
526 if (end >= buf && end < bufend)
527 return (void *)(end & ~3);
529 return NULL;
532 #endif /* HAVE_RECORDING */