[atheros] Implement a preliminary combined image format.
[openwrt.git] / target / linux / pxa / patches-2.6.21 / 027-ucb1400-ac97-audio.patch
1 --- a/sound/pci/ac97/ac97_codec.c
2 +++ b/sound/pci/ac97/ac97_codec.c
3 @@ -158,7 +158,7 @@ static const struct ac97_codec_id snd_ac
4 { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk
5 { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
6 { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix
7 -{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL },
8 +{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL, AC97_HAS_NO_STD_PCM },
9 { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH },
10 { 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
11 { 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
12 --- a/sound/pci/ac97/ac97_patch.c
13 +++ b/sound/pci/ac97/ac97_patch.c
14 @@ -29,6 +29,10 @@
15 #include <linux/slab.h>
16 #include <linux/mutex.h>
17
18 +#include <linux/proc_fs.h>
19 +#include <linux/string.h>
20 +#include <linux/ctype.h>
21 +
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/control.h>
25 @@ -406,6 +410,227 @@ int patch_yamaha_ymf753(struct snd_ac97
26 }
27
28 /*
29 + * UCB1400 codec
30 + */
31 +
32 +#define AC97_UCB1400_FCSR1 0x6a
33 +#define AC97_UCB1400_FCSR2 0x6c
34 +
35 +static const struct snd_kcontrol_new ucb1400_snd_ac97_controls[] = {
36 + AC97_SINGLE("Tone Control - Bass", AC97_UCB1400_FCSR1, 11, 4, 0),
37 + AC97_SINGLE("Tone Control - Treble", AC97_UCB1400_FCSR1, 9, 2, 0),
38 + AC97_SINGLE("Headphone Playback Switch", AC97_UCB1400_FCSR1, 6, 1, 0),
39 + AC97_SINGLE("De-emphasis", AC97_UCB1400_FCSR1, 5, 1, 0),
40 + AC97_SINGLE("DC Filter", AC97_UCB1400_FCSR1, 4, 1, 0),
41 + AC97_SINGLE("Hi-pass Filter", AC97_UCB1400_FCSR1, 3, 1, 0),
42 + AC97_SINGLE("ADC Filter", AC97_UCB1400_FCSR2, 12, 1, 0),
43 +};
44 +
45 +#define NUM_GPIO_LINES 10
46 +
47 +static struct proc_dir_entry *proc_gpio_parent;
48 +static struct proc_dir_entry *proc_gpios[NUM_GPIO_LINES];
49 +
50 +typedef struct
51 +{
52 + int gpio;
53 + char name[32];
54 + struct snd_ac97 *ac97;
55 +} gpio_summary_type;
56 +
57 +static gpio_summary_type gpio_summaries[NUM_GPIO_LINES] =
58 +{
59 + { 0, "UCB1400-0-0" },
60 + { 1, "UCB1400-0-1" },
61 + { 2, "UCB1400-0-2" },
62 + { 3, "UCB1400-0-3" },
63 + { 4, "UCB1400-0-4" },
64 + { 5, "UCB1400-0-5" },
65 + { 6, "UCB1400-0-6" },
66 + { 7, "UCB1400-0-7" },
67 + { 8, "UCB1400-0-8" },
68 + { 9, "UCB1400-0-9" }
69 +};
70 +
71 +
72 +static int proc_ucb1400_ac97_gpio_write(struct file *file, const char __user *buf,
73 + unsigned long count, void *data)
74 +{
75 + char *cur, lbuf[count + 1];
76 + gpio_summary_type *summary = data;
77 + u32 direction_is_out, operation_is_set;
78 + int i = summary->gpio;
79 + u16 dir, value;
80 +
81 + if (!capable(CAP_SYS_ADMIN))
82 + return -EACCES;
83 +
84 + memset(lbuf, 0, count + 1);
85 +
86 + if (copy_from_user(lbuf, buf, count))
87 + return -EFAULT;
88 +
89 + cur = lbuf;
90 +
91 + // Get current values
92 + direction_is_out = !!(snd_ac97_read(summary->ac97, 0x5c) & (0x0001 << i));
93 + operation_is_set = !!(snd_ac97_read(summary->ac97, 0x5a) & (0x0001 << i));
94 + while(1)
95 + {
96 + // We accept options: {GPIO|AF1|AF2|AF3}, {set|clear}, {in|out}
97 + // Anything else is an error
98 + while(cur[0] && (isspace(cur[0]) || ispunct(cur[0]))) cur = &(cur[1]);
99 +
100 + if('\0' == cur[0]) break;
101 +
102 + // Ok, so now we're pointing at the start of something
103 + switch(cur[0])
104 + {
105 + case 'G':
106 + // Check that next is "PIO" -- '\0' will cause safe short-circuit if end of buf
107 + if(!(cur[1] == 'P' && cur[2] == 'I' && cur[3] == 'O')) goto parse_error;
108 + cur = &(cur[4]);
109 + break;
110 + case 's':
111 + if(!(cur[1] == 'e' && cur[2] == 't')) goto parse_error;
112 + operation_is_set = 1;
113 + cur = &(cur[3]);
114 + break;
115 + case 'c':
116 + if(!(cur[1] == 'l' && cur[2] == 'e' && cur[3] == 'a' && cur[4] == 'r')) goto
117 +parse_error;
118 + operation_is_set = 0;
119 + cur = &(cur[5]);
120 + break;
121 + case 'i':
122 + if(!(cur[1] == 'n')) goto parse_error;
123 + direction_is_out = 0;
124 + cur = &(cur[2]);
125 + break;
126 + case 'o':
127 + if(!(cur[1] == 'u' && cur[2] == 't')) goto parse_error;
128 + direction_is_out = 1;
129 + cur = &(cur[3]);
130 + break;
131 + default: goto parse_error;
132 + }
133 + }
134 +
135 + // set/get value
136 + dir = snd_ac97_read(summary->ac97, 0x5c);
137 + value = snd_ac97_read(summary->ac97, 0x5a);
138 + if (direction_is_out)
139 + {
140 + dir |= 0x0001 << i;
141 + if (operation_is_set)
142 + {
143 + value |= 0x0001 << i;
144 + }
145 + else
146 + {
147 + value &= ~(0x0001 << i);
148 + }
149 +
150 + snd_ac97_write(summary->ac97, 0x5c, dir);
151 + snd_ac97_write(summary->ac97, 0x5a, value);
152 + }
153 + else // direction in
154 + {
155 + dir &= ~(0x0001 << i);
156 + snd_ac97_write(summary->ac97, 0x5c, dir);
157 + operation_is_set = snd_ac97_read(summary->ac97, 0x5a) & ~(0x0001 << i);
158 + }
159 +
160 +#ifdef CONFIG_PROC_GPIO_DEBUG
161 + printk(KERN_INFO "Set (%s,%s,%s) via /proc/gpio/%s\n",
162 + "GPIO",
163 + direction_is_out ? "out" : "in",
164 + operation_is_set ? "set" : "clear",
165 + summary->name);
166 +#endif
167 +
168 + return count;
169 +
170 +parse_error:
171 + printk(KERN_CRIT "Parse error: Expect \"GPIO|[set|clear]|[in|out] ...\"\n");
172 + return -EINVAL;
173 +}
174 +
175 +static int proc_ucb1400_ac97_gpio_read(char *page, char **start, off_t off,
176 + int count, int *eof, void *data)
177 +{
178 + char *p = page;
179 + gpio_summary_type *summary = data;
180 + int len, i; /*, af;*/
181 + i = summary->gpio;
182 +
183 + p += sprintf(p, "%d\t%s\t%s\t%s\n", i,
184 + "GPIO",
185 + (snd_ac97_read(summary->ac97, 0x5c) & (0x0001 << i)) ? "out" : "in",
186 + (snd_ac97_read(summary->ac97, 0x5a) & (0x0001 << i)) ? "set" : "clear");
187 +
188 + len = (p - page) - off;
189 +
190 + if(len < 0)
191 + {
192 + len = 0;
193 + }
194 +
195 + *eof = (len <= count) ? 1 : 0;
196 + *start = page + off;
197 +
198 + return len;
199 +}
200 +
201 +int patch_ucb1400(struct snd_ac97 * ac97)
202 +{
203 + int err, i;
204 +
205 + proc_gpio_parent = proc_mkdir("gpio", NULL);
206 + if(!proc_gpio_parent) return 0;
207 +
208 + for(i=0; i < NUM_GPIO_LINES; i++)
209 + {
210 + proc_gpios[i] = create_proc_entry(gpio_summaries[i].name, 0644, proc_gpio_parent);
211 + if(proc_gpios[i])
212 + {
213 + gpio_summaries[i].ac97 = ac97;
214 + proc_gpios[i]->data = &gpio_summaries[i];
215 + proc_gpios[i]->read_proc = proc_ucb1400_ac97_gpio_read;
216 + proc_gpios[i]->write_proc = proc_ucb1400_ac97_gpio_write;
217 + }
218 + }
219 +
220 + for(i = 0; i < ARRAY_SIZE(ucb1400_snd_ac97_controls); i++) {
221 + if((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&ucb1400_snd_ac97_controls[i], ac97))) < 0)
222 + return err;
223 + }
224 +
225 + snd_ac97_write_cache(ac97, AC97_UCB1400_FCSR1,
226 + (0 << 11) | // 0 base boost
227 + (0 << 9) | // 0 treble boost
228 + (0 << 7) | // Mode = flat
229 + (1 << 6) | // Headphones enable
230 + (0 << 5) | // De-emphasis disabled
231 + (1 << 4) | // DC filter enabled
232 + (1 << 3) | // Hi-pass filter enabled
233 + (0 << 2) | // disable interrupt signalling via GPIO_INT
234 + (1 << 0) // clear ADC overflow status if set
235 + );
236 +
237 + snd_ac97_write_cache(ac97, AC97_UCB1400_FCSR2,
238 + (0 << 15) | // must be 0
239 + (0 << 13) | // must be 0
240 + (1 << 12) | // ADC filter enabled
241 + (0 << 10) | // must be 0
242 + (0 << 4) | // Smart low power mode on neither Codec nor PLL
243 + (0 << 0) // must be 0
244 + );
245 +
246 + return 0;
247 +}
248 +
249 +/*
250 * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
251 * removed broken wolfson00 patch.
252 * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
253 @@ -3408,41 +3633,3 @@ int patch_lm4550(struct snd_ac97 *ac97)
254 ac97->res_table = lm4550_restbl;
255 return 0;
256 }
257 -
258 -/*
259 - * UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf)
260 - */
261 -static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = {
262 -/* enable/disable headphone driver which allows direct connection to
263 - stereo headphone without the use of external DC blocking
264 - capacitors */
265 -AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0),
266 -/* Filter used to compensate the DC offset is added in the ADC to remove idle
267 - tones from the audio band. */
268 -AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0),
269 -/* Control smart-low-power mode feature. Allows automatic power down
270 - of unused blocks in the ADC analog front end and the PLL. */
271 -AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0),
272 -};
273 -
274 -static int patch_ucb1400_specific(struct snd_ac97 * ac97)
275 -{
276 - int idx, err;
277 - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++)
278 - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0)
279 - return err;
280 - return 0;
281 -}
282 -
283 -static struct snd_ac97_build_ops patch_ucb1400_ops = {
284 - .build_specific = patch_ucb1400_specific,
285 -};
286 -
287 -int patch_ucb1400(struct snd_ac97 * ac97)
288 -{
289 - ac97->build_ops = &patch_ucb1400_ops;
290 - /* enable headphone driver and smart low power mode by default */
291 - snd_ac97_write(ac97, 0x6a, 0x0050);
292 - snd_ac97_write(ac97, 0x6c, 0x0030);
293 - return 0;
294 -}
This page took 0.053759 seconds and 5 git commands to generate.