diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 116 |
1 files changed, 58 insertions, 58 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index 9d2503f4e6..649186ab2e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | |||
@@ -88,7 +88,7 @@ static void play_dma_callback(void) | |||
88 | void pcm_play_lock(void) | 88 | void pcm_play_lock(void) |
89 | { | 89 | { |
90 | if (++dma_play_data.locked == 1) | 90 | if (++dma_play_data.locked == 1) |
91 | imx31_regclr32(&SSI_SIER1, SSI_SIER_TDMAE); | 91 | imx31_regclr32(&SSI_SIER2, SSI_SIER_TDMAE); |
92 | } | 92 | } |
93 | 93 | ||
94 | void pcm_play_unlock(void) | 94 | void pcm_play_unlock(void) |
@@ -98,7 +98,7 @@ void pcm_play_unlock(void) | |||
98 | int oldstatus = disable_irq_save(); | 98 | int oldstatus = disable_irq_save(); |
99 | int pending = dma_play_data.callback_pending; | 99 | int pending = dma_play_data.callback_pending; |
100 | dma_play_data.callback_pending = 0; | 100 | dma_play_data.callback_pending = 0; |
101 | SSI_SIER1 |= SSI_SIER_TDMAE; | 101 | SSI_SIER2 |= SSI_SIER_TDMAE; |
102 | restore_irq(oldstatus); | 102 | restore_irq(oldstatus); |
103 | 103 | ||
104 | /* Should an interrupt be forced instead? The upper pcm layer can | 104 | /* Should an interrupt be forced instead? The upper pcm layer can |
@@ -119,11 +119,11 @@ void pcm_play_dma_init(void) | |||
119 | /* Init channel information */ | 119 | /* Init channel information */ |
120 | dma_play_cd.bd_count = 1; | 120 | dma_play_cd.bd_count = 1; |
121 | dma_play_cd.callback = play_dma_callback; | 121 | dma_play_cd.callback = play_dma_callback; |
122 | dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI1_TX1; | 122 | dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI2_TX1; |
123 | dma_play_cd.wml = SDMA_SSI_TXFIFO_WML*2; | 123 | dma_play_cd.wml = SDMA_SSI_TXFIFO_WML*2; |
124 | dma_play_cd.per_type = SDMA_PER_SSI; | 124 | dma_play_cd.per_type = SDMA_PER_SSI_SHP; /* SSI2 shared with SDMA core */ |
125 | dma_play_cd.tran_type = SDMA_TRAN_EMI_2_PER; | 125 | dma_play_cd.tran_type = SDMA_TRAN_EMI_2_PER; |
126 | dma_play_cd.event_id1 = SDMA_REQ_SSI1_TX1; | 126 | dma_play_cd.event_id1 = SDMA_REQ_SSI2_TX1; |
127 | 127 | ||
128 | sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); | 128 | sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); |
129 | 129 | ||
@@ -131,60 +131,60 @@ void pcm_play_dma_init(void) | |||
131 | imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); | 131 | imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); |
132 | 132 | ||
133 | /* Reset & disable SSIs */ | 133 | /* Reset & disable SSIs */ |
134 | SSI_SCR2 &= ~SSI_SCR_SSIEN; | ||
135 | SSI_SCR1 &= ~SSI_SCR_SSIEN; | 134 | SSI_SCR1 &= ~SSI_SCR_SSIEN; |
135 | SSI_SCR2 &= ~SSI_SCR_SSIEN; | ||
136 | 136 | ||
137 | SSI_SIER1 = 0; | 137 | SSI_SIER1 = 0; |
138 | SSI_SIER2 = 0; | 138 | SSI_SIER2 = 0; |
139 | 139 | ||
140 | /* Set up audio mux */ | 140 | /* Set up audio mux */ |
141 | 141 | ||
142 | /* Port 1 (internally connected to SSI1) | 142 | /* Port 2 (internally connected to SSI2) |
143 | * All clocking is output sourced from port 4 */ | 143 | * All clocking is output sourced from port 4 */ |
144 | AUDMUX_PTCR1 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | | 144 | AUDMUX_PTCR2 = AUDMUX_PTCR_TFS_DIR | AUDMUX_PTCR_TFSEL_PORT4 | |
145 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | | 145 | AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT4 | |
146 | AUDMUX_PTCR_SYN; | 146 | AUDMUX_PTCR_SYN; |
147 | 147 | ||
148 | /* Receive data from port 4 */ | 148 | /* Receive data from port 4 */ |
149 | AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; | 149 | AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; |
150 | /* All clock lines are inputs sourced from the master mode codec and | 150 | /* All clock lines are inputs sourced from the master mode codec and |
151 | * sent back to SSI1 through port 1 */ | 151 | * sent back to SSI2 through port 2 */ |
152 | AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; | 152 | AUDMUX_PTCR4 = AUDMUX_PTCR_SYN; |
153 | 153 | ||
154 | /* Receive data from port 1 */ | 154 | /* Receive data from port 2 */ |
155 | AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT1; | 155 | AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; |
156 | 156 | ||
157 | /* PORT2 (internally connected to SSI2) routes clocking to PORT5 to | 157 | /* PORT1 (internally connected to SSI1) routes clocking to PORT5 to |
158 | * provide MCLK to the codec */ | 158 | * provide MCLK to the codec */ |
159 | /* TX clocks are inputs taken from SSI2 */ | 159 | /* TX clocks are inputs taken from SSI2 */ |
160 | /* RX clocks are outputs taken from PORT4 */ | 160 | /* RX clocks are outputs taken from PORT4 */ |
161 | AUDMUX_PTCR2 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | | 161 | AUDMUX_PTCR1 = AUDMUX_PTCR_RFS_DIR | AUDMUX_PTCR_RFSSEL_PORT4 | |
162 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4; | 162 | AUDMUX_PTCR_RCLKDIR | AUDMUX_PTCR_RCSEL_PORT4; |
163 | /* RX data taken from PORT4 */ | 163 | /* RX data taken from PORT4 */ |
164 | AUDMUX_PDCR2 = AUDMUX_PDCR_RXDSEL_PORT4; | 164 | AUDMUX_PDCR1 = AUDMUX_PDCR_RXDSEL_PORT4; |
165 | 165 | ||
166 | /* PORT5 outputs TCLK sourced from PORT2 (SSI2) */ | 166 | /* PORT5 outputs TCLK sourced from PORT1 (SSI1) */ |
167 | AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT2; | 167 | AUDMUX_PTCR5 = AUDMUX_PTCR_TCLKDIR | AUDMUX_PTCR_TCSEL_PORT1; |
168 | AUDMUX_PDCR5 = 0; | 168 | AUDMUX_PDCR5 = 0; |
169 | 169 | ||
170 | /* Setup SSIs */ | 170 | /* Setup SSIs */ |
171 | 171 | ||
172 | /* SSI1 - SoC software interface for all I2S data out */ | 172 | /* SSI2 - SoC software interface for all I2S data out */ |
173 | SSI_SCR1 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; | 173 | SSI_SCR2 = SSI_SCR_SYN | SSI_SCR_I2S_MODE_SLAVE; |
174 | SSI_STCR1 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | | 174 | SSI_STCR2 = SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI | |
175 | SSI_STCR_TEFS | SSI_STCR_TFEN0; | 175 | SSI_STCR_TEFS | SSI_STCR_TFEN0; |
176 | 176 | ||
177 | /* 16 bits per word, 2 words per frame */ | 177 | /* 16 bits per word, 2 words per frame */ |
178 | SSI_STCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | | 178 | SSI_STCCR2 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | |
179 | SSI_STRCCR_PMw(4-1); | 179 | SSI_STRCCR_PMw(4-1); |
180 | 180 | ||
181 | /* Transmit low watermark */ | 181 | /* Transmit low watermark */ |
182 | SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_TFWM0) | | 182 | SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_TFWM0) | |
183 | SSI_SFCSR_TFWM0w(8-SDMA_SSI_TXFIFO_WML); | 183 | SSI_SFCSR_TFWM0w(8-SDMA_SSI_TXFIFO_WML); |
184 | SSI_STMSK1 = 0; | 184 | SSI_STMSK2 = 0; |
185 | 185 | ||
186 | /* SSI2 - provides MCLK to codec. Receives data from codec. */ | 186 | /* SSI1 - provides MCLK to codec. Receives data from codec. */ |
187 | SSI_STCR2 = SSI_STCR_TXDIR; | 187 | SSI_STCR1 = SSI_STCR_TXDIR; |
188 | 188 | ||
189 | /* f(INT_BIT_CLK) = | 189 | /* f(INT_BIT_CLK) = |
190 | * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = | 190 | * f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] = |
@@ -198,25 +198,25 @@ void pcm_play_dma_init(void) | |||
198 | * The hardware seems to force a divide by 4 even if all bits are | 198 | * The hardware seems to force a divide by 4 even if all bits are |
199 | * zero but comply by setting DIV2 and the others to zero. | 199 | * zero but comply by setting DIV2 and the others to zero. |
200 | */ | 200 | */ |
201 | SSI_STCCR2 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1); | 201 | SSI_STCCR1 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1); |
202 | 202 | ||
203 | /* SSI2 - receive - asynchronous clocks */ | 203 | /* SSI1 - receive - asynchronous clocks */ |
204 | SSI_SCR2 = SSI_SCR_I2S_MODE_SLAVE; | 204 | SSI_SCR1 = SSI_SCR_I2S_MODE_SLAVE; |
205 | 205 | ||
206 | SSI_SRCR2 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | | 206 | SSI_SRCR1 = SSI_SRCR_RXBIT0 | SSI_SRCR_RSCKP | SSI_SRCR_RFSI | |
207 | SSI_SRCR_REFS; | 207 | SSI_SRCR_REFS; |
208 | 208 | ||
209 | /* 16 bits per word, 2 words per frame */ | 209 | /* 16 bits per word, 2 words per frame */ |
210 | SSI_SRCCR2 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | | 210 | SSI_SRCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | |
211 | SSI_STRCCR_PMw(4-1); | 211 | SSI_STRCCR_PMw(4-1); |
212 | 212 | ||
213 | /* Receive high watermark */ | 213 | /* Receive high watermark */ |
214 | SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_RFWM0) | | 214 | SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_RFWM0) | |
215 | SSI_SFCSR_RFWM0w(SDMA_SSI_RXFIFO_WML); | 215 | SSI_SFCSR_RFWM0w(SDMA_SSI_RXFIFO_WML); |
216 | SSI_SRMSK2 = 0; | 216 | SSI_SRMSK1 = 0; |
217 | 217 | ||
218 | /* Enable SSI2 (codec clock) */ | 218 | /* Enable SSI1 (codec clock) */ |
219 | SSI_SCR2 |= SSI_SCR_SSIEN; | 219 | SSI_SCR1 |= SSI_SCR_SSIEN; |
220 | 220 | ||
221 | audiohw_init(); | 221 | audiohw_init(); |
222 | } | 222 | } |
@@ -229,31 +229,31 @@ void pcm_postinit(void) | |||
229 | static void play_start_pcm(void) | 229 | static void play_start_pcm(void) |
230 | { | 230 | { |
231 | /* Stop transmission (if in progress) */ | 231 | /* Stop transmission (if in progress) */ |
232 | SSI_SCR1 &= ~SSI_SCR_TE; | 232 | SSI_SCR2 &= ~SSI_SCR_TE; |
233 | 233 | ||
234 | SSI_SCR1 |= SSI_SCR_SSIEN; /* Enable SSI */ | 234 | SSI_SCR2 |= SSI_SCR_SSIEN; /* Enable SSI */ |
235 | SSI_STCR1 |= SSI_STCR_TFEN0; /* Enable TX FIFO */ | 235 | SSI_STCR2 |= SSI_STCR_TFEN0; /* Enable TX FIFO */ |
236 | 236 | ||
237 | dma_play_data.state = 1; /* Enable DMA requests on unlock */ | 237 | dma_play_data.state = 1; /* Enable DMA requests on unlock */ |
238 | 238 | ||
239 | /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE). | 239 | /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE). |
240 | * No actual solution was offered but this appears to work. */ | 240 | * No actual solution was offered but this appears to work. */ |
241 | SSI_STX0_1 = 0; | 241 | SSI_STX0_2 = 0; |
242 | SSI_STX0_1 = 0; | 242 | SSI_STX0_2 = 0; |
243 | SSI_STX0_1 = 0; | 243 | SSI_STX0_2 = 0; |
244 | SSI_STX0_1 = 0; | 244 | SSI_STX0_2 = 0; |
245 | 245 | ||
246 | SSI_SCR1 |= SSI_SCR_TE; /* Start transmitting */ | 246 | SSI_SCR2 |= SSI_SCR_TE; /* Start transmitting */ |
247 | } | 247 | } |
248 | 248 | ||
249 | static void play_stop_pcm(void) | 249 | static void play_stop_pcm(void) |
250 | { | 250 | { |
251 | /* Wait for FIFO to empty */ | 251 | /* Wait for FIFO to empty */ |
252 | while (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 0); | 252 | while (SSI_SFCSR_TFCNT0r(SSI_SFCSR2) > 0); |
253 | 253 | ||
254 | /* Disable transmission */ | 254 | /* Disable transmission */ |
255 | SSI_STCR1 &= ~SSI_STCR_TFEN0; | 255 | SSI_STCR2 &= ~SSI_STCR_TFEN0; |
256 | SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); | 256 | SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); |
257 | 257 | ||
258 | /* Set state before pending to prevent race with interrupt */ | 258 | /* Set state before pending to prevent race with interrupt */ |
259 | /* Do not enable DMA requests on unlock */ | 259 | /* Do not enable DMA requests on unlock */ |
@@ -266,8 +266,8 @@ void pcm_play_dma_start(const void *addr, size_t size) | |||
266 | sdma_channel_stop(DMA_PLAY_CH_NUM); | 266 | sdma_channel_stop(DMA_PLAY_CH_NUM); |
267 | 267 | ||
268 | /* Disable transmission */ | 268 | /* Disable transmission */ |
269 | SSI_STCR1 &= ~SSI_STCR_TFEN0; | 269 | SSI_STCR2 &= ~SSI_STCR_TFEN0; |
270 | SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); | 270 | SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); |
271 | 271 | ||
272 | addr = (void *)(((unsigned long)addr + 3) & ~3); | 272 | addr = (void *)(((unsigned long)addr + 3) & ~3); |
273 | size &= ~3; | 273 | size &= ~3; |
@@ -408,7 +408,7 @@ static void rec_dma_callback(void) | |||
408 | void pcm_rec_lock(void) | 408 | void pcm_rec_lock(void) |
409 | { | 409 | { |
410 | if (++dma_rec_data.locked == 1) | 410 | if (++dma_rec_data.locked == 1) |
411 | imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); | 411 | imx31_regclr32(&SSI_SIER1, SSI_SIER_RDMAE); |
412 | } | 412 | } |
413 | 413 | ||
414 | void pcm_rec_unlock(void) | 414 | void pcm_rec_unlock(void) |
@@ -418,7 +418,7 @@ void pcm_rec_unlock(void) | |||
418 | int oldstatus = disable_irq_save(); | 418 | int oldstatus = disable_irq_save(); |
419 | int pending = dma_rec_data.callback_pending; | 419 | int pending = dma_rec_data.callback_pending; |
420 | dma_rec_data.callback_pending = 0; | 420 | dma_rec_data.callback_pending = 0; |
421 | SSI_SIER2 |= SSI_SIER_RDMAE; | 421 | SSI_SIER1 |= SSI_SIER_RDMAE; |
422 | restore_irq(oldstatus); | 422 | restore_irq(oldstatus); |
423 | 423 | ||
424 | /* Should an interrupt be forced instead? The upper pcm layer can | 424 | /* Should an interrupt be forced instead? The upper pcm layer can |
@@ -451,10 +451,10 @@ void pcm_rec_dma_stop(void) | |||
451 | /* Stop receiving data */ | 451 | /* Stop receiving data */ |
452 | sdma_channel_stop(DMA_REC_CH_NUM); | 452 | sdma_channel_stop(DMA_REC_CH_NUM); |
453 | 453 | ||
454 | imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); | 454 | imx31_regclr32(&SSI_SIER1, SSI_SIER_RDMAE); |
455 | 455 | ||
456 | SSI_SCR2 &= ~SSI_SCR_RE; /* Disable RX */ | 456 | SSI_SCR1 &= ~SSI_SCR_RE; /* Disable RX */ |
457 | SSI_SRCR2 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */ | 457 | SSI_SRCR1 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */ |
458 | 458 | ||
459 | /* Set state before pending to prevent race with interrupt */ | 459 | /* Set state before pending to prevent race with interrupt */ |
460 | /* Do not enable DMA requests on unlock */ | 460 | /* Do not enable DMA requests on unlock */ |
@@ -487,14 +487,14 @@ void pcm_rec_dma_start(void *addr, size_t size) | |||
487 | 487 | ||
488 | dma_rec_data.state = 1; | 488 | dma_rec_data.state = 1; |
489 | 489 | ||
490 | SSI_SRCR2 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ | 490 | SSI_SRCR1 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ |
491 | 491 | ||
492 | /* Ensure clear FIFO */ | 492 | /* Ensure clear FIFO */ |
493 | while (SSI_SFCSR2 & SSI_SFCSR_RFCNT0) | 493 | while (SSI_SFCSR1 & SSI_SFCSR_RFCNT0) |
494 | SSI_SRX0_2; | 494 | SSI_SRX0_1; |
495 | 495 | ||
496 | /* Enable receive */ | 496 | /* Enable receive */ |
497 | SSI_SCR2 |= SSI_SCR_RE; | 497 | SSI_SCR1 |= SSI_SCR_RE; |
498 | sdma_channel_run(DMA_REC_CH_NUM); | 498 | sdma_channel_run(DMA_REC_CH_NUM); |
499 | } | 499 | } |
500 | 500 | ||
@@ -511,11 +511,11 @@ void pcm_rec_dma_init(void) | |||
511 | /* Init channel information */ | 511 | /* Init channel information */ |
512 | dma_rec_cd.bd_count = 1; | 512 | dma_rec_cd.bd_count = 1; |
513 | dma_rec_cd.callback = rec_dma_callback; | 513 | dma_rec_cd.callback = rec_dma_callback; |
514 | dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI2_RX1; | 514 | dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI1_RX1; |
515 | dma_rec_cd.wml = SDMA_SSI_RXFIFO_WML*2; | 515 | dma_rec_cd.wml = SDMA_SSI_RXFIFO_WML*2; |
516 | dma_rec_cd.per_type = SDMA_PER_SSI; | 516 | dma_rec_cd.per_type = SDMA_PER_SSI; |
517 | dma_rec_cd.tran_type = SDMA_TRAN_PER_2_EMI; | 517 | dma_rec_cd.tran_type = SDMA_TRAN_PER_2_EMI; |
518 | dma_rec_cd.event_id1 = SDMA_REQ_SSI2_RX1; | 518 | dma_rec_cd.event_id1 = SDMA_REQ_SSI1_RX1; |
519 | 519 | ||
520 | sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd); | 520 | sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd); |
521 | } | 521 | } |