aboutsummaryrefslogtreecommitdiffstats
path: root/sound/arm/aaci.c
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2005-05-12 08:04:59 -0400
committerJaroslav Kysela <perex@suse.cz>2005-05-29 04:06:52 -0400
commitcb5a6ffc5c09bc354af69407dae710dcddcced37 (patch)
tree077341868201a1514a87f8cf25902903b873790f /sound/arm/aaci.c
parent9b9a5afffd8636a82c6b32970342aef9d1f3d17d (diff)
[ALSA] ARM AACI primecell driver
ARM,/arm/Makefile,ARM AACI PL041 driver Add support for the ARM AACI Primecell, which provides an AC'97 based interface. This driver only provides playback support. This has been extensively tested with an LM4549 AC'97 codec. Signed-off-by: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/arm/aaci.c')
-rw-r--r--sound/arm/aaci.c968
1 files changed, 968 insertions, 0 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
new file mode 100644
index 000000000000..08cc3ddca96f
--- /dev/null
+++ b/sound/arm/aaci.c
@@ -0,0 +1,968 @@
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
21#include <asm/io.h>
22#include <asm/irq.h>
23#include <asm/hardware/amba.h>
24
25#include <sound/driver.h>
26#include <sound/core.h>
27#include <sound/initval.h>
28#include <sound/ac97_codec.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31
32#include "aaci.h"
33#include "devdma.h"
34
35#define DRIVER_NAME "aaci-pl041"
36
37/*
38 * PM support is not complete. Turn it off.
39 */
40#undef CONFIG_PM
41
42static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
43{
44 u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
45
46 /*
47 * Ensure that the slot 1/2 RX registers are empty.
48 */
49 v = readl(aaci->base + AACI_SLFR);
50 if (v & SLFR_2RXV)
51 readl(aaci->base + AACI_SL2RX);
52 if (v & SLFR_1RXV)
53 readl(aaci->base + AACI_SL1RX);
54
55 writel(maincr, aaci->base + AACI_MAINCR);
56}
57
58/*
59 * P29:
60 * The recommended use of programming the external codec through slot 1
61 * and slot 2 data is to use the channels during setup routines and the
62 * slot register at any other time. The data written into slot 1, slot 2
63 * and slot 12 registers is transmitted only when their corresponding
64 * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
65 * register.
66 */
67static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
68{
69 struct aaci *aaci = ac97->private_data;
70 u32 v;
71
72 if (ac97->num >= 4)
73 return;
74
75 down(&aaci->ac97_sem);
76
77 aaci_ac97_select_codec(aaci, ac97);
78
79 /*
80 * P54: You must ensure that AACI_SL2TX is always written
81 * to, if required, before data is written to AACI_SL1TX.
82 */
83 writel(val << 4, aaci->base + AACI_SL2TX);
84 writel(reg << 12, aaci->base + AACI_SL1TX);
85
86 /*
87 * Wait for the transmission of both slots to complete.
88 */
89 do {
90 v = readl(aaci->base + AACI_SLFR);
91 } while (v & (SLFR_1TXB|SLFR_2TXB));
92
93 up(&aaci->ac97_sem);
94}
95
96/*
97 * Read an AC'97 register.
98 */
99static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
100{
101 struct aaci *aaci = ac97->private_data;
102 u32 v;
103
104 if (ac97->num >= 4)
105 return ~0;
106
107 down(&aaci->ac97_sem);
108
109 aaci_ac97_select_codec(aaci, ac97);
110
111 /*
112 * Write the register address to slot 1.
113 */
114 writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
115
116 /*
117 * Wait for the transmission to complete.
118 */
119 do {
120 v = readl(aaci->base + AACI_SLFR);
121 } while (v & SLFR_1TXB);
122
123 /*
124 * Give the AC'97 codec more than enough time
125 * to respond. (42us = ~2 frames at 48kHz.)
126 */
127 udelay(42);
128
129 /*
130 * Wait for slot 2 to indicate data.
131 */
132 do {
133 cond_resched();
134 v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
135 } while (v != (SLFR_1RXV|SLFR_2RXV));
136
137 v = readl(aaci->base + AACI_SL1RX) >> 12;
138 if (v == reg) {
139 v = readl(aaci->base + AACI_SL2RX) >> 4;
140 } else {
141 dev_err(&aaci->dev->dev,
142 "wrong ac97 register read back (%x != %x)\n",
143 v, reg);
144 v = ~0;
145 }
146
147 up(&aaci->ac97_sem);
148 return v;
149}
150
151static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
152{
153 u32 val;
154 int timeout = 5000;
155
156 do {
157 val = readl(aacirun->base + AACI_SR);
158 } while (val & (SR_TXB|SR_RXB) && timeout--);
159}
160
161
162
163/*
164 * Interrupt support.
165 */
166static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
167{
168 if (mask & ISR_URINTR) {
169 writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
170 }
171
172 if (mask & ISR_TXINTR) {
173 struct aaci_runtime *aacirun = &aaci->playback;
174 void *ptr;
175
176 if (!aacirun->substream || !aacirun->start) {
177 dev_warn(&aaci->dev->dev, "TX interrupt???");
178 writel(0, aacirun->base + AACI_IE);
179 return;
180 }
181
182 ptr = aacirun->ptr;
183 do {
184 unsigned int len = aacirun->fifosz;
185 u32 val;
186
187 if (aacirun->bytes <= 0) {
188 aacirun->bytes += aacirun->period;
189 aacirun->ptr = ptr;
190 spin_unlock(&aaci->lock);
191 snd_pcm_period_elapsed(aacirun->substream);
192 spin_lock(&aaci->lock);
193 }
194 if (!(aacirun->cr & TXCR_TXEN))
195 break;
196
197 val = readl(aacirun->base + AACI_SR);
198 if (!(val & SR_TXHE))
199 break;
200 if (!(val & SR_TXFE))
201 len >>= 1;
202
203 aacirun->bytes -= len;
204
205 /* writing 16 bytes at a time */
206 for ( ; len > 0; len -= 16) {
207 asm(
208 "ldmia %0!, {r0, r1, r2, r3}\n\t"
209 "stmia %1, {r0, r1, r2, r3}"
210 : "+r" (ptr)
211 : "r" (aacirun->fifo)
212 : "r0", "r1", "r2", "r3", "cc");
213
214 if (ptr >= aacirun->end)
215 ptr = aacirun->start;
216 }
217 } while (1);
218
219 aacirun->ptr = ptr;
220 }
221}
222
223static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
224{
225 struct aaci *aaci = devid;
226 u32 mask;
227 int i;
228
229 spin_lock(&aaci->lock);
230 mask = readl(aaci->base + AACI_ALLINTS);
231 if (mask) {
232 u32 m = mask;
233 for (i = 0; i < 4; i++, m >>= 7) {
234 if (m & 0x7f) {
235 aaci_fifo_irq(aaci, m);
236 }
237 }
238 }
239 spin_unlock(&aaci->lock);
240
241 return mask ? IRQ_HANDLED : IRQ_NONE;
242}
243
244
245
246/*
247 * ALSA support.
248 */
249
250struct aaci_stream {
251 unsigned char codec_idx;
252 unsigned char rate_idx;
253};
254
255static struct aaci_stream aaci_streams[] = {
256 [ACSTREAM_FRONT] = {
257 .codec_idx = 0,
258 .rate_idx = AC97_RATES_FRONT_DAC,
259 },
260 [ACSTREAM_SURROUND] = {
261 .codec_idx = 0,
262 .rate_idx = AC97_RATES_SURR_DAC,
263 },
264 [ACSTREAM_LFE] = {
265 .codec_idx = 0,
266 .rate_idx = AC97_RATES_LFE_DAC,
267 },
268};
269
270static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
271{
272 struct aaci_stream *s = aaci_streams + streamid;
273 return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
274}
275
276static unsigned int rate_list[] = {
277 5512, 8000, 11025, 16000, 22050, 32000, 44100,
278 48000, 64000, 88200, 96000, 176400, 192000
279};
280
281/*
282 * Double-rate rule: we can support double rate iff channels == 2
283 * (unimplemented)
284 */
285static int
286aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
287{
288 struct aaci *aaci = rule->private;
289 unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
290 snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
291
292 switch (c->max) {
293 case 6:
294 rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
295 case 4:
296 rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
297 case 2:
298 rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
299 }
300
301 return snd_interval_list(hw_param_interval(p, rule->var),
302 ARRAY_SIZE(rate_list), rate_list,
303 rate_mask);
304}
305
306static snd_pcm_hardware_t aaci_hw_info = {
307 .info = SNDRV_PCM_INFO_MMAP |
308 SNDRV_PCM_INFO_MMAP_VALID |
309 SNDRV_PCM_INFO_INTERLEAVED |
310 SNDRV_PCM_INFO_BLOCK_TRANSFER |
311 SNDRV_PCM_INFO_RESUME,
312
313 /*
314 * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
315 * words. It also doesn't support 12-bit at all.
316 */
317 .formats = SNDRV_PCM_FMTBIT_S16_LE,
318
319 /* should this be continuous or knot? */
320 .rates = SNDRV_PCM_RATE_CONTINUOUS,
321 .rate_max = 48000,
322 .rate_min = 4000,
323 .channels_min = 2,
324 .channels_max = 6,
325 .buffer_bytes_max = 64 * 1024,
326 .period_bytes_min = 256,
327 .period_bytes_max = PAGE_SIZE,
328 .periods_min = 4,
329 .periods_max = PAGE_SIZE / 16,
330};
331
332static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
333 struct aaci_runtime *aacirun)
334{
335 snd_pcm_runtime_t *runtime = substream->runtime;
336 int ret;
337
338 aacirun->substream = substream;
339 runtime->private_data = aacirun;
340 runtime->hw = aaci_hw_info;
341
342 /*
343 * FIXME: ALSA specifies fifo_size in bytes. If we're in normal
344 * mode, each 32-bit word contains one sample. If we're in
345 * compact mode, each 32-bit word contains two samples, effectively
346 * halving the FIFO size. However, we don't know for sure which
347 * we'll be using at this point. We set this to the lower limit.
348 */
349 runtime->hw.fifo_size = aaci->fifosize * 2;
350
351 /*
352 * Add rule describing hardware rate dependency
353 * on the number of channels.
354 */
355 ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
356 aaci_rule_rate_by_channels, aaci,
357 SNDRV_PCM_HW_PARAM_CHANNELS,
358 SNDRV_PCM_HW_PARAM_RATE, -1);
359 if (ret)
360 goto out;
361
362 ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT,
363 DRIVER_NAME, aaci);
364 if (ret)
365 goto out;
366
367 return 0;
368
369 out:
370 return ret;
371}
372
373
374/*
375 * Common ALSA stuff
376 */
377static int aaci_pcm_close(snd_pcm_substream_t *substream)
378{
379 struct aaci *aaci = substream->private_data;
380 struct aaci_runtime *aacirun = substream->runtime->private_data;
381
382 WARN_ON(aacirun->cr & TXCR_TXEN);
383
384 aacirun->substream = NULL;
385 free_irq(aaci->dev->irq[0], aaci);
386
387 return 0;
388}
389
390static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
391{
392 struct aaci_runtime *aacirun = substream->runtime->private_data;
393
394 /*
395 * This must not be called with the device enabled.
396 */
397 WARN_ON(aacirun->cr & TXCR_TXEN);
398
399 if (aacirun->pcm_open)
400 snd_ac97_pcm_close(aacirun->pcm);
401 aacirun->pcm_open = 0;
402
403 /*
404 * Clear out the DMA and any allocated buffers.
405 */
406 devdma_hw_free(NULL, substream);
407
408 return 0;
409}
410
411static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
412 struct aaci_runtime *aacirun,
413 snd_pcm_hw_params_t *params)
414{
415 int err;
416
417 aaci_pcm_hw_free(substream);
418
419 err = devdma_hw_alloc(NULL, substream,
420 params_buffer_bytes(params));
421 if (err < 0)
422 goto out;
423
424 err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
425 params_channels(params),
426 aacirun->pcm->r[0].slots);
427 if (err)
428 goto out;
429
430 aacirun->pcm_open = 1;
431
432 out:
433 return err;
434}
435
436static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
437{
438 snd_pcm_runtime_t *runtime = substream->runtime;
439 struct aaci_runtime *aacirun = runtime->private_data;
440
441 aacirun->start = (void *)runtime->dma_area;
442 aacirun->end = aacirun->start + runtime->dma_bytes;
443 aacirun->ptr = aacirun->start;
444 aacirun->period =
445 aacirun->bytes = frames_to_bytes(runtime, runtime->period_size);
446
447 return 0;
448}
449
450static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
451{
452 snd_pcm_runtime_t *runtime = substream->runtime;
453 struct aaci_runtime *aacirun = runtime->private_data;
454 ssize_t bytes = aacirun->ptr - aacirun->start;
455
456 return bytes_to_frames(runtime, bytes);
457}
458
459static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
460{
461 return devdma_mmap(NULL, substream, vma);
462}
463
464
465/*
466 * Playback specific ALSA stuff
467 */
468static const u32 channels_to_txmask[] = {
469 [2] = TXCR_TX3 | TXCR_TX4,
470 [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
471 [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
472};
473
474/*
475 * We can support two and four channel audio. Unfortunately
476 * six channel audio requires a non-standard channel ordering:
477 * 2 -> FL(3), FR(4)
478 * 4 -> FL(3), FR(4), SL(7), SR(8)
479 * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
480 * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
481 * This requires an ALSA configuration file to correct.
482 */
483static unsigned int channel_list[] = { 2, 4, 6 };
484
485static int
486aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
487{
488 struct aaci *aaci = rule->private;
489 unsigned int chan_mask = 1 << 0, slots;
490
491 /*
492 * pcms[0] is the our 5.1 PCM instance.
493 */
494 slots = aaci->ac97_bus->pcms[0].r[0].slots;
495 if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
496 chan_mask |= 1 << 1;
497 if (slots & (1 << AC97_SLOT_LFE))
498 chan_mask |= 1 << 2;
499 }
500
501 return snd_interval_list(hw_param_interval(p, rule->var),
502 ARRAY_SIZE(channel_list), channel_list,
503 chan_mask);
504}
505
506static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
507{
508 struct aaci *aaci = substream->private_data;
509 int ret;
510
511 /*
512 * Add rule describing channel dependency.
513 */
514 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
515 SNDRV_PCM_HW_PARAM_CHANNELS,
516 aaci_rule_channels, aaci,
517 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
518 if (ret)
519 return ret;
520
521 return aaci_pcm_open(aaci, substream, &aaci->playback);
522}
523
524static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
525 snd_pcm_hw_params_t *params)
526{
527 struct aaci *aaci = substream->private_data;
528 struct aaci_runtime *aacirun = substream->runtime->private_data;
529 unsigned int channels = params_channels(params);
530 int ret;
531
532 WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
533 !channels_to_txmask[channels]);
534
535 ret = aaci_pcm_hw_params(substream, aacirun, params);
536
537 /*
538 * Enable FIFO, compact mode, 16 bits per sample.
539 * FIXME: double rate slots?
540 */
541 if (ret >= 0) {
542 aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
543 aacirun->cr |= channels_to_txmask[channels];
544
545 aacirun->fifosz = aaci->fifosize * 4;
546 if (aacirun->cr & TXCR_COMPACT)
547 aacirun->fifosz >>= 1;
548 }
549 return ret;
550}
551
552static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
553{
554 u32 ie;
555
556 ie = readl(aacirun->base + AACI_IE);
557 ie &= ~(IE_URIE|IE_TXIE);
558 writel(ie, aacirun->base + AACI_IE);
559 aacirun->cr &= ~TXCR_TXEN;
560 aaci_chan_wait_ready(aacirun);
561 writel(aacirun->cr, aacirun->base + AACI_TXCR);
562}
563
564static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
565{
566 u32 ie;
567
568 aaci_chan_wait_ready(aacirun);
569 aacirun->cr |= TXCR_TXEN;
570
571 ie = readl(aacirun->base + AACI_IE);
572 ie |= IE_URIE | IE_TXIE;
573 writel(ie, aacirun->base + AACI_IE);
574 writel(aacirun->cr, aacirun->base + AACI_TXCR);
575}
576
577static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
578{
579 struct aaci *aaci = substream->private_data;
580 struct aaci_runtime *aacirun = substream->runtime->private_data;
581 unsigned long flags;
582 int ret = 0;
583
584 spin_lock_irqsave(&aaci->lock, flags);
585 switch (cmd) {
586 case SNDRV_PCM_TRIGGER_START:
587 aaci_pcm_playback_start(aacirun);
588 break;
589
590 case SNDRV_PCM_TRIGGER_RESUME:
591 aaci_pcm_playback_start(aacirun);
592 break;
593
594 case SNDRV_PCM_TRIGGER_STOP:
595 aaci_pcm_playback_stop(aacirun);
596 break;
597
598 case SNDRV_PCM_TRIGGER_SUSPEND:
599 aaci_pcm_playback_stop(aacirun);
600 break;
601
602 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
603 break;
604
605 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
606 break;
607
608 default:
609 ret = -EINVAL;
610 }
611 spin_unlock_irqrestore(&aaci->lock, flags);
612
613 return ret;
614}
615
616static snd_pcm_ops_t aaci_playback_ops = {
617 .open = aaci_pcm_playback_open,
618 .close = aaci_pcm_close,
619 .ioctl = snd_pcm_lib_ioctl,
620 .hw_params = aaci_pcm_playback_hw_params,
621 .hw_free = aaci_pcm_hw_free,
622 .prepare = aaci_pcm_prepare,
623 .trigger = aaci_pcm_playback_trigger,
624 .pointer = aaci_pcm_pointer,
625 .mmap = aaci_pcm_mmap,
626};
627
628
629
630/*
631 * Power Management.
632 */
633#ifdef CONFIG_PM
634static int aaci_do_suspend(snd_card_t *card, unsigned int state)
635{
636 struct aaci *aaci = card->private_data;
637 if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
638 snd_pcm_suspend_all(aaci->pcm);
639 snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
640 }
641 return 0;
642}
643
644static int aaci_do_resume(snd_card_t *card, unsigned int state)
645{
646 struct aaci *aaci = card->private_data;
647 if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
648 snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
649 }
650 return 0;
651}
652
653static int aaci_suspend(struct amba_device *dev, u32 state)
654{
655 snd_card_t *card = amba_get_drvdata(dev);
656 return card ? aaci_do_suspend(card) : 0;
657}
658
659static int aaci_resume(struct amba_device *dev)
660{
661 snd_card_t *card = amba_get_drvdata(dev);
662 return card ? aaci_do_resume(card) : 0;
663}
664#else
665#define aaci_do_suspend NULL
666#define aaci_do_resume NULL
667#define aaci_suspend NULL
668#define aaci_resume NULL
669#endif
670
671
672static struct ac97_pcm ac97_defs[] __devinitdata = {
673 [0] = { /* Front PCM */
674 .exclusive = 1,
675 .r = {
676 [0] = {
677 .slots = (1 << AC97_SLOT_PCM_LEFT) |
678 (1 << AC97_SLOT_PCM_RIGHT) |
679 (1 << AC97_SLOT_PCM_CENTER) |
680 (1 << AC97_SLOT_PCM_SLEFT) |
681 (1 << AC97_SLOT_PCM_SRIGHT) |
682 (1 << AC97_SLOT_LFE),
683 },
684 },
685 },
686 [1] = { /* PCM in */
687 .stream = 1,
688 .exclusive = 1,
689 .r = {
690 [0] = {
691 .slots = (1 << AC97_SLOT_PCM_LEFT) |
692 (1 << AC97_SLOT_PCM_RIGHT),
693 },
694 },
695 },
696 [2] = { /* Mic in */
697 .stream = 1,
698 .exclusive = 1,
699 .r = {
700 [0] = {
701 .slots = (1 << AC97_SLOT_MIC),
702 },
703 },
704 }
705};
706
707static ac97_bus_ops_t aaci_bus_ops = {
708 .write = aaci_ac97_write,
709 .read = aaci_ac97_read,
710};
711
712static int __devinit aaci_probe_ac97(struct aaci *aaci)
713{
714 ac97_template_t ac97_template;
715 ac97_bus_t *ac97_bus;
716 ac97_t *ac97;
717 int ret;
718
719 /*
720 * Assert AACIRESET for 2us
721 */
722 writel(0, aaci->base + AACI_RESET);
723 udelay(2);
724 writel(RESET_NRST, aaci->base + AACI_RESET);
725
726 /*
727 * Give the AC'97 codec more than enough time
728 * to wake up. (42us = ~2 frames at 48kHz.)
729 */
730 udelay(42);
731
732 ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
733 if (ret)
734 goto out;
735
736 ac97_bus->clock = 48000;
737 aaci->ac97_bus = ac97_bus;
738
739 memset(&ac97_template, 0, sizeof(ac97_template_t));
740 ac97_template.private_data = aaci;
741 ac97_template.num = 0;
742 ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
743
744 ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
745 if (ret)
746 goto out;
747
748 /*
749 * Disable AC97 PC Beep input on audio codecs.
750 */
751 if (ac97_is_audio(ac97))
752 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
753
754 ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
755 if (ret)
756 goto out;
757
758 aaci->playback.pcm = &ac97_bus->pcms[0];
759
760 out:
761 return ret;
762}
763
764static void aaci_free_card(snd_card_t *card)
765{
766 struct aaci *aaci = card->private_data;
767 if (aaci->base)
768 iounmap(aaci->base);
769}
770
771static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
772{
773 struct aaci *aaci;
774 snd_card_t *card;
775
776 card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
777 THIS_MODULE, sizeof(struct aaci));
778 if (card == NULL)
779 return ERR_PTR(-ENOMEM);
780
781 card->private_free = aaci_free_card;
782 snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
783
784 strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
785 strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
786 snprintf(card->longname, sizeof(card->longname),
787 "%s at 0x%08lx, irq %d",
788 card->shortname, dev->res.start, dev->irq[0]);
789
790 aaci = card->private_data;
791 init_MUTEX(&aaci->ac97_sem);
792 spin_lock_init(&aaci->lock);
793 aaci->card = card;
794 aaci->dev = dev;
795
796 /* Set MAINCR to allow slot 1 and 2 data IO */
797 aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
798 MAINCR_SL2RXEN | MAINCR_SL2TXEN;
799
800 return aaci;
801}
802
803static int __devinit aaci_init_pcm(struct aaci *aaci)
804{
805 snd_pcm_t *pcm;
806 int ret;
807
808 ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
809 if (ret == 0) {
810 aaci->pcm = pcm;
811 pcm->private_data = aaci;
812 pcm->info_flags = 0;
813
814 strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
815
816 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
817 }
818
819 return ret;
820}
821
822static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
823{
824 void *base = aaci->base + AACI_CSCH1;
825 int i;
826
827 writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
828
829 for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
830 writel(0, aaci->base + AACI_DR1);
831
832 writel(0, base + AACI_TXCR);
833
834 /*
835 * Re-initialise the AACI after the FIFO depth test, to
836 * ensure that the FIFOs are empty. Unfortunately, merely
837 * disabling the channel doesn't clear the FIFO.
838 */
839 writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
840 writel(aaci->maincr, aaci->base + AACI_MAINCR);
841
842 /*
843 * If we hit 4096, we failed. Go back to the specified
844 * fifo depth.
845 */
846 if (i == 4096)
847 i = 8;
848
849 return i;
850}
851
852static int __devinit aaci_probe(struct amba_device *dev, void *id)
853{
854 struct aaci *aaci;
855 int ret, i;
856
857 ret = amba_request_regions(dev, NULL);
858 if (ret)
859 return ret;
860
861 aaci = aaci_init_card(dev);
862 if (IS_ERR(aaci)) {
863 ret = PTR_ERR(aaci);
864 goto out;
865 }
866
867 aaci->base = ioremap(dev->res.start, SZ_4K);
868 if (!aaci->base) {
869 ret = -ENOMEM;
870 goto out;
871 }
872
873 /*
874 * Playback uses AACI channel 0
875 */
876 aaci->playback.base = aaci->base + AACI_CSCH1;
877 aaci->playback.fifo = aaci->base + AACI_DR1;
878
879 for (i = 0; i < 4; i++) {
880 void *base = aaci->base + i * 0x14;
881
882 writel(0, base + AACI_IE);
883 writel(0, base + AACI_TXCR);
884 writel(0, base + AACI_RXCR);
885 }
886
887 writel(0x1fff, aaci->base + AACI_INTCLR);
888 writel(aaci->maincr, aaci->base + AACI_MAINCR);
889
890 /*
891 * Size the FIFOs.
892 */
893 aaci->fifosize = aaci_size_fifo(aaci);
894
895 ret = aaci_probe_ac97(aaci);
896 if (ret)
897 goto out;
898
899 ret = aaci_init_pcm(aaci);
900 if (ret)
901 goto out;
902
903 ret = snd_card_register(aaci->card);
904 if (ret == 0) {
905 dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
906 aaci->fifosize);
907 amba_set_drvdata(dev, aaci->card);
908 return ret;
909 }
910
911 out:
912 if (aaci)
913 snd_card_free(aaci->card);
914 amba_release_regions(dev);
915 return ret;
916}
917
918static int __devexit aaci_remove(struct amba_device *dev)
919{
920 snd_card_t *card = amba_get_drvdata(dev);
921
922 amba_set_drvdata(dev, NULL);
923
924 if (card) {
925 struct aaci *aaci = card->private_data;
926 writel(0, aaci->base + AACI_MAINCR);
927
928 snd_card_free(card);
929 amba_release_regions(dev);
930 }
931
932 return 0;
933}
934
935static struct amba_id aaci_ids[] = {
936 {
937 .id = 0x00041041,
938 .mask = 0x000fffff,
939 },
940 { 0, 0 },
941};
942
943static struct amba_driver aaci_driver = {
944 .drv = {
945 .name = DRIVER_NAME,
946 },
947 .probe = aaci_probe,
948 .remove = __devexit_p(aaci_remove),
949 .suspend = aaci_suspend,
950 .resume = aaci_resume,
951 .id_table = aaci_ids,
952};
953
954static int __init aaci_init(void)
955{
956 return amba_driver_register(&aaci_driver);
957}
958
959static void __exit aaci_exit(void)
960{
961 amba_driver_unregister(&aaci_driver);
962}
963
964module_init(aaci_init);
965module_exit(aaci_exit);
966
967MODULE_LICENSE("GPL");
968MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");