diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
commit | ed40d0c472b136682b2fcba05f89762859c7374f (patch) | |
tree | 076b83a26bcd63d6158463735dd34c10bbc591dc /sound/arm/pxa2xx-ac97-lib.c | |
parent | 9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff) | |
parent | 5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff) |
Merge branch 'origin' into devel
Conflicts:
sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'sound/arm/pxa2xx-ac97-lib.c')
-rw-r--r-- | sound/arm/pxa2xx-ac97-lib.c | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 718d06640dd4..7793d2a511ce 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c | |||
@@ -30,6 +30,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | |||
30 | static volatile long gsr_bits; | 30 | static volatile long gsr_bits; |
31 | static struct clk *ac97_clk; | 31 | static struct clk *ac97_clk; |
32 | static struct clk *ac97conf_clk; | 32 | static struct clk *ac97conf_clk; |
33 | static int reset_gpio; | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * Beware PXA27x bugs: | 36 | * Beware PXA27x bugs: |
@@ -41,6 +42,45 @@ static struct clk *ac97conf_clk; | |||
41 | * 1 jiffy timeout if interrupt never comes). | 42 | * 1 jiffy timeout if interrupt never comes). |
42 | */ | 43 | */ |
43 | 44 | ||
45 | enum { | ||
46 | RESETGPIO_FORCE_HIGH, | ||
47 | RESETGPIO_FORCE_LOW, | ||
48 | RESETGPIO_NORMAL_ALTFUNC | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA | ||
53 | * @mode: chosen action | ||
54 | * | ||
55 | * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line | ||
56 | * must be done to insure proper work of AC97 reset line. This function | ||
57 | * computes the correct gpio_mode for further use by reset functions, and | ||
58 | * applied the change through pxa_gpio_mode. | ||
59 | */ | ||
60 | static void set_resetgpio_mode(int resetgpio_action) | ||
61 | { | ||
62 | int mode = 0; | ||
63 | |||
64 | if (reset_gpio) | ||
65 | switch (resetgpio_action) { | ||
66 | case RESETGPIO_NORMAL_ALTFUNC: | ||
67 | if (reset_gpio == 113) | ||
68 | mode = 113 | GPIO_OUT | GPIO_DFLT_LOW; | ||
69 | if (reset_gpio == 95) | ||
70 | mode = 95 | GPIO_ALT_FN_1_OUT; | ||
71 | break; | ||
72 | case RESETGPIO_FORCE_LOW: | ||
73 | mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW; | ||
74 | break; | ||
75 | case RESETGPIO_FORCE_HIGH: | ||
76 | mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH; | ||
77 | break; | ||
78 | }; | ||
79 | |||
80 | if (mode) | ||
81 | pxa_gpio_mode(mode); | ||
82 | } | ||
83 | |||
44 | unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 84 | unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
45 | { | 85 | { |
46 | unsigned short val = -1; | 86 | unsigned short val = -1; |
@@ -136,10 +176,10 @@ static inline void pxa_ac97_warm_pxa27x(void) | |||
136 | 176 | ||
137 | /* warm reset broken on Bulverde, | 177 | /* warm reset broken on Bulverde, |
138 | so manually keep AC97 reset high */ | 178 | so manually keep AC97 reset high */ |
139 | pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); | 179 | set_resetgpio_mode(RESETGPIO_FORCE_HIGH); |
140 | udelay(10); | 180 | udelay(10); |
141 | GCR |= GCR_WARM_RST; | 181 | GCR |= GCR_WARM_RST; |
142 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 182 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
143 | udelay(500); | 183 | udelay(500); |
144 | } | 184 | } |
145 | 185 | ||
@@ -307,8 +347,8 @@ int pxa2xx_ac97_hw_resume(void) | |||
307 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); | 347 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); |
308 | } | 348 | } |
309 | if (cpu_is_pxa27x()) { | 349 | if (cpu_is_pxa27x()) { |
310 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 350 | /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */ |
311 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 351 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
312 | } | 352 | } |
313 | clk_enable(ac97_clk); | 353 | clk_enable(ac97_clk); |
314 | return 0; | 354 | return 0; |
@@ -319,6 +359,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); | |||
319 | int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) | 359 | int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) |
320 | { | 360 | { |
321 | int ret; | 361 | int ret; |
362 | struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data; | ||
363 | |||
364 | if (pdata) { | ||
365 | switch (pdata->reset_gpio) { | ||
366 | case 95: | ||
367 | case 113: | ||
368 | reset_gpio = pdata->reset_gpio; | ||
369 | break; | ||
370 | case 0: | ||
371 | reset_gpio = 113; | ||
372 | break; | ||
373 | case -1: | ||
374 | break; | ||
375 | default: | ||
376 | dev_err(&dev->dev, "Invalid reset GPIO %d\n", | ||
377 | pdata->reset_gpio); | ||
378 | } | ||
379 | } else { | ||
380 | if (cpu_is_pxa27x()) | ||
381 | reset_gpio = 113; | ||
382 | } | ||
322 | 383 | ||
323 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) { | 384 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) { |
324 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); | 385 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); |
@@ -329,7 +390,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) | |||
329 | 390 | ||
330 | if (cpu_is_pxa27x()) { | 391 | if (cpu_is_pxa27x()) { |
331 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 392 | /* Use GPIO 113 as AC97 Reset on Bulverde */ |
332 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 393 | set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); |
333 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); | 394 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); |
334 | if (IS_ERR(ac97conf_clk)) { | 395 | if (IS_ERR(ac97conf_clk)) { |
335 | ret = PTR_ERR(ac97conf_clk); | 396 | ret = PTR_ERR(ac97conf_clk); |