Root/
1 | /* |
2 | * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver |
3 | * |
4 | * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. |
9 | * |
10 | * Documentation: ARM DDI 0173B |
11 | */ |
12 | #include <linux/module.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/init.h> |
15 | #include <linux/ioport.h> |
16 | #include <linux/device.h> |
17 | #include <linux/spinlock.h> |
18 | #include <linux/interrupt.h> |
19 | #include <linux/err.h> |
20 | #include <linux/amba/bus.h> |
21 | #include <linux/io.h> |
22 | |
23 | #include <sound/core.h> |
24 | #include <sound/initval.h> |
25 | #include <sound/ac97_codec.h> |
26 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> |
28 | |
29 | #include "aaci.h" |
30 | |
31 | #define DRIVER_NAME "aaci-pl041" |
32 | |
33 | #define FRAME_PERIOD_US 21 |
34 | |
35 | /* |
36 | * PM support is not complete. Turn it off. |
37 | */ |
38 | #undef CONFIG_PM |
39 | |
40 | static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97) |
41 | { |
42 | u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); |
43 | |
44 | /* |
45 | * Ensure that the slot 1/2 RX registers are empty. |
46 | */ |
47 | v = readl(aaci->base + AACI_SLFR); |
48 | if (v & SLFR_2RXV) |
49 | readl(aaci->base + AACI_SL2RX); |
50 | if (v & SLFR_1RXV) |
51 | readl(aaci->base + AACI_SL1RX); |
52 | |
53 | if (maincr != readl(aaci->base + AACI_MAINCR)) { |
54 | writel(maincr, aaci->base + AACI_MAINCR); |
55 | readl(aaci->base + AACI_MAINCR); |
56 | udelay(1); |
57 | } |
58 | } |
59 | |
60 | /* |
61 | * P29: |
62 | * The recommended use of programming the external codec through slot 1 |
63 | * and slot 2 data is to use the channels during setup routines and the |
64 | * slot register at any other time. The data written into slot 1, slot 2 |
65 | * and slot 12 registers is transmitted only when their corresponding |
66 | * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR |
67 | * register. |
68 | */ |
69 | static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, |
70 | unsigned short val) |
71 | { |
72 | struct aaci *aaci = ac97->private_data; |
73 | int timeout; |
74 | u32 v; |
75 | |
76 | if (ac97->num >= 4) |
77 | return; |
78 | |
79 | mutex_lock(&aaci->ac97_sem); |
80 | |
81 | aaci_ac97_select_codec(aaci, ac97); |
82 | |
83 | /* |
84 | * P54: You must ensure that AACI_SL2TX is always written |
85 | * to, if required, before data is written to AACI_SL1TX. |
86 | */ |
87 | writel(val << 4, aaci->base + AACI_SL2TX); |
88 | writel(reg << 12, aaci->base + AACI_SL1TX); |
89 | |
90 | /* Initially, wait one frame period */ |
91 | udelay(FRAME_PERIOD_US); |
92 | |
93 | /* And then wait an additional eight frame periods for it to be sent */ |
94 | timeout = FRAME_PERIOD_US * 8; |
95 | do { |
96 | udelay(1); |
97 | v = readl(aaci->base + AACI_SLFR); |
98 | } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); |
99 | |
100 | if (v & (SLFR_1TXB|SLFR_2TXB)) |
101 | dev_err(&aaci->dev->dev, |
102 | "timeout waiting for write to complete\n"); |
103 | |
104 | mutex_unlock(&aaci->ac97_sem); |
105 | } |
106 | |
107 | /* |
108 | * Read an AC'97 register. |
109 | */ |
110 | static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
111 | { |
112 | struct aaci *aaci = ac97->private_data; |
113 | int timeout, retries = 10; |
114 | u32 v; |
115 | |
116 | if (ac97->num >= 4) |
117 | return ~0; |
118 | |
119 | mutex_lock(&aaci->ac97_sem); |
120 | |
121 | aaci_ac97_select_codec(aaci, ac97); |
122 | |
123 | /* |
124 | * Write the register address to slot 1. |
125 | */ |
126 | writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); |
127 | |
128 | /* Initially, wait one frame period */ |
129 | udelay(FRAME_PERIOD_US); |
130 | |
131 | /* And then wait an additional eight frame periods for it to be sent */ |
132 | timeout = FRAME_PERIOD_US * 8; |
133 | do { |
134 | udelay(1); |
135 | v = readl(aaci->base + AACI_SLFR); |
136 | } while ((v & SLFR_1TXB) && --timeout); |
137 | |
138 | if (v & SLFR_1TXB) { |
139 | dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); |
140 | v = ~0; |
141 | goto out; |
142 | } |
143 | |
144 | /* Now wait for the response frame */ |
145 | udelay(FRAME_PERIOD_US); |
146 | |
147 | /* And then wait an additional eight frame periods for data */ |
148 | timeout = FRAME_PERIOD_US * 8; |
149 | do { |
150 | udelay(1); |
151 | cond_resched(); |
152 | v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); |
153 | } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); |
154 | |
155 | if (v != (SLFR_1RXV|SLFR_2RXV)) { |
156 | dev_err(&aaci->dev->dev, "timeout on RX valid\n"); |
157 | v = ~0; |
158 | goto out; |
159 | } |
160 | |
161 | do { |
162 | v = readl(aaci->base + AACI_SL1RX) >> 12; |
163 | if (v == reg) { |
164 | v = readl(aaci->base + AACI_SL2RX) >> 4; |
165 | break; |
166 | } else if (--retries) { |
167 | dev_warn(&aaci->dev->dev, |
168 | "ac97 read back fail. retry\n"); |
169 | continue; |
170 | } else { |
171 | dev_warn(&aaci->dev->dev, |
172 | "wrong ac97 register read back (%x != %x)\n", |
173 | v, reg); |
174 | v = ~0; |
175 | } |
176 | } while (retries); |
177 | out: |
178 | mutex_unlock(&aaci->ac97_sem); |
179 | return v; |
180 | } |
181 | |
182 | static inline void |
183 | aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) |
184 | { |
185 | u32 val; |
186 | int timeout = 5000; |
187 | |
188 | do { |
189 | udelay(1); |
190 | val = readl(aacirun->base + AACI_SR); |
191 | } while (val & mask && timeout--); |
192 | } |
193 | |
194 | |
195 | |
196 | /* |
197 | * Interrupt support. |
198 | */ |
199 | static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) |
200 | { |
201 | if (mask & ISR_ORINTR) { |
202 | dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel); |
203 | writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR); |
204 | } |
205 | |
206 | if (mask & ISR_RXTOINTR) { |
207 | dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel); |
208 | writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR); |
209 | } |
210 | |
211 | if (mask & ISR_RXINTR) { |
212 | struct aaci_runtime *aacirun = &aaci->capture; |
213 | bool period_elapsed = false; |
214 | void *ptr; |
215 | |
216 | if (!aacirun->substream || !aacirun->start) { |
217 | dev_warn(&aaci->dev->dev, "RX interrupt???\n"); |
218 | writel(0, aacirun->base + AACI_IE); |
219 | return; |
220 | } |
221 | |
222 | spin_lock(&aacirun->lock); |
223 | |
224 | ptr = aacirun->ptr; |
225 | do { |
226 | unsigned int len = aacirun->fifo_bytes; |
227 | u32 val; |
228 | |
229 | if (aacirun->bytes <= 0) { |
230 | aacirun->bytes += aacirun->period; |
231 | period_elapsed = true; |
232 | } |
233 | if (!(aacirun->cr & CR_EN)) |
234 | break; |
235 | |
236 | val = readl(aacirun->base + AACI_SR); |
237 | if (!(val & SR_RXHF)) |
238 | break; |
239 | if (!(val & SR_RXFF)) |
240 | len >>= 1; |
241 | |
242 | aacirun->bytes -= len; |
243 | |
244 | /* reading 16 bytes at a time */ |
245 | for( ; len > 0; len -= 16) { |
246 | asm( |
247 | "ldmia %1, {r0, r1, r2, r3}\n\t" |
248 | "stmia %0!, {r0, r1, r2, r3}" |
249 | : "+r" (ptr) |
250 | : "r" (aacirun->fifo) |
251 | : "r0", "r1", "r2", "r3", "cc"); |
252 | |
253 | if (ptr >= aacirun->end) |
254 | ptr = aacirun->start; |
255 | } |
256 | } while(1); |
257 | |
258 | aacirun->ptr = ptr; |
259 | |
260 | spin_unlock(&aacirun->lock); |
261 | |
262 | if (period_elapsed) |
263 | snd_pcm_period_elapsed(aacirun->substream); |
264 | } |
265 | |
266 | if (mask & ISR_URINTR) { |
267 | dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel); |
268 | writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR); |
269 | } |
270 | |
271 | if (mask & ISR_TXINTR) { |
272 | struct aaci_runtime *aacirun = &aaci->playback; |
273 | bool period_elapsed = false; |
274 | void *ptr; |
275 | |
276 | if (!aacirun->substream || !aacirun->start) { |
277 | dev_warn(&aaci->dev->dev, "TX interrupt???\n"); |
278 | writel(0, aacirun->base + AACI_IE); |
279 | return; |
280 | } |
281 | |
282 | spin_lock(&aacirun->lock); |
283 | |
284 | ptr = aacirun->ptr; |
285 | do { |
286 | unsigned int len = aacirun->fifo_bytes; |
287 | u32 val; |
288 | |
289 | if (aacirun->bytes <= 0) { |
290 | aacirun->bytes += aacirun->period; |
291 | period_elapsed = true; |
292 | } |
293 | if (!(aacirun->cr & CR_EN)) |
294 | break; |
295 | |
296 | val = readl(aacirun->base + AACI_SR); |
297 | if (!(val & SR_TXHE)) |
298 | break; |
299 | if (!(val & SR_TXFE)) |
300 | len >>= 1; |
301 | |
302 | aacirun->bytes -= len; |
303 | |
304 | /* writing 16 bytes at a time */ |
305 | for ( ; len > 0; len -= 16) { |
306 | asm( |
307 | "ldmia %0!, {r0, r1, r2, r3}\n\t" |
308 | "stmia %1, {r0, r1, r2, r3}" |
309 | : "+r" (ptr) |
310 | : "r" (aacirun->fifo) |
311 | : "r0", "r1", "r2", "r3", "cc"); |
312 | |
313 | if (ptr >= aacirun->end) |
314 | ptr = aacirun->start; |
315 | } |
316 | } while (1); |
317 | |
318 | aacirun->ptr = ptr; |
319 | |
320 | spin_unlock(&aacirun->lock); |
321 | |
322 | if (period_elapsed) |
323 | snd_pcm_period_elapsed(aacirun->substream); |
324 | } |
325 | } |
326 | |
327 | static irqreturn_t aaci_irq(int irq, void *devid) |
328 | { |
329 | struct aaci *aaci = devid; |
330 | u32 mask; |
331 | int i; |
332 | |
333 | mask = readl(aaci->base + AACI_ALLINTS); |
334 | if (mask) { |
335 | u32 m = mask; |
336 | for (i = 0; i < 4; i++, m >>= 7) { |
337 | if (m & 0x7f) { |
338 | aaci_fifo_irq(aaci, i, m); |
339 | } |
340 | } |
341 | } |
342 | |
343 | return mask ? IRQ_HANDLED : IRQ_NONE; |
344 | } |
345 | |
346 | |
347 | |
348 | /* |
349 | * ALSA support. |
350 | */ |
351 | static struct snd_pcm_hardware aaci_hw_info = { |
352 | .info = SNDRV_PCM_INFO_MMAP | |
353 | SNDRV_PCM_INFO_MMAP_VALID | |
354 | SNDRV_PCM_INFO_INTERLEAVED | |
355 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
356 | SNDRV_PCM_INFO_RESUME, |
357 | |
358 | /* |
359 | * ALSA doesn't support 18-bit or 20-bit packed into 32-bit |
360 | * words. It also doesn't support 12-bit at all. |
361 | */ |
362 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
363 | |
364 | /* rates are setup from the AC'97 codec */ |
365 | .channels_min = 2, |
366 | .channels_max = 2, |
367 | .buffer_bytes_max = 64 * 1024, |
368 | .period_bytes_min = 256, |
369 | .period_bytes_max = PAGE_SIZE, |
370 | .periods_min = 4, |
371 | .periods_max = PAGE_SIZE / 16, |
372 | }; |
373 | |
374 | /* |
375 | * We can support two and four channel audio. Unfortunately |
376 | * six channel audio requires a non-standard channel ordering: |
377 | * 2 -> FL(3), FR(4) |
378 | * 4 -> FL(3), FR(4), SL(7), SR(8) |
379 | * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) |
380 | * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) |
381 | * This requires an ALSA configuration file to correct. |
382 | */ |
383 | static int aaci_rule_channels(struct snd_pcm_hw_params *p, |
384 | struct snd_pcm_hw_rule *rule) |
385 | { |
386 | static unsigned int channel_list[] = { 2, 4, 6 }; |
387 | struct aaci *aaci = rule->private; |
388 | unsigned int mask = 1 << 0, slots; |
389 | |
390 | /* pcms[0] is the our 5.1 PCM instance. */ |
391 | slots = aaci->ac97_bus->pcms[0].r[0].slots; |
392 | if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { |
393 | mask |= 1 << 1; |
394 | if (slots & (1 << AC97_SLOT_LFE)) |
395 | mask |= 1 << 2; |
396 | } |
397 | |
398 | return snd_interval_list(hw_param_interval(p, rule->var), |
399 | ARRAY_SIZE(channel_list), channel_list, mask); |
400 | } |
401 | |
402 | static int aaci_pcm_open(struct snd_pcm_substream *substream) |
403 | { |
404 | struct snd_pcm_runtime *runtime = substream->runtime; |
405 | struct aaci *aaci = substream->private_data; |
406 | struct aaci_runtime *aacirun; |
407 | int ret = 0; |
408 | |
409 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
410 | aacirun = &aaci->playback; |
411 | } else { |
412 | aacirun = &aaci->capture; |
413 | } |
414 | |
415 | aacirun->substream = substream; |
416 | runtime->private_data = aacirun; |
417 | runtime->hw = aaci_hw_info; |
418 | runtime->hw.rates = aacirun->pcm->rates; |
419 | snd_pcm_limit_hw_rates(runtime); |
420 | |
421 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
422 | runtime->hw.channels_max = 6; |
423 | |
424 | /* Add rule describing channel dependency. */ |
425 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
426 | SNDRV_PCM_HW_PARAM_CHANNELS, |
427 | aaci_rule_channels, aaci, |
428 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
429 | if (ret) |
430 | return ret; |
431 | |
432 | if (aacirun->pcm->r[1].slots) |
433 | snd_ac97_pcm_double_rate_rules(runtime); |
434 | } |
435 | |
436 | /* |
437 | * ALSA wants the byte-size of the FIFOs. As we only support |
438 | * 16-bit samples, this is twice the FIFO depth irrespective |
439 | * of whether it's in compact mode or not. |
440 | */ |
441 | runtime->hw.fifo_size = aaci->fifo_depth * 2; |
442 | |
443 | mutex_lock(&aaci->irq_lock); |
444 | if (!aaci->users++) { |
445 | ret = request_irq(aaci->dev->irq[0], aaci_irq, |
446 | IRQF_SHARED, DRIVER_NAME, aaci); |
447 | if (ret != 0) |
448 | aaci->users--; |
449 | } |
450 | mutex_unlock(&aaci->irq_lock); |
451 | |
452 | return ret; |
453 | } |
454 | |
455 | |
456 | /* |
457 | * Common ALSA stuff |
458 | */ |
459 | static int aaci_pcm_close(struct snd_pcm_substream *substream) |
460 | { |
461 | struct aaci *aaci = substream->private_data; |
462 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
463 | |
464 | WARN_ON(aacirun->cr & CR_EN); |
465 | |
466 | aacirun->substream = NULL; |
467 | |
468 | mutex_lock(&aaci->irq_lock); |
469 | if (!--aaci->users) |
470 | free_irq(aaci->dev->irq[0], aaci); |
471 | mutex_unlock(&aaci->irq_lock); |
472 | |
473 | return 0; |
474 | } |
475 | |
476 | static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) |
477 | { |
478 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
479 | |
480 | /* |
481 | * This must not be called with the device enabled. |
482 | */ |
483 | WARN_ON(aacirun->cr & CR_EN); |
484 | |
485 | if (aacirun->pcm_open) |
486 | snd_ac97_pcm_close(aacirun->pcm); |
487 | aacirun->pcm_open = 0; |
488 | |
489 | /* |
490 | * Clear out the DMA and any allocated buffers. |
491 | */ |
492 | snd_pcm_lib_free_pages(substream); |
493 | |
494 | return 0; |
495 | } |
496 | |
497 | /* Channel to slot mask */ |
498 | static const u32 channels_to_slotmask[] = { |
499 | [2] = CR_SL3 | CR_SL4, |
500 | [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, |
501 | [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, |
502 | }; |
503 | |
504 | static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, |
505 | struct snd_pcm_hw_params *params) |
506 | { |
507 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
508 | unsigned int channels = params_channels(params); |
509 | unsigned int rate = params_rate(params); |
510 | int dbl = rate > 48000; |
511 | int err; |
512 | |
513 | aaci_pcm_hw_free(substream); |
514 | if (aacirun->pcm_open) { |
515 | snd_ac97_pcm_close(aacirun->pcm); |
516 | aacirun->pcm_open = 0; |
517 | } |
518 | |
519 | /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */ |
520 | if (dbl && channels != 2) |
521 | return -EINVAL; |
522 | |
523 | err = snd_pcm_lib_malloc_pages(substream, |
524 | params_buffer_bytes(params)); |
525 | if (err >= 0) { |
526 | struct aaci *aaci = substream->private_data; |
527 | |
528 | err = snd_ac97_pcm_open(aacirun->pcm, rate, channels, |
529 | aacirun->pcm->r[dbl].slots); |
530 | |
531 | aacirun->pcm_open = err == 0; |
532 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; |
533 | aacirun->cr |= channels_to_slotmask[channels + dbl * 2]; |
534 | |
535 | /* |
536 | * fifo_bytes is the number of bytes we transfer to/from |
537 | * the FIFO, including padding. So that's x4. As we're |
538 | * in compact mode, the FIFO is half the size. |
539 | */ |
540 | aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2; |
541 | } |
542 | |
543 | return err; |
544 | } |
545 | |
546 | static int aaci_pcm_prepare(struct snd_pcm_substream *substream) |
547 | { |
548 | struct snd_pcm_runtime *runtime = substream->runtime; |
549 | struct aaci_runtime *aacirun = runtime->private_data; |
550 | |
551 | aacirun->period = snd_pcm_lib_period_bytes(substream); |
552 | aacirun->start = runtime->dma_area; |
553 | aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); |
554 | aacirun->ptr = aacirun->start; |
555 | aacirun->bytes = aacirun->period; |
556 | |
557 | return 0; |
558 | } |
559 | |
560 | static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) |
561 | { |
562 | struct snd_pcm_runtime *runtime = substream->runtime; |
563 | struct aaci_runtime *aacirun = runtime->private_data; |
564 | ssize_t bytes = aacirun->ptr - aacirun->start; |
565 | |
566 | return bytes_to_frames(runtime, bytes); |
567 | } |
568 | |
569 | |
570 | /* |
571 | * Playback specific ALSA stuff |
572 | */ |
573 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) |
574 | { |
575 | u32 ie; |
576 | |
577 | ie = readl(aacirun->base + AACI_IE); |
578 | ie &= ~(IE_URIE|IE_TXIE); |
579 | writel(ie, aacirun->base + AACI_IE); |
580 | aacirun->cr &= ~CR_EN; |
581 | aaci_chan_wait_ready(aacirun, SR_TXB); |
582 | writel(aacirun->cr, aacirun->base + AACI_TXCR); |
583 | } |
584 | |
585 | static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) |
586 | { |
587 | u32 ie; |
588 | |
589 | aaci_chan_wait_ready(aacirun, SR_TXB); |
590 | aacirun->cr |= CR_EN; |
591 | |
592 | ie = readl(aacirun->base + AACI_IE); |
593 | ie |= IE_URIE | IE_TXIE; |
594 | writel(ie, aacirun->base + AACI_IE); |
595 | writel(aacirun->cr, aacirun->base + AACI_TXCR); |
596 | } |
597 | |
598 | static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) |
599 | { |
600 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
601 | unsigned long flags; |
602 | int ret = 0; |
603 | |
604 | spin_lock_irqsave(&aacirun->lock, flags); |
605 | |
606 | switch (cmd) { |
607 | case SNDRV_PCM_TRIGGER_START: |
608 | aaci_pcm_playback_start(aacirun); |
609 | break; |
610 | |
611 | case SNDRV_PCM_TRIGGER_RESUME: |
612 | aaci_pcm_playback_start(aacirun); |
613 | break; |
614 | |
615 | case SNDRV_PCM_TRIGGER_STOP: |
616 | aaci_pcm_playback_stop(aacirun); |
617 | break; |
618 | |
619 | case SNDRV_PCM_TRIGGER_SUSPEND: |
620 | aaci_pcm_playback_stop(aacirun); |
621 | break; |
622 | |
623 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
624 | break; |
625 | |
626 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
627 | break; |
628 | |
629 | default: |
630 | ret = -EINVAL; |
631 | } |
632 | |
633 | spin_unlock_irqrestore(&aacirun->lock, flags); |
634 | |
635 | return ret; |
636 | } |
637 | |
638 | static struct snd_pcm_ops aaci_playback_ops = { |
639 | .open = aaci_pcm_open, |
640 | .close = aaci_pcm_close, |
641 | .ioctl = snd_pcm_lib_ioctl, |
642 | .hw_params = aaci_pcm_hw_params, |
643 | .hw_free = aaci_pcm_hw_free, |
644 | .prepare = aaci_pcm_prepare, |
645 | .trigger = aaci_pcm_playback_trigger, |
646 | .pointer = aaci_pcm_pointer, |
647 | }; |
648 | |
649 | static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) |
650 | { |
651 | u32 ie; |
652 | |
653 | aaci_chan_wait_ready(aacirun, SR_RXB); |
654 | |
655 | ie = readl(aacirun->base + AACI_IE); |
656 | ie &= ~(IE_ORIE | IE_RXIE); |
657 | writel(ie, aacirun->base+AACI_IE); |
658 | |
659 | aacirun->cr &= ~CR_EN; |
660 | |
661 | writel(aacirun->cr, aacirun->base + AACI_RXCR); |
662 | } |
663 | |
664 | static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) |
665 | { |
666 | u32 ie; |
667 | |
668 | aaci_chan_wait_ready(aacirun, SR_RXB); |
669 | |
670 | #ifdef DEBUG |
671 | /* RX Timeout value: bits 28:17 in RXCR */ |
672 | aacirun->cr |= 0xf << 17; |
673 | #endif |
674 | |
675 | aacirun->cr |= CR_EN; |
676 | writel(aacirun->cr, aacirun->base + AACI_RXCR); |
677 | |
678 | ie = readl(aacirun->base + AACI_IE); |
679 | ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full |
680 | writel(ie, aacirun->base + AACI_IE); |
681 | } |
682 | |
683 | static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) |
684 | { |
685 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
686 | unsigned long flags; |
687 | int ret = 0; |
688 | |
689 | spin_lock_irqsave(&aacirun->lock, flags); |
690 | |
691 | switch (cmd) { |
692 | case SNDRV_PCM_TRIGGER_START: |
693 | aaci_pcm_capture_start(aacirun); |
694 | break; |
695 | |
696 | case SNDRV_PCM_TRIGGER_RESUME: |
697 | aaci_pcm_capture_start(aacirun); |
698 | break; |
699 | |
700 | case SNDRV_PCM_TRIGGER_STOP: |
701 | aaci_pcm_capture_stop(aacirun); |
702 | break; |
703 | |
704 | case SNDRV_PCM_TRIGGER_SUSPEND: |
705 | aaci_pcm_capture_stop(aacirun); |
706 | break; |
707 | |
708 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
709 | break; |
710 | |
711 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
712 | break; |
713 | |
714 | default: |
715 | ret = -EINVAL; |
716 | } |
717 | |
718 | spin_unlock_irqrestore(&aacirun->lock, flags); |
719 | |
720 | return ret; |
721 | } |
722 | |
723 | static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream) |
724 | { |
725 | struct snd_pcm_runtime *runtime = substream->runtime; |
726 | struct aaci *aaci = substream->private_data; |
727 | |
728 | aaci_pcm_prepare(substream); |
729 | |
730 | /* allow changing of sample rate */ |
731 | aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */ |
732 | aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); |
733 | aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate); |
734 | |
735 | /* Record select: Mic: 0, Aux: 3, Line: 4 */ |
736 | aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404); |
737 | |
738 | return 0; |
739 | } |
740 | |
741 | static struct snd_pcm_ops aaci_capture_ops = { |
742 | .open = aaci_pcm_open, |
743 | .close = aaci_pcm_close, |
744 | .ioctl = snd_pcm_lib_ioctl, |
745 | .hw_params = aaci_pcm_hw_params, |
746 | .hw_free = aaci_pcm_hw_free, |
747 | .prepare = aaci_pcm_capture_prepare, |
748 | .trigger = aaci_pcm_capture_trigger, |
749 | .pointer = aaci_pcm_pointer, |
750 | }; |
751 | |
752 | /* |
753 | * Power Management. |
754 | */ |
755 | #ifdef CONFIG_PM |
756 | static int aaci_do_suspend(struct snd_card *card, unsigned int state) |
757 | { |
758 | struct aaci *aaci = card->private_data; |
759 | snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); |
760 | snd_pcm_suspend_all(aaci->pcm); |
761 | return 0; |
762 | } |
763 | |
764 | static int aaci_do_resume(struct snd_card *card, unsigned int state) |
765 | { |
766 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
767 | return 0; |
768 | } |
769 | |
770 | static int aaci_suspend(struct amba_device *dev, pm_message_t state) |
771 | { |
772 | struct snd_card *card = amba_get_drvdata(dev); |
773 | return card ? aaci_do_suspend(card) : 0; |
774 | } |
775 | |
776 | static int aaci_resume(struct amba_device *dev) |
777 | { |
778 | struct snd_card *card = amba_get_drvdata(dev); |
779 | return card ? aaci_do_resume(card) : 0; |
780 | } |
781 | #else |
782 | #define aaci_do_suspend NULL |
783 | #define aaci_do_resume NULL |
784 | #define aaci_suspend NULL |
785 | #define aaci_resume NULL |
786 | #endif |
787 | |
788 | |
789 | static struct ac97_pcm ac97_defs[] = { |
790 | [0] = { /* Front PCM */ |
791 | .exclusive = 1, |
792 | .r = { |
793 | [0] = { |
794 | .slots = (1 << AC97_SLOT_PCM_LEFT) | |
795 | (1 << AC97_SLOT_PCM_RIGHT) | |
796 | (1 << AC97_SLOT_PCM_CENTER) | |
797 | (1 << AC97_SLOT_PCM_SLEFT) | |
798 | (1 << AC97_SLOT_PCM_SRIGHT) | |
799 | (1 << AC97_SLOT_LFE), |
800 | }, |
801 | [1] = { |
802 | .slots = (1 << AC97_SLOT_PCM_LEFT) | |
803 | (1 << AC97_SLOT_PCM_RIGHT) | |
804 | (1 << AC97_SLOT_PCM_LEFT_0) | |
805 | (1 << AC97_SLOT_PCM_RIGHT_0), |
806 | }, |
807 | }, |
808 | }, |
809 | [1] = { /* PCM in */ |
810 | .stream = 1, |
811 | .exclusive = 1, |
812 | .r = { |
813 | [0] = { |
814 | .slots = (1 << AC97_SLOT_PCM_LEFT) | |
815 | (1 << AC97_SLOT_PCM_RIGHT), |
816 | }, |
817 | }, |
818 | }, |
819 | [2] = { /* Mic in */ |
820 | .stream = 1, |
821 | .exclusive = 1, |
822 | .r = { |
823 | [0] = { |
824 | .slots = (1 << AC97_SLOT_MIC), |
825 | }, |
826 | }, |
827 | } |
828 | }; |
829 | |
830 | static struct snd_ac97_bus_ops aaci_bus_ops = { |
831 | .write = aaci_ac97_write, |
832 | .read = aaci_ac97_read, |
833 | }; |
834 | |
835 | static int aaci_probe_ac97(struct aaci *aaci) |
836 | { |
837 | struct snd_ac97_template ac97_template; |
838 | struct snd_ac97_bus *ac97_bus; |
839 | struct snd_ac97 *ac97; |
840 | int ret; |
841 | |
842 | /* |
843 | * Assert AACIRESET for 2us |
844 | */ |
845 | writel(0, aaci->base + AACI_RESET); |
846 | udelay(2); |
847 | writel(RESET_NRST, aaci->base + AACI_RESET); |
848 | |
849 | /* |
850 | * Give the AC'97 codec more than enough time |
851 | * to wake up. (42us = ~2 frames at 48kHz.) |
852 | */ |
853 | udelay(FRAME_PERIOD_US * 2); |
854 | |
855 | ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); |
856 | if (ret) |
857 | goto out; |
858 | |
859 | ac97_bus->clock = 48000; |
860 | aaci->ac97_bus = ac97_bus; |
861 | |
862 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
863 | ac97_template.private_data = aaci; |
864 | ac97_template.num = 0; |
865 | ac97_template.scaps = AC97_SCAP_SKIP_MODEM; |
866 | |
867 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); |
868 | if (ret) |
869 | goto out; |
870 | aaci->ac97 = ac97; |
871 | |
872 | /* |
873 | * Disable AC97 PC Beep input on audio codecs. |
874 | */ |
875 | if (ac97_is_audio(ac97)) |
876 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); |
877 | |
878 | ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); |
879 | if (ret) |
880 | goto out; |
881 | |
882 | aaci->playback.pcm = &ac97_bus->pcms[0]; |
883 | aaci->capture.pcm = &ac97_bus->pcms[1]; |
884 | |
885 | out: |
886 | return ret; |
887 | } |
888 | |
889 | static void aaci_free_card(struct snd_card *card) |
890 | { |
891 | struct aaci *aaci = card->private_data; |
892 | if (aaci->base) |
893 | iounmap(aaci->base); |
894 | } |
895 | |
896 | static struct aaci *aaci_init_card(struct amba_device *dev) |
897 | { |
898 | struct aaci *aaci; |
899 | struct snd_card *card; |
900 | int err; |
901 | |
902 | err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
903 | THIS_MODULE, sizeof(struct aaci), &card); |
904 | if (err < 0) |
905 | return NULL; |
906 | |
907 | card->private_free = aaci_free_card; |
908 | |
909 | strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); |
910 | strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); |
911 | snprintf(card->longname, sizeof(card->longname), |
912 | "%s PL%03x rev%u at 0x%08llx, irq %d", |
913 | card->shortname, amba_part(dev), amba_rev(dev), |
914 | (unsigned long long)dev->res.start, dev->irq[0]); |
915 | |
916 | aaci = card->private_data; |
917 | mutex_init(&aaci->ac97_sem); |
918 | mutex_init(&aaci->irq_lock); |
919 | aaci->card = card; |
920 | aaci->dev = dev; |
921 | |
922 | /* Set MAINCR to allow slot 1 and 2 data IO */ |
923 | aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | |
924 | MAINCR_SL2RXEN | MAINCR_SL2TXEN; |
925 | |
926 | return aaci; |
927 | } |
928 | |
929 | static int aaci_init_pcm(struct aaci *aaci) |
930 | { |
931 | struct snd_pcm *pcm; |
932 | int ret; |
933 | |
934 | ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm); |
935 | if (ret == 0) { |
936 | aaci->pcm = pcm; |
937 | pcm->private_data = aaci; |
938 | pcm->info_flags = 0; |
939 | |
940 | strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); |
941 | |
942 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); |
943 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); |
944 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
945 | NULL, 0, 64 * 1024); |
946 | } |
947 | |
948 | return ret; |
949 | } |
950 | |
951 | static unsigned int aaci_size_fifo(struct aaci *aaci) |
952 | { |
953 | struct aaci_runtime *aacirun = &aaci->playback; |
954 | int i; |
955 | |
956 | /* |
957 | * Enable the channel, but don't assign it to any slots, so |
958 | * it won't empty onto the AC'97 link. |
959 | */ |
960 | writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR); |
961 | |
962 | for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++) |
963 | writel(0, aacirun->fifo); |
964 | |
965 | writel(0, aacirun->base + AACI_TXCR); |
966 | |
967 | /* |
968 | * Re-initialise the AACI after the FIFO depth test, to |
969 | * ensure that the FIFOs are empty. Unfortunately, merely |
970 | * disabling the channel doesn't clear the FIFO. |
971 | */ |
972 | writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); |
973 | readl(aaci->base + AACI_MAINCR); |
974 | udelay(1); |
975 | writel(aaci->maincr, aaci->base + AACI_MAINCR); |
976 | |
977 | /* |
978 | * If we hit 4096 entries, we failed. Go back to the specified |
979 | * fifo depth. |
980 | */ |
981 | if (i == 4096) |
982 | i = 8; |
983 | |
984 | return i; |
985 | } |
986 | |
987 | static int aaci_probe(struct amba_device *dev, |
988 | const struct amba_id *id) |
989 | { |
990 | struct aaci *aaci; |
991 | int ret, i; |
992 | |
993 | ret = amba_request_regions(dev, NULL); |
994 | if (ret) |
995 | return ret; |
996 | |
997 | aaci = aaci_init_card(dev); |
998 | if (!aaci) { |
999 | ret = -ENOMEM; |
1000 | goto out; |
1001 | } |
1002 | |
1003 | aaci->base = ioremap(dev->res.start, resource_size(&dev->res)); |
1004 | if (!aaci->base) { |
1005 | ret = -ENOMEM; |
1006 | goto out; |
1007 | } |
1008 | |
1009 | /* |
1010 | * Playback uses AACI channel 0 |
1011 | */ |
1012 | spin_lock_init(&aaci->playback.lock); |
1013 | aaci->playback.base = aaci->base + AACI_CSCH1; |
1014 | aaci->playback.fifo = aaci->base + AACI_DR1; |
1015 | |
1016 | /* |
1017 | * Capture uses AACI channel 0 |
1018 | */ |
1019 | spin_lock_init(&aaci->capture.lock); |
1020 | aaci->capture.base = aaci->base + AACI_CSCH1; |
1021 | aaci->capture.fifo = aaci->base + AACI_DR1; |
1022 | |
1023 | for (i = 0; i < 4; i++) { |
1024 | void __iomem *base = aaci->base + i * 0x14; |
1025 | |
1026 | writel(0, base + AACI_IE); |
1027 | writel(0, base + AACI_TXCR); |
1028 | writel(0, base + AACI_RXCR); |
1029 | } |
1030 | |
1031 | writel(0x1fff, aaci->base + AACI_INTCLR); |
1032 | writel(aaci->maincr, aaci->base + AACI_MAINCR); |
1033 | /* |
1034 | * Fix: ac97 read back fail errors by reading |
1035 | * from any arbitrary aaci register. |
1036 | */ |
1037 | readl(aaci->base + AACI_CSCH1); |
1038 | ret = aaci_probe_ac97(aaci); |
1039 | if (ret) |
1040 | goto out; |
1041 | |
1042 | /* |
1043 | * Size the FIFOs (must be multiple of 16). |
1044 | * This is the number of entries in the FIFO. |
1045 | */ |
1046 | aaci->fifo_depth = aaci_size_fifo(aaci); |
1047 | if (aaci->fifo_depth & 15) { |
1048 | printk(KERN_WARNING "AACI: FIFO depth %d not supported\n", |
1049 | aaci->fifo_depth); |
1050 | ret = -ENODEV; |
1051 | goto out; |
1052 | } |
1053 | |
1054 | ret = aaci_init_pcm(aaci); |
1055 | if (ret) |
1056 | goto out; |
1057 | |
1058 | snd_card_set_dev(aaci->card, &dev->dev); |
1059 | |
1060 | ret = snd_card_register(aaci->card); |
1061 | if (ret == 0) { |
1062 | dev_info(&dev->dev, "%s\n", aaci->card->longname); |
1063 | dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth); |
1064 | amba_set_drvdata(dev, aaci->card); |
1065 | return ret; |
1066 | } |
1067 | |
1068 | out: |
1069 | if (aaci) |
1070 | snd_card_free(aaci->card); |
1071 | amba_release_regions(dev); |
1072 | return ret; |
1073 | } |
1074 | |
1075 | static int aaci_remove(struct amba_device *dev) |
1076 | { |
1077 | struct snd_card *card = amba_get_drvdata(dev); |
1078 | |
1079 | amba_set_drvdata(dev, NULL); |
1080 | |
1081 | if (card) { |
1082 | struct aaci *aaci = card->private_data; |
1083 | writel(0, aaci->base + AACI_MAINCR); |
1084 | |
1085 | snd_card_free(card); |
1086 | amba_release_regions(dev); |
1087 | } |
1088 | |
1089 | return 0; |
1090 | } |
1091 | |
1092 | static struct amba_id aaci_ids[] = { |
1093 | { |
1094 | .id = 0x00041041, |
1095 | .mask = 0x000fffff, |
1096 | }, |
1097 | { 0, 0 }, |
1098 | }; |
1099 | |
1100 | MODULE_DEVICE_TABLE(amba, aaci_ids); |
1101 | |
1102 | static struct amba_driver aaci_driver = { |
1103 | .drv = { |
1104 | .name = DRIVER_NAME, |
1105 | }, |
1106 | .probe = aaci_probe, |
1107 | .remove = aaci_remove, |
1108 | .suspend = aaci_suspend, |
1109 | .resume = aaci_resume, |
1110 | .id_table = aaci_ids, |
1111 | }; |
1112 | |
1113 | module_amba_driver(aaci_driver); |
1114 | |
1115 | MODULE_LICENSE("GPL"); |
1116 | MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); |
1117 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9