aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
commit651dab4264e4ba0e563f5ff56f748127246e9065 (patch)
tree016630974bdcb00fe529b673f96d389e0fd6dc94 /sound/soc/pxa
parent40b8606253552109815786e5d4b0de98782d31f5 (diff)
parent2e532d68a2b3e2aa6b19731501222069735c741c (diff)
Merge commit 'linus/master' into merge-linus
Conflicts: arch/x86/kvm/i8254.c
Diffstat (limited to 'sound/soc/pxa')
-rw-r--r--sound/soc/pxa/Kconfig3
-rw-r--r--sound/soc/pxa/corgi.c41
-rw-r--r--sound/soc/pxa/em-x270.c2
-rw-r--r--sound/soc/pxa/poodle.c7
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c282
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c67
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c265
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.h15
-rw-r--r--sound/soc/pxa/spitz.c63
-rw-r--r--sound/soc/pxa/tosa.c6
10 files changed, 136 insertions, 615 deletions
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 9212c37a33b8..f8c1cdd940ac 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -1,6 +1,7 @@
1config SND_PXA2XX_SOC 1config SND_PXA2XX_SOC
2 tristate "SoC Audio for the Intel PXA2xx chip" 2 tristate "SoC Audio for the Intel PXA2xx chip"
3 depends on ARCH_PXA 3 depends on ARCH_PXA
4 select SND_PXA2XX_LIB
4 help 5 help
5 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
6 the PXA2xx AC97, I2S or SSP interface. You will also need 7 the PXA2xx AC97, I2S or SSP interface. You will also need
@@ -13,6 +14,8 @@ config SND_PXA2XX_AC97
13config SND_PXA2XX_SOC_AC97 14config SND_PXA2XX_SOC_AC97
14 tristate 15 tristate
15 select AC97_BUS 16 select AC97_BUS
17 select SND_ARM
18 select SND_PXA2XX_LIB_AC97
16 select SND_SOC_AC97_BUS 19 select SND_SOC_AC97_BUS
17 20
18config SND_PXA2XX_SOC_I2S 21config SND_PXA2XX_SOC_I2S
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 0a53f72077fd..2718eaf7895f 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -18,13 +18,13 @@
18#include <linux/timer.h> 18#include <linux/timer.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/gpio.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23#include <sound/soc.h> 24#include <sound/soc.h>
24#include <sound/soc-dapm.h> 25#include <sound/soc-dapm.h>
25 26
26#include <asm/mach-types.h> 27#include <asm/mach-types.h>
27#include <asm/hardware/scoop.h>
28#include <mach/pxa-regs.h> 28#include <mach/pxa-regs.h>
29#include <mach/hardware.h> 29#include <mach/hardware.h>
30#include <mach/corgi.h> 30#include <mach/corgi.h>
@@ -54,8 +54,8 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
54 switch (corgi_jack_func) { 54 switch (corgi_jack_func) {
55 case CORGI_HP: 55 case CORGI_HP:
56 /* set = unmute headphone */ 56 /* set = unmute headphone */
57 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 57 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
58 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 58 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
59 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 59 snd_soc_dapm_disable_pin(codec, "Mic Jack");
60 snd_soc_dapm_disable_pin(codec, "Line Jack"); 60 snd_soc_dapm_disable_pin(codec, "Line Jack");
61 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 61 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
@@ -63,24 +63,24 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
63 break; 63 break;
64 case CORGI_MIC: 64 case CORGI_MIC:
65 /* reset = mute headphone */ 65 /* reset = mute headphone */
66 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 66 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
67 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 67 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
68 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 68 snd_soc_dapm_enable_pin(codec, "Mic Jack");
69 snd_soc_dapm_disable_pin(codec, "Line Jack"); 69 snd_soc_dapm_disable_pin(codec, "Line Jack");
70 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 70 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
71 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 71 snd_soc_dapm_disable_pin(codec, "Headset Jack");
72 break; 72 break;
73 case CORGI_LINE: 73 case CORGI_LINE:
74 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 74 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
75 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 75 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
76 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 76 snd_soc_dapm_disable_pin(codec, "Mic Jack");
77 snd_soc_dapm_enable_pin(codec, "Line Jack"); 77 snd_soc_dapm_enable_pin(codec, "Line Jack");
78 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 78 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
79 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 79 snd_soc_dapm_disable_pin(codec, "Headset Jack");
80 break; 80 break;
81 case CORGI_HEADSET: 81 case CORGI_HEADSET:
82 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 82 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
83 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 83 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
84 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 84 snd_soc_dapm_enable_pin(codec, "Mic Jack");
85 snd_soc_dapm_disable_pin(codec, "Line Jack"); 85 snd_soc_dapm_disable_pin(codec, "Line Jack");
86 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 86 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
@@ -114,8 +114,8 @@ static int corgi_shutdown(struct snd_pcm_substream *substream)
114 struct snd_soc_codec *codec = rtd->socdev->codec; 114 struct snd_soc_codec *codec = rtd->socdev->codec;
115 115
116 /* set = unmute headphone */ 116 /* set = unmute headphone */
117 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 117 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
118 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 118 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
119 return 0; 119 return 0;
120} 120}
121 121
@@ -218,22 +218,14 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol,
218static int corgi_amp_event(struct snd_soc_dapm_widget *w, 218static int corgi_amp_event(struct snd_soc_dapm_widget *w,
219 struct snd_kcontrol *k, int event) 219 struct snd_kcontrol *k, int event)
220{ 220{
221 if (SND_SOC_DAPM_EVENT_ON(event)) 221 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
222 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
223 else
224 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
225
226 return 0; 222 return 0;
227} 223}
228 224
229static int corgi_mic_event(struct snd_soc_dapm_widget *w, 225static int corgi_mic_event(struct snd_soc_dapm_widget *w,
230 struct snd_kcontrol *k, int event) 226 struct snd_kcontrol *k, int event)
231{ 227{
232 if (SND_SOC_DAPM_EVENT_ON(event)) 228 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
233 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
234 else
235 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
236
237 return 0; 229 return 0;
238} 230}
239 231
@@ -289,8 +281,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
289{ 281{
290 int i, err; 282 int i, err;
291 283
292 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 284 snd_soc_dapm_nc_pin(codec, "LLINEIN");
293 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 285 snd_soc_dapm_nc_pin(codec, "RLINEIN");
294 286
295 /* Add corgi specific controls */ 287 /* Add corgi specific controls */
296 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { 288 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
@@ -330,6 +322,7 @@ static struct snd_soc_machine snd_soc_machine_corgi = {
330 322
331/* corgi audio private data */ 323/* corgi audio private data */
332static struct wm8731_setup_data corgi_wm8731_setup = { 324static struct wm8731_setup_data corgi_wm8731_setup = {
325 .i2c_bus = 0,
333 .i2c_address = 0x1b, 326 .i2c_address = 0x1b,
334}; 327};
335 328
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index d9c3f7b28be2..e6ff6929ab4b 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -9,7 +9,7 @@
9 * Copyright 2005 Wolfson Microelectronics PLC. 9 * Copyright 2005 Wolfson Microelectronics PLC.
10 * Copyright 2005 Openedhand Ltd. 10 * Copyright 2005 Openedhand Ltd.
11 * 11 *
12 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 12 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
13 * Richard Purdie <richard@openedhand.com> 13 * Richard Purdie <richard@openedhand.com>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify it 15 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index a4697f7e2921..4d9930c52789 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
242{ 242{
243 int i, err; 243 int i, err;
244 244
245 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 245 snd_soc_dapm_nc_pin(codec, "LLINEIN");
246 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 246 snd_soc_dapm_nc_pin(codec, "RLINEIN");
247 snd_soc_dapm_enable_pin(codec, "MICIN"); 247 snd_soc_dapm_enable_pin(codec, "MICIN");
248 248
249 /* Add poodle specific controls */ 249 /* Add poodle specific controls */
@@ -284,6 +284,7 @@ static struct snd_soc_machine snd_soc_machine_poodle = {
284 284
285/* poodle audio private data */ 285/* poodle audio private data */
286static struct wm8731_setup_data poodle_wm8731_setup = { 286static struct wm8731_setup_data poodle_wm8731_setup = {
287 .i2c_bus = 0,
287 .i2c_address = 0x1b, 288 .i2c_address = 0x1b,
288}; 289};
289 290
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index d94a495bd6bd..a7a3a9c5c6ff 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -13,225 +13,30 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/interrupt.h>
17#include <linux/wait.h>
18#include <linux/clk.h>
19#include <linux/delay.h>
20 16
21#include <sound/core.h> 17#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/ac97_codec.h> 18#include <sound/ac97_codec.h>
24#include <sound/initval.h>
25#include <sound/soc.h> 19#include <sound/soc.h>
20#include <sound/pxa2xx-lib.h>
26 21
27#include <asm/irq.h>
28#include <linux/mutex.h>
29#include <mach/hardware.h> 22#include <mach/hardware.h>
30#include <mach/pxa-regs.h> 23#include <mach/pxa-regs.h>
31#include <mach/pxa2xx-gpio.h>
32#include <mach/audio.h>
33 24
34#include "pxa2xx-pcm.h" 25#include "pxa2xx-pcm.h"
35#include "pxa2xx-ac97.h" 26#include "pxa2xx-ac97.h"
36 27
37static DEFINE_MUTEX(car_mutex);
38static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
39static volatile long gsr_bits;
40static struct clk *ac97_clk;
41#ifdef CONFIG_PXA27x
42static 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
55static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
56 unsigned short reg)
57{
58 unsigned short val = -1;
59 volatile u32 *reg_addr;
60
61 mutex_lock(&car_mutex);
62
63 /* set up primary or secondary codec/modem space */
64#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
65 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
66#else
67 if (reg == AC97_GPIO_STATUS)
68 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
69 else
70 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
71#endif
72 reg_addr += (reg >> 1);
73
74#ifndef CONFIG_PXA27x
75 if (reg == AC97_GPIO_STATUS) {
76 /* read from controller cache */
77 val = *reg_addr;
78 goto out;
79 }
80#endif
81
82 /* start read access across the ac97 link */
83 GSR = GSR_CDONE | GSR_SDONE;
84 gsr_bits = 0;
85 val = *reg_addr;
86
87 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
88 if (!((GSR | gsr_bits) & GSR_SDONE)) {
89 printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
90 __func__, reg, GSR | gsr_bits);
91 val = -1;
92 goto out;
93 }
94
95 /* valid data now */
96 GSR = GSR_CDONE | GSR_SDONE;
97 gsr_bits = 0;
98 val = *reg_addr;
99 /* but we've just started another cycle... */
100 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
101
102out: mutex_unlock(&car_mutex);
103 return val;
104}
105
106static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
107 unsigned short val)
108{
109 volatile u32 *reg_addr;
110
111 mutex_lock(&car_mutex);
112
113 /* set up primary or secondary codec/modem space */
114#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
115 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
116#else
117 if (reg == AC97_GPIO_STATUS)
118 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
119 else
120 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
121#endif
122 reg_addr += (reg >> 1);
123
124 GSR = GSR_CDONE | GSR_SDONE;
125 gsr_bits = 0;
126 *reg_addr = val;
127 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
128 if (!((GSR | gsr_bits) & GSR_CDONE))
129 printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
130 __func__, reg, GSR | gsr_bits);
131
132 mutex_unlock(&car_mutex);
133}
134
135static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) 28static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
136{ 29{
137#ifdef CONFIG_PXA3xx 30 pxa2xx_ac97_try_warm_reset(ac97);
138 int timeout = 100;
139#endif
140 gsr_bits = 0;
141
142#ifdef CONFIG_PXA27x
143 /* warm reset broken on Bulverde,
144 so manually keep AC97 reset high */
145 pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
146 udelay(10);
147 GCR |= GCR_WARM_RST;
148 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
149 udelay(500);
150#elif defined(CONFIG_PXA3xx)
151 /* Can't use interrupts */
152 GCR |= GCR_WARM_RST;
153 while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
154 mdelay(1);
155#else
156 GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
157 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
158#endif
159
160 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
161 printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
162 __func__, gsr_bits);
163 31
164 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); 32 pxa2xx_ac97_finish_reset(ac97);
165 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
166} 33}
167 34
168static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) 35static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
169{ 36{
170#ifdef CONFIG_PXA3xx 37 pxa2xx_ac97_try_cold_reset(ac97);
171 int timeout = 1000;
172
173 /* Hold CLKBPB for 100us */
174 GCR = 0;
175 GCR = GCR_CLKBPB;
176 udelay(100);
177 GCR = 0;
178#endif
179 38
180 GCR &= GCR_COLD_RST; /* clear everything but nCRST */ 39 pxa2xx_ac97_finish_reset(ac97);
181 GCR &= ~GCR_COLD_RST; /* then assert nCRST */
182
183 gsr_bits = 0;
184#ifdef CONFIG_PXA27x
185 /* PXA27x Developers Manual section 13.5.2.2.1 */
186 clk_enable(ac97conf_clk);
187 udelay(5);
188 clk_disable(ac97conf_clk);
189 GCR = GCR_COLD_RST;
190 udelay(50);
191#elif defined(CONFIG_PXA3xx)
192 /* Can't use interrupts on PXA3xx */
193 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
194
195 GCR = GCR_WARM_RST | GCR_COLD_RST;
196 while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
197 mdelay(10);
198#else
199 GCR = GCR_COLD_RST;
200 GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
201 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
202#endif
203
204 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
205 printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
206 __func__, gsr_bits);
207
208 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
209 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
210}
211
212static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
213{
214 long status;
215
216 status = GSR;
217 if (status) {
218 GSR = status;
219 gsr_bits |= status;
220 wake_up(&gsr_wq);
221
222#ifdef CONFIG_PXA27x
223 /* Although we don't use those we still need to clear them
224 since they tend to spuriously trigger when MMC is used
225 (hardware bug? go figure)... */
226 MISR = MISR_EOC;
227 PISR = PISR_EOC;
228 MCSR = MCSR_EOC;
229#endif
230
231 return IRQ_HANDLED;
232 }
233
234 return IRQ_NONE;
235} 40}
236 41
237struct snd_ac97_bus_ops soc_ac97_ops = { 42struct snd_ac97_bus_ops soc_ac97_ops = {
@@ -244,7 +49,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
244static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { 49static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
245 .name = "AC97 PCM Stereo out", 50 .name = "AC97 PCM Stereo out",
246 .dev_addr = __PREG(PCDR), 51 .dev_addr = __PREG(PCDR),
247 .drcmr = &DRCMRTXPCDR, 52 .drcmr = &DRCMR(12),
248 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 53 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
249 DCMD_BURST32 | DCMD_WIDTH4, 54 DCMD_BURST32 | DCMD_WIDTH4,
250}; 55};
@@ -252,7 +57,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
252static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { 57static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
253 .name = "AC97 PCM Stereo in", 58 .name = "AC97 PCM Stereo in",
254 .dev_addr = __PREG(PCDR), 59 .dev_addr = __PREG(PCDR),
255 .drcmr = &DRCMRRXPCDR, 60 .drcmr = &DRCMR(11),
256 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 61 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
257 DCMD_BURST32 | DCMD_WIDTH4, 62 DCMD_BURST32 | DCMD_WIDTH4,
258}; 63};
@@ -260,7 +65,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
260static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { 65static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
261 .name = "AC97 Aux PCM (Slot 5) Mono out", 66 .name = "AC97 Aux PCM (Slot 5) Mono out",
262 .dev_addr = __PREG(MODR), 67 .dev_addr = __PREG(MODR),
263 .drcmr = &DRCMRTXMODR, 68 .drcmr = &DRCMR(10),
264 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 69 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
265 DCMD_BURST16 | DCMD_WIDTH2, 70 DCMD_BURST16 | DCMD_WIDTH2,
266}; 71};
@@ -268,7 +73,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
268static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { 73static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
269 .name = "AC97 Aux PCM (Slot 5) Mono in", 74 .name = "AC97 Aux PCM (Slot 5) Mono in",
270 .dev_addr = __PREG(MODR), 75 .dev_addr = __PREG(MODR),
271 .drcmr = &DRCMRRXMODR, 76 .drcmr = &DRCMR(9),
272 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 77 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
273 DCMD_BURST16 | DCMD_WIDTH2, 78 DCMD_BURST16 | DCMD_WIDTH2,
274}; 79};
@@ -276,7 +81,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
276static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { 81static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
277 .name = "AC97 Mic PCM (Slot 6) Mono in", 82 .name = "AC97 Mic PCM (Slot 6) Mono in",
278 .dev_addr = __PREG(MCDR), 83 .dev_addr = __PREG(MCDR),
279 .drcmr = &DRCMRRXMCDR, 84 .drcmr = &DRCMR(8),
280 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 85 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
281 DCMD_BURST16 | DCMD_WIDTH2, 86 DCMD_BURST16 | DCMD_WIDTH2,
282}; 87};
@@ -285,24 +90,13 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
285static int pxa2xx_ac97_suspend(struct platform_device *pdev, 90static int pxa2xx_ac97_suspend(struct platform_device *pdev,
286 struct snd_soc_dai *dai) 91 struct snd_soc_dai *dai)
287{ 92{
288 GCR |= GCR_ACLINK_OFF; 93 return pxa2xx_ac97_hw_suspend();
289 clk_disable(ac97_clk);
290 return 0;
291} 94}
292 95
293static int pxa2xx_ac97_resume(struct platform_device *pdev, 96static int pxa2xx_ac97_resume(struct platform_device *pdev,
294 struct snd_soc_dai *dai) 97 struct snd_soc_dai *dai)
295{ 98{
296 pxa_gpio_mode(GPIO31_SYNC_AC97_MD); 99 return pxa2xx_ac97_hw_resume();
297 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
298 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
299 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
300#ifdef CONFIG_PXA27x
301 /* Use GPIO 113 as AC97 Reset on Bulverde */
302 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
303#endif
304 clk_enable(ac97_clk);
305 return 0;
306} 100}
307 101
308#else 102#else
@@ -313,61 +107,13 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
313static int pxa2xx_ac97_probe(struct platform_device *pdev, 107static int pxa2xx_ac97_probe(struct platform_device *pdev,
314 struct snd_soc_dai *dai) 108 struct snd_soc_dai *dai)
315{ 109{
316 int ret; 110 return pxa2xx_ac97_hw_probe(pdev);
317
318 ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
319 if (ret < 0)
320 goto err;
321
322 pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
323 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
324 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
325 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
326#ifdef CONFIG_PXA27x
327 /* Use GPIO 113 as AC97 Reset on Bulverde */
328 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
329
330 ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
331 if (IS_ERR(ac97conf_clk)) {
332 ret = PTR_ERR(ac97conf_clk);
333 ac97conf_clk = NULL;
334 goto err_irq;
335 }
336#endif
337 ac97_clk = clk_get(&pdev->dev, "AC97CLK");
338 if (IS_ERR(ac97_clk)) {
339 ret = PTR_ERR(ac97_clk);
340 ac97_clk = NULL;
341 goto err_irq;
342 }
343 clk_enable(ac97_clk);
344 return 0;
345
346 err_irq:
347 GCR |= GCR_ACLINK_OFF;
348#ifdef CONFIG_PXA27x
349 if (ac97conf_clk) {
350 clk_put(ac97conf_clk);
351 ac97conf_clk = NULL;
352 }
353#endif
354 free_irq(IRQ_AC97, NULL);
355 err:
356 return ret;
357} 111}
358 112
359static void pxa2xx_ac97_remove(struct platform_device *pdev, 113static void pxa2xx_ac97_remove(struct platform_device *pdev,
360 struct snd_soc_dai *dai) 114 struct snd_soc_dai *dai)
361{ 115{
362 GCR |= GCR_ACLINK_OFF; 116 pxa2xx_ac97_hw_remove(pdev);
363 free_irq(IRQ_AC97, NULL);
364#ifdef CONFIG_PXA27x
365 clk_put(ac97conf_clk);
366 ac97conf_clk = NULL;
367#endif
368 clk_disable(ac97_clk);
369 clk_put(ac97_clk);
370 ac97_clk = NULL;
371} 117}
372 118
373static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 119static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index c796b1882776..e758034db5c3 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com 6 * lrg@slimlogic.co.uk
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -21,6 +21,7 @@
21#include <sound/pcm.h> 21#include <sound/pcm.h>
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/pxa2xx-lib.h>
24 25
25#include <mach/hardware.h> 26#include <mach/hardware.h>
26#include <mach/pxa-regs.h> 27#include <mach/pxa-regs.h>
@@ -30,6 +31,54 @@
30#include "pxa2xx-pcm.h" 31#include "pxa2xx-pcm.h"
31#include "pxa2xx-i2s.h" 32#include "pxa2xx-i2s.h"
32 33
34struct pxa2xx_gpio {
35 u32 sys;
36 u32 rx;
37 u32 tx;
38 u32 clk;
39 u32 frm;
40};
41
42/*
43 * I2S Controller Register and Bit Definitions
44 */
45#define SACR0 __REG(0x40400000) /* Global Control Register */
46#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
47#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
48#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */
49#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */
50#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
51#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
52
53#define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */
54#define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */
55#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */
56#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */
57#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */
58#define SACR0_BCKD (1 << 2) /* Bit Clock Direction */
59#define SACR0_ENB (1 << 0) /* Enable I2S Link */
60#define SACR1_ENLBF (1 << 5) /* Enable Loopback */
61#define SACR1_DRPL (1 << 4) /* Disable Replaying Function */
62#define SACR1_DREC (1 << 3) /* Disable Recording Function */
63#define SACR1_AMSL (1 << 0) /* Specify Alternate Mode */
64
65#define SASR0_I2SOFF (1 << 7) /* Controller Status */
66#define SASR0_ROR (1 << 6) /* Rx FIFO Overrun */
67#define SASR0_TUR (1 << 5) /* Tx FIFO Underrun */
68#define SASR0_RFS (1 << 4) /* Rx FIFO Service Request */
69#define SASR0_TFS (1 << 3) /* Tx FIFO Service Request */
70#define SASR0_BSY (1 << 2) /* I2S Busy */
71#define SASR0_RNE (1 << 1) /* Rx FIFO Not Empty */
72#define SASR0_TNF (1 << 0) /* Tx FIFO Not Empty */
73
74#define SAICR_ROR (1 << 6) /* Clear Rx FIFO Overrun Interrupt */
75#define SAICR_TUR (1 << 5) /* Clear Tx FIFO Underrun Interrupt */
76
77#define SAIMR_ROR (1 << 6) /* Enable Rx FIFO Overrun Condition Interrupt */
78#define SAIMR_TUR (1 << 5) /* Enable Tx FIFO Underrun Condition Interrupt */
79#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */
80#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */
81
33struct pxa_i2s_port { 82struct pxa_i2s_port {
34 u32 sadiv; 83 u32 sadiv;
35 u32 sacr0; 84 u32 sacr0;
@@ -44,7 +93,7 @@ static struct clk *clk_i2s;
44static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { 93static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
45 .name = "I2S PCM Stereo out", 94 .name = "I2S PCM Stereo out",
46 .dev_addr = __PREG(SADR), 95 .dev_addr = __PREG(SADR),
47 .drcmr = &DRCMRTXSADR, 96 .drcmr = &DRCMR(3),
48 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 97 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
49 DCMD_BURST32 | DCMD_WIDTH4, 98 DCMD_BURST32 | DCMD_WIDTH4,
50}; 99};
@@ -52,7 +101,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
52static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { 101static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
53 .name = "I2S PCM Stereo in", 102 .name = "I2S PCM Stereo in",
54 .dev_addr = __PREG(SADR), 103 .dev_addr = __PREG(SADR),
55 .drcmr = &DRCMRRXSADR, 104 .drcmr = &DRCMR(2),
56 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 105 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
57 DCMD_BURST32 | DCMD_WIDTH4, 106 DCMD_BURST32 | DCMD_WIDTH4,
58}; 107};
@@ -65,11 +114,6 @@ static struct pxa2xx_gpio gpio_bus[] = {
65 .frm = GPIO31_SYNC_I2S_MD, 114 .frm = GPIO31_SYNC_I2S_MD,
66 }, 115 },
67 { /* I2S SoC Master */ 116 { /* I2S SoC Master */
68#ifdef CONFIG_PXA27x
69 .sys = GPIO113_I2S_SYSCLK_MD,
70#else
71 .sys = GPIO32_SYSCLK_I2S_MD,
72#endif
73 .rx = GPIO29_SDATA_IN_I2S_MD, 117 .rx = GPIO29_SDATA_IN_I2S_MD,
74 .tx = GPIO30_SDATA_OUT_I2S_MD, 118 .tx = GPIO30_SDATA_OUT_I2S_MD,
75 .clk = GPIO28_BITCLK_OUT_I2S_MD, 119 .clk = GPIO28_BITCLK_OUT_I2S_MD,
@@ -343,6 +387,11 @@ static struct platform_driver pxa2xx_i2s_driver = {
343 387
344static int __init pxa2xx_i2s_init(void) 388static int __init pxa2xx_i2s_init(void)
345{ 389{
390 if (cpu_is_pxa27x())
391 gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD;
392 else
393 gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD;
394
346 clk_i2s = ERR_PTR(-ENOENT); 395 clk_i2s = ERR_PTR(-ENOENT);
347 return platform_driver_register(&pxa2xx_i2s_driver); 396 return platform_driver_register(&pxa2xx_i2s_driver);
348} 397}
@@ -356,6 +405,6 @@ module_init(pxa2xx_i2s_init);
356module_exit(pxa2xx_i2s_exit); 405module_exit(pxa2xx_i2s_exit);
357 406
358/* Module information */ 407/* Module information */
359MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 408MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
360MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); 409MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
361MODULE_LICENSE("GPL"); 410MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 4345f387fe41..afcd892cd2fa 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -10,64 +10,14 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/dma-mapping.h> 13#include <linux/dma-mapping.h>
18 14
19#include <sound/core.h> 15#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h> 16#include <sound/soc.h>
23 17#include <sound/pxa2xx-lib.h>
24#include <asm/dma.h>
25#include <mach/hardware.h>
26#include <mach/pxa-regs.h>
27#include <mach/audio.h>
28 18
29#include "pxa2xx-pcm.h" 19#include "pxa2xx-pcm.h"
30 20#include "../../arm/pxa2xx-pcm.h"
31static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
32 .info = SNDRV_PCM_INFO_MMAP |
33 SNDRV_PCM_INFO_MMAP_VALID |
34 SNDRV_PCM_INFO_INTERLEAVED |
35 SNDRV_PCM_INFO_PAUSE |
36 SNDRV_PCM_INFO_RESUME,
37 .formats = SNDRV_PCM_FMTBIT_S16_LE |
38 SNDRV_PCM_FMTBIT_S24_LE |
39 SNDRV_PCM_FMTBIT_S32_LE,
40 .period_bytes_min = 32,
41 .period_bytes_max = 8192 - 32,
42 .periods_min = 1,
43 .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
44 .buffer_bytes_max = 128 * 1024,
45 .fifo_size = 32,
46};
47
48struct pxa2xx_runtime_data {
49 int dma_ch;
50 struct pxa2xx_pcm_dma_params *params;
51 pxa_dma_desc *dma_desc_array;
52 dma_addr_t dma_desc_array_phys;
53};
54
55static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
56{
57 struct snd_pcm_substream *substream = dev_id;
58 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
59 int dcsr;
60
61 dcsr = DCSR(dma_ch);
62 DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
63
64 if (dcsr & DCSR_ENDINTR) {
65 snd_pcm_period_elapsed(substream);
66 } else {
67 printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
68 prtd->params->name, dma_ch, dcsr);
69 }
70}
71 21
72static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 22static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
73 struct snd_pcm_hw_params *params) 23 struct snd_pcm_hw_params *params)
@@ -76,10 +26,6 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
76 struct pxa2xx_runtime_data *prtd = runtime->private_data; 26 struct pxa2xx_runtime_data *prtd = runtime->private_data;
77 struct snd_soc_pcm_runtime *rtd = substream->private_data; 27 struct snd_soc_pcm_runtime *rtd = substream->private_data;
78 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; 28 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
79 size_t totsize = params_buffer_bytes(params);
80 size_t period = params_period_bytes(params);
81 pxa_dma_desc *dma_desc;
82 dma_addr_t dma_buff_phys, next_desc_phys;
83 int ret; 29 int ret;
84 30
85 /* return if this is a bufferless transfer e.g. 31 /* return if this is a bufferless transfer e.g.
@@ -106,42 +52,16 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
106 prtd->dma_ch = ret; 52 prtd->dma_ch = ret;
107 } 53 }
108 54
109 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 55 return __pxa2xx_pcm_hw_params(substream, params);
110 runtime->dma_bytes = totsize;
111
112 dma_desc = prtd->dma_desc_array;
113 next_desc_phys = prtd->dma_desc_array_phys;
114 dma_buff_phys = runtime->dma_addr;
115 do {
116 next_desc_phys += sizeof(pxa_dma_desc);
117 dma_desc->ddadr = next_desc_phys;
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
119 dma_desc->dsadr = dma_buff_phys;
120 dma_desc->dtadr = prtd->params->dev_addr;
121 } else {
122 dma_desc->dsadr = prtd->params->dev_addr;
123 dma_desc->dtadr = dma_buff_phys;
124 }
125 if (period > totsize)
126 period = totsize;
127 dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
128 dma_desc++;
129 dma_buff_phys += period;
130 } while (totsize -= period);
131 dma_desc[-1].ddadr = prtd->dma_desc_array_phys;
132
133 return 0;
134} 56}
135 57
136static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) 58static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
137{ 59{
138 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 60 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
139 61
140 if (prtd && prtd->params) 62 __pxa2xx_pcm_hw_free(substream);
141 *prtd->params->drcmr = 0;
142 63
143 if (prtd->dma_ch) { 64 if (prtd->dma_ch) {
144 snd_pcm_set_runtime_buffer(substream, NULL);
145 pxa_free_dma(prtd->dma_ch); 65 pxa_free_dma(prtd->dma_ch);
146 prtd->dma_ch = 0; 66 prtd->dma_ch = 0;
147 } 67 }
@@ -149,188 +69,21 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
149 return 0; 69 return 0;
150} 70}
151 71
152static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
153{
154 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
155
156 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
157 DCSR(prtd->dma_ch) = 0;
158 DCMD(prtd->dma_ch) = 0;
159 *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
160
161 return 0;
162}
163
164static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
165{
166 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
167 int ret = 0;
168
169 switch (cmd) {
170 case SNDRV_PCM_TRIGGER_START:
171 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
172 DCSR(prtd->dma_ch) = DCSR_RUN;
173 break;
174
175 case SNDRV_PCM_TRIGGER_STOP:
176 case SNDRV_PCM_TRIGGER_SUSPEND:
177 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
178 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
179 break;
180
181 case SNDRV_PCM_TRIGGER_RESUME:
182 DCSR(prtd->dma_ch) |= DCSR_RUN;
183 break;
184 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
185 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
186 DCSR(prtd->dma_ch) |= DCSR_RUN;
187 break;
188
189 default:
190 ret = -EINVAL;
191 }
192
193 return ret;
194}
195
196static snd_pcm_uframes_t
197pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
198{
199 struct snd_pcm_runtime *runtime = substream->runtime;
200 struct pxa2xx_runtime_data *prtd = runtime->private_data;
201
202 dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
203 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
204 snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
205
206 if (x == runtime->buffer_size)
207 x = 0;
208 return x;
209}
210
211static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
212{
213 struct snd_pcm_runtime *runtime = substream->runtime;
214 struct pxa2xx_runtime_data *prtd;
215 int ret;
216
217 snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware);
218
219 /*
220 * For mysterious reasons (and despite what the manual says)
221 * playback samples are lost if the DMA count is not a multiple
222 * of the DMA burst size. Let's add a rule to enforce that.
223 */
224 ret = snd_pcm_hw_constraint_step(runtime, 0,
225 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
226 if (ret)
227 goto out;
228
229 ret = snd_pcm_hw_constraint_step(runtime, 0,
230 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
231 if (ret)
232 goto out;
233
234 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
235 if (ret < 0)
236 goto out;
237
238 prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL);
239 if (prtd == NULL) {
240 ret = -ENOMEM;
241 goto out;
242 }
243
244 prtd->dma_desc_array =
245 dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
246 &prtd->dma_desc_array_phys, GFP_KERNEL);
247 if (!prtd->dma_desc_array) {
248 ret = -ENOMEM;
249 goto err1;
250 }
251
252 runtime->private_data = prtd;
253 return 0;
254
255 err1:
256 kfree(prtd);
257 out:
258 return ret;
259}
260
261static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
262{
263 struct snd_pcm_runtime *runtime = substream->runtime;
264 struct pxa2xx_runtime_data *prtd = runtime->private_data;
265
266 dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
267 prtd->dma_desc_array, prtd->dma_desc_array_phys);
268 kfree(prtd);
269 return 0;
270}
271
272static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
273 struct vm_area_struct *vma)
274{
275 struct snd_pcm_runtime *runtime = substream->runtime;
276 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
277 runtime->dma_area,
278 runtime->dma_addr,
279 runtime->dma_bytes);
280}
281
282struct snd_pcm_ops pxa2xx_pcm_ops = { 72struct snd_pcm_ops pxa2xx_pcm_ops = {
283 .open = pxa2xx_pcm_open, 73 .open = __pxa2xx_pcm_open,
284 .close = pxa2xx_pcm_close, 74 .close = __pxa2xx_pcm_close,
285 .ioctl = snd_pcm_lib_ioctl, 75 .ioctl = snd_pcm_lib_ioctl,
286 .hw_params = pxa2xx_pcm_hw_params, 76 .hw_params = pxa2xx_pcm_hw_params,
287 .hw_free = pxa2xx_pcm_hw_free, 77 .hw_free = pxa2xx_pcm_hw_free,
288 .prepare = pxa2xx_pcm_prepare, 78 .prepare = __pxa2xx_pcm_prepare,
289 .trigger = pxa2xx_pcm_trigger, 79 .trigger = pxa2xx_pcm_trigger,
290 .pointer = pxa2xx_pcm_pointer, 80 .pointer = pxa2xx_pcm_pointer,
291 .mmap = pxa2xx_pcm_mmap, 81 .mmap = pxa2xx_pcm_mmap,
292}; 82};
293 83
294static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
295{
296 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
297 struct snd_dma_buffer *buf = &substream->dma_buffer;
298 size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
299 buf->dev.type = SNDRV_DMA_TYPE_DEV;
300 buf->dev.dev = pcm->card->dev;
301 buf->private_data = NULL;
302 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
303 &buf->addr, GFP_KERNEL);
304 if (!buf->area)
305 return -ENOMEM;
306 buf->bytes = size;
307 return 0;
308}
309
310static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
311{
312 struct snd_pcm_substream *substream;
313 struct snd_dma_buffer *buf;
314 int stream;
315
316 for (stream = 0; stream < 2; stream++) {
317 substream = pcm->streams[stream].substream;
318 if (!substream)
319 continue;
320
321 buf = &substream->dma_buffer;
322 if (!buf->area)
323 continue;
324
325 dma_free_writecombine(pcm->card->dev, buf->bytes,
326 buf->area, buf->addr);
327 buf->area = NULL;
328 }
329}
330
331static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK; 84static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
332 85
333int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 86static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
334 struct snd_pcm *pcm) 87 struct snd_pcm *pcm)
335{ 88{
336 int ret = 0; 89 int ret = 0;
@@ -360,7 +113,7 @@ int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
360struct snd_soc_platform pxa2xx_soc_platform = { 113struct snd_soc_platform pxa2xx_soc_platform = {
361 .name = "pxa2xx-audio", 114 .name = "pxa2xx-audio",
362 .pcm_ops = &pxa2xx_pcm_ops, 115 .pcm_ops = &pxa2xx_pcm_ops,
363 .pcm_new = pxa2xx_pcm_new, 116 .pcm_new = pxa2xx_soc_pcm_new,
364 .pcm_free = pxa2xx_pcm_free_dma_buffers, 117 .pcm_free = pxa2xx_pcm_free_dma_buffers,
365}; 118};
366EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); 119EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
index 54c9c755e508..60c3b20aeeb4 100644
--- a/sound/soc/pxa/pxa2xx-pcm.h
+++ b/sound/soc/pxa/pxa2xx-pcm.h
@@ -13,21 +13,6 @@
13#ifndef _PXA2XX_PCM_H 13#ifndef _PXA2XX_PCM_H
14#define _PXA2XX_PCM_H 14#define _PXA2XX_PCM_H
15 15
16struct pxa2xx_pcm_dma_params {
17 char *name; /* stream identifier */
18 u32 dcmd; /* DMA descriptor dcmd field */
19 volatile u32 *drcmr; /* the DMA request channel to use */
20 u32 dev_addr; /* device physical address for DMA */
21};
22
23struct pxa2xx_gpio {
24 u32 sys;
25 u32 rx;
26 u32 tx;
27 u32 clk;
28 u32 frm;
29};
30
31/* platform data */ 16/* platform data */
32extern struct snd_soc_platform pxa2xx_soc_platform; 17extern struct snd_soc_platform pxa2xx_soc_platform;
33 18
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 37cb768fc933..d307b6757e95 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -19,16 +19,15 @@
19#include <linux/timer.h> 19#include <linux/timer.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/gpio.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/soc.h> 25#include <sound/soc.h>
25#include <sound/soc-dapm.h> 26#include <sound/soc-dapm.h>
26 27
27#include <asm/mach-types.h> 28#include <asm/mach-types.h>
28#include <asm/hardware/scoop.h>
29#include <mach/pxa-regs.h> 29#include <mach/pxa-regs.h>
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <mach/akita.h>
32#include <mach/spitz.h> 31#include <mach/spitz.h>
33#include "../codecs/wm8750.h" 32#include "../codecs/wm8750.h"
34#include "pxa2xx-pcm.h" 33#include "pxa2xx-pcm.h"
@@ -63,8 +62,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
63 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 62 snd_soc_dapm_disable_pin(codec, "Mic Jack");
64 snd_soc_dapm_disable_pin(codec, "Line Jack"); 63 snd_soc_dapm_disable_pin(codec, "Line Jack");
65 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 64 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
66 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 65 gpio_set_value(SPITZ_GPIO_MUTE_L, 1);
67 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 66 gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
68 break; 67 break;
69 case SPITZ_MIC: 68 case SPITZ_MIC:
70 /* enable mic jack and bias, mute hp */ 69 /* enable mic jack and bias, mute hp */
@@ -72,8 +71,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
72 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 71 snd_soc_dapm_disable_pin(codec, "Headset Jack");
73 snd_soc_dapm_disable_pin(codec, "Line Jack"); 72 snd_soc_dapm_disable_pin(codec, "Line Jack");
74 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 73 snd_soc_dapm_enable_pin(codec, "Mic Jack");
75 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 74 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
76 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 75 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
77 break; 76 break;
78 case SPITZ_LINE: 77 case SPITZ_LINE:
79 /* enable line jack, disable mic bias and mute hp */ 78 /* enable line jack, disable mic bias and mute hp */
@@ -81,8 +80,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
81 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 80 snd_soc_dapm_disable_pin(codec, "Headset Jack");
82 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 81 snd_soc_dapm_disable_pin(codec, "Mic Jack");
83 snd_soc_dapm_enable_pin(codec, "Line Jack"); 82 snd_soc_dapm_enable_pin(codec, "Line Jack");
84 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 83 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
85 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 84 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
86 break; 85 break;
87 case SPITZ_HEADSET: 86 case SPITZ_HEADSET:
88 /* enable and unmute headset jack enable mic bias, mute L hp */ 87 /* enable and unmute headset jack enable mic bias, mute L hp */
@@ -90,8 +89,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
90 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 89 snd_soc_dapm_enable_pin(codec, "Mic Jack");
91 snd_soc_dapm_disable_pin(codec, "Line Jack"); 90 snd_soc_dapm_disable_pin(codec, "Line Jack");
92 snd_soc_dapm_enable_pin(codec, "Headset Jack"); 91 snd_soc_dapm_enable_pin(codec, "Headset Jack");
93 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 92 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
94 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 93 gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
95 break; 94 break;
96 case SPITZ_HP_OFF: 95 case SPITZ_HP_OFF:
97 96
@@ -100,8 +99,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
100 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 99 snd_soc_dapm_disable_pin(codec, "Headset Jack");
101 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 100 snd_soc_dapm_disable_pin(codec, "Mic Jack");
102 snd_soc_dapm_disable_pin(codec, "Line Jack"); 101 snd_soc_dapm_disable_pin(codec, "Line Jack");
103 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 102 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
104 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 103 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
105 break; 104 break;
106 } 105 }
107 snd_soc_dapm_sync(codec); 106 snd_soc_dapm_sync(codec);
@@ -215,23 +214,14 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol,
215static int spitz_mic_bias(struct snd_soc_dapm_widget *w, 214static int spitz_mic_bias(struct snd_soc_dapm_widget *w,
216 struct snd_kcontrol *k, int event) 215 struct snd_kcontrol *k, int event)
217{ 216{
218 if (machine_is_borzoi() || machine_is_spitz()) { 217 if (machine_is_borzoi() || machine_is_spitz())
219 if (SND_SOC_DAPM_EVENT_ON(event)) 218 gpio_set_value(SPITZ_GPIO_MIC_BIAS,
220 set_scoop_gpio(&spitzscoop2_device.dev, 219 SND_SOC_DAPM_EVENT_ON(event));
221 SPITZ_SCP2_MIC_BIAS); 220
222 else 221 if (machine_is_akita())
223 reset_scoop_gpio(&spitzscoop2_device.dev, 222 gpio_set_value(AKITA_GPIO_MIC_BIAS,
224 SPITZ_SCP2_MIC_BIAS); 223 SND_SOC_DAPM_EVENT_ON(event));
225 }
226 224
227 if (machine_is_akita()) {
228 if (SND_SOC_DAPM_EVENT_ON(event))
229 akita_set_ioexp(&akitaioexp_device.dev,
230 AKITA_IOEXP_MIC_BIAS);
231 else
232 akita_reset_ioexp(&akitaioexp_device.dev,
233 AKITA_IOEXP_MIC_BIAS);
234 }
235 return 0; 225 return 0;
236} 226}
237 227
@@ -291,13 +281,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
291 int i, err; 281 int i, err;
292 282
293 /* NC codec pins */ 283 /* NC codec pins */
294 snd_soc_dapm_disable_pin(codec, "RINPUT1"); 284 snd_soc_dapm_nc_pin(codec, "RINPUT1");
295 snd_soc_dapm_disable_pin(codec, "LINPUT2"); 285 snd_soc_dapm_nc_pin(codec, "LINPUT2");
296 snd_soc_dapm_disable_pin(codec, "RINPUT2"); 286 snd_soc_dapm_nc_pin(codec, "RINPUT2");
297 snd_soc_dapm_disable_pin(codec, "LINPUT3"); 287 snd_soc_dapm_nc_pin(codec, "LINPUT3");
298 snd_soc_dapm_disable_pin(codec, "RINPUT3"); 288 snd_soc_dapm_nc_pin(codec, "RINPUT3");
299 snd_soc_dapm_disable_pin(codec, "OUT3"); 289 snd_soc_dapm_nc_pin(codec, "OUT3");
300 snd_soc_dapm_disable_pin(codec, "MONO1"); 290 snd_soc_dapm_nc_pin(codec, "MONO1");
301 291
302 /* Add spitz specific controls */ 292 /* Add spitz specific controls */
303 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { 293 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
@@ -337,6 +327,7 @@ static struct snd_soc_machine snd_soc_machine_spitz = {
337 327
338/* spitz audio private data */ 328/* spitz audio private data */
339static struct wm8750_setup_data spitz_wm8750_setup = { 329static struct wm8750_setup_data spitz_wm8750_setup = {
330 .i2c_bus = 0,
340 .i2c_address = 0x1b, 331 .i2c_address = 0x1b,
341}; 332};
342 333
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 2baaa750f123..afefe41b8c46 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
190{ 190{
191 int i, err; 191 int i, err;
192 192
193 snd_soc_dapm_disable_pin(codec, "OUT3"); 193 snd_soc_dapm_nc_pin(codec, "OUT3");
194 snd_soc_dapm_disable_pin(codec, "MONOOUT"); 194 snd_soc_dapm_nc_pin(codec, "MONOOUT");
195 195
196 /* add tosa specific controls */ 196 /* add tosa specific controls */
197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { 197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {