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