diff options
author | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2008-09-09 21:01:17 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-09-23 02:18:08 -0400 |
commit | 9c63634221f67450ead19820e33996b69691194f (patch) | |
tree | e21917379124783bbf37348c84bf9765cd1dc5d1 /sound/arm/pxa2xx-ac97.c | |
parent | 081b355dd5a17788880a0241ed988c7483c1e40f (diff) |
ALSA: Separate common pxa2xx-ac97 code
ASoC and non-ASoC drivers for ACLINK on PXA share lot's of common code.
Move all common code into separate module snd-pxa2xx-lib.
[Fixed handing of SND_AC97_CODEC in Kconfig and some checkpatch warnings
-- broonie]
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/arm/pxa2xx-ac97.c')
-rw-r--r-- | sound/arm/pxa2xx-ac97.c | 247 |
1 files changed, 18 insertions, 229 deletions
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 199cca3366df..cba71d867542 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -12,198 +12,27 @@ | |||
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/wait.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/delay.h> | ||
21 | 16 | ||
22 | #include <sound/core.h> | 17 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
24 | #include <sound/ac97_codec.h> | 19 | #include <sound/ac97_codec.h> |
25 | #include <sound/initval.h> | 20 | #include <sound/initval.h> |
21 | #include <sound/pxa2xx-lib.h> | ||
26 | 22 | ||
27 | #include <asm/irq.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
30 | #include <mach/pxa-regs.h> | 24 | #include <mach/pxa-regs.h> |
31 | #include <mach/pxa2xx-gpio.h> | ||
32 | #include <mach/audio.h> | 25 | #include <mach/audio.h> |
33 | 26 | ||
34 | #include "pxa2xx-pcm.h" | 27 | #include "pxa2xx-pcm.h" |
35 | 28 | ||
36 | |||
37 | static DEFINE_MUTEX(car_mutex); | ||
38 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | ||
39 | static volatile long gsr_bits; | ||
40 | static struct clk *ac97_clk; | ||
41 | #ifdef CONFIG_PXA27x | ||
42 | static struct clk *ac97conf_clk; | ||
43 | #endif | ||
44 | |||
45 | /* | ||
46 | * Beware PXA27x bugs: | ||
47 | * | ||
48 | * o Slot 12 read from modem space will hang controller. | ||
49 | * o CDONE, SDONE interrupt fails after any slot 12 IO. | ||
50 | * | ||
51 | * We therefore have an hybrid approach for waiting on SDONE (interrupt or | ||
52 | * 1 jiffy timeout if interrupt never comes). | ||
53 | */ | ||
54 | |||
55 | static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | ||
56 | { | ||
57 | unsigned short val = -1; | ||
58 | volatile u32 *reg_addr; | ||
59 | |||
60 | mutex_lock(&car_mutex); | ||
61 | |||
62 | /* set up primary or secondary codec space */ | ||
63 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
64 | reg_addr += (reg >> 1); | ||
65 | |||
66 | /* start read access across the ac97 link */ | ||
67 | GSR = GSR_CDONE | GSR_SDONE; | ||
68 | gsr_bits = 0; | ||
69 | val = *reg_addr; | ||
70 | if (reg == AC97_GPIO_STATUS) | ||
71 | goto out; | ||
72 | if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 && | ||
73 | !((GSR | gsr_bits) & GSR_SDONE)) { | ||
74 | printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", | ||
75 | __func__, reg, GSR | gsr_bits); | ||
76 | val = -1; | ||
77 | goto out; | ||
78 | } | ||
79 | |||
80 | /* valid data now */ | ||
81 | GSR = GSR_CDONE | GSR_SDONE; | ||
82 | gsr_bits = 0; | ||
83 | val = *reg_addr; | ||
84 | /* but we've just started another cycle... */ | ||
85 | wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); | ||
86 | |||
87 | out: mutex_unlock(&car_mutex); | ||
88 | return val; | ||
89 | } | ||
90 | |||
91 | static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) | ||
92 | { | ||
93 | volatile u32 *reg_addr; | ||
94 | |||
95 | mutex_lock(&car_mutex); | ||
96 | |||
97 | /* set up primary or secondary codec space */ | ||
98 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
99 | reg_addr += (reg >> 1); | ||
100 | |||
101 | GSR = GSR_CDONE | GSR_SDONE; | ||
102 | gsr_bits = 0; | ||
103 | *reg_addr = val; | ||
104 | if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 && | ||
105 | !((GSR | gsr_bits) & GSR_CDONE)) | ||
106 | printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", | ||
107 | __func__, reg, GSR | gsr_bits); | ||
108 | |||
109 | mutex_unlock(&car_mutex); | ||
110 | } | ||
111 | |||
112 | static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) | 29 | static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) |
113 | { | 30 | { |
114 | /* First, try cold reset */ | 31 | if (!pxa2xx_ac97_try_cold_reset(ac97)) { |
115 | #ifdef CONFIG_PXA3xx | 32 | pxa2xx_ac97_try_warm_reset(ac97); |
116 | int timeout; | ||
117 | |||
118 | /* Hold CLKBPB for 100us */ | ||
119 | GCR = 0; | ||
120 | GCR = GCR_CLKBPB; | ||
121 | udelay(100); | ||
122 | GCR = 0; | ||
123 | #endif | ||
124 | |||
125 | GCR &= GCR_COLD_RST; /* clear everything but nCRST */ | ||
126 | GCR &= ~GCR_COLD_RST; /* then assert nCRST */ | ||
127 | |||
128 | gsr_bits = 0; | ||
129 | #ifdef CONFIG_PXA27x | ||
130 | /* PXA27x Developers Manual section 13.5.2.2.1 */ | ||
131 | clk_enable(ac97conf_clk); | ||
132 | udelay(5); | ||
133 | clk_disable(ac97conf_clk); | ||
134 | GCR = GCR_COLD_RST; | ||
135 | udelay(50); | ||
136 | #elif defined(CONFIG_PXA3xx) | ||
137 | timeout = 1000; | ||
138 | /* Can't use interrupts on PXA3xx */ | ||
139 | GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); | ||
140 | |||
141 | GCR = GCR_WARM_RST | GCR_COLD_RST; | ||
142 | while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--) | ||
143 | mdelay(10); | ||
144 | #else | ||
145 | GCR = GCR_COLD_RST; | ||
146 | GCR |= GCR_CDONE_IE|GCR_SDONE_IE; | ||
147 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
148 | #endif | ||
149 | |||
150 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { | ||
151 | printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", | ||
152 | __func__, gsr_bits); | ||
153 | |||
154 | /* let's try warm reset */ | ||
155 | gsr_bits = 0; | ||
156 | #ifdef CONFIG_PXA27x | ||
157 | /* warm reset broken on Bulverde, | ||
158 | so manually keep AC97 reset high */ | ||
159 | pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); | ||
160 | udelay(10); | ||
161 | GCR |= GCR_WARM_RST; | ||
162 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
163 | udelay(500); | ||
164 | #elif defined(CONFIG_PXA3xx) | ||
165 | timeout = 100; | ||
166 | /* Can't use interrupts */ | ||
167 | GCR |= GCR_WARM_RST; | ||
168 | while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) | ||
169 | mdelay(1); | ||
170 | #else | ||
171 | GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN; | ||
172 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
173 | #endif | ||
174 | |||
175 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) | ||
176 | printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", | ||
177 | __func__, gsr_bits); | ||
178 | } | ||
179 | |||
180 | GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); | ||
181 | GCR |= GCR_SDONE_IE|GCR_CDONE_IE; | ||
182 | } | ||
183 | |||
184 | static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) | ||
185 | { | ||
186 | long status; | ||
187 | |||
188 | status = GSR; | ||
189 | if (status) { | ||
190 | GSR = status; | ||
191 | gsr_bits |= status; | ||
192 | wake_up(&gsr_wq); | ||
193 | |||
194 | #ifdef CONFIG_PXA27x | ||
195 | /* Although we don't use those we still need to clear them | ||
196 | since they tend to spuriously trigger when MMC is used | ||
197 | (hardware bug? go figure)... */ | ||
198 | MISR = MISR_EOC; | ||
199 | PISR = PISR_EOC; | ||
200 | MCSR = MCSR_EOC; | ||
201 | #endif | ||
202 | |||
203 | return IRQ_HANDLED; | ||
204 | } | 33 | } |
205 | 34 | ||
206 | return IRQ_NONE; | 35 | pxa2xx_ac97_finish_reset(ac97); |
207 | } | 36 | } |
208 | 37 | ||
209 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { | 38 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { |
@@ -288,17 +117,19 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) | |||
288 | snd_ac97_suspend(pxa2xx_ac97_ac97); | 117 | snd_ac97_suspend(pxa2xx_ac97_ac97); |
289 | if (platform_ops && platform_ops->suspend) | 118 | if (platform_ops && platform_ops->suspend) |
290 | platform_ops->suspend(platform_ops->priv); | 119 | platform_ops->suspend(platform_ops->priv); |
291 | GCR |= GCR_ACLINK_OFF; | ||
292 | clk_disable(ac97_clk); | ||
293 | 120 | ||
294 | return 0; | 121 | return pxa2xx_ac97_hw_suspend(); |
295 | } | 122 | } |
296 | 123 | ||
297 | static int pxa2xx_ac97_do_resume(struct snd_card *card) | 124 | static int pxa2xx_ac97_do_resume(struct snd_card *card) |
298 | { | 125 | { |
299 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | 126 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; |
127 | int rc; | ||
128 | |||
129 | rc = pxa2xx_ac97_hw_resume(); | ||
130 | if (rc) | ||
131 | return rc; | ||
300 | 132 | ||
301 | clk_enable(ac97_clk); | ||
302 | if (platform_ops && platform_ops->resume) | 133 | if (platform_ops && platform_ops->resume) |
303 | platform_ops->resume(platform_ops->priv); | 134 | platform_ops->resume(platform_ops->priv); |
304 | snd_ac97_resume(pxa2xx_ac97_ac97); | 135 | snd_ac97_resume(pxa2xx_ac97_ac97); |
@@ -354,40 +185,17 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | |||
354 | if (ret) | 185 | if (ret) |
355 | goto err; | 186 | goto err; |
356 | 187 | ||
357 | ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); | 188 | ret = pxa2xx_ac97_hw_probe(dev); |
358 | if (ret < 0) | 189 | if (ret) |
359 | goto err; | ||
360 | |||
361 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); | ||
362 | pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); | ||
363 | pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); | ||
364 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); | ||
365 | #ifdef CONFIG_PXA27x | ||
366 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | ||
367 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
368 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); | ||
369 | if (IS_ERR(ac97conf_clk)) { | ||
370 | ret = PTR_ERR(ac97conf_clk); | ||
371 | ac97conf_clk = NULL; | ||
372 | goto err; | ||
373 | } | ||
374 | #endif | ||
375 | |||
376 | ac97_clk = clk_get(&dev->dev, "AC97CLK"); | ||
377 | if (IS_ERR(ac97_clk)) { | ||
378 | ret = PTR_ERR(ac97_clk); | ||
379 | ac97_clk = NULL; | ||
380 | goto err; | 190 | goto err; |
381 | } | ||
382 | clk_enable(ac97_clk); | ||
383 | 191 | ||
384 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); | 192 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); |
385 | if (ret) | 193 | if (ret) |
386 | goto err; | 194 | goto err_remove; |
387 | memset(&ac97_template, 0, sizeof(ac97_template)); | 195 | memset(&ac97_template, 0, sizeof(ac97_template)); |
388 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); | 196 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); |
389 | if (ret) | 197 | if (ret) |
390 | goto err; | 198 | goto err_remove; |
391 | 199 | ||
392 | snprintf(card->shortname, sizeof(card->shortname), | 200 | snprintf(card->shortname, sizeof(card->shortname), |
393 | "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); | 201 | "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); |
@@ -401,22 +209,11 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | |||
401 | return 0; | 209 | return 0; |
402 | } | 210 | } |
403 | 211 | ||
404 | err: | 212 | err_remove: |
213 | pxa2xx_ac97_hw_remove(dev); | ||
214 | err: | ||
405 | if (card) | 215 | if (card) |
406 | snd_card_free(card); | 216 | snd_card_free(card); |
407 | if (ac97_clk) { | ||
408 | GCR |= GCR_ACLINK_OFF; | ||
409 | free_irq(IRQ_AC97, NULL); | ||
410 | clk_disable(ac97_clk); | ||
411 | clk_put(ac97_clk); | ||
412 | ac97_clk = NULL; | ||
413 | } | ||
414 | #ifdef CONFIG_PXA27x | ||
415 | if (ac97conf_clk) { | ||
416 | clk_put(ac97conf_clk); | ||
417 | ac97conf_clk = NULL; | ||
418 | } | ||
419 | #endif | ||
420 | return ret; | 217 | return ret; |
421 | } | 218 | } |
422 | 219 | ||
@@ -427,15 +224,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) | |||
427 | if (card) { | 224 | if (card) { |
428 | snd_card_free(card); | 225 | snd_card_free(card); |
429 | platform_set_drvdata(dev, NULL); | 226 | platform_set_drvdata(dev, NULL); |
430 | GCR |= GCR_ACLINK_OFF; | 227 | pxa2xx_ac97_hw_remove(dev); |
431 | free_irq(IRQ_AC97, NULL); | ||
432 | clk_disable(ac97_clk); | ||
433 | clk_put(ac97_clk); | ||
434 | ac97_clk = NULL; | ||
435 | #ifdef CONFIG_PXA27x | ||
436 | clk_put(ac97conf_clk); | ||
437 | ac97conf_clk = NULL; | ||
438 | #endif | ||
439 | } | 228 | } |
440 | 229 | ||
441 | return 0; | 230 | return 0; |