upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / sound / pci / ice1712 / aureon.c
1 /*
2  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  *   Lowlevel functions for Terratec Aureon cards
5  *
6  *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  *
23  * NOTES:
24  *
25  * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
26  *   both wm and akm codecs are pretty similar, so we can integrate
27  *   both controls in the future, once if wm codecs are reused in
28  *   many boards.
29  *
30  * - writing over SPI is implemented but reading is not yet.
31  *   the SPDIF-in channel status, etc. can be read from CS chip.
32  *
33  * - DAC digital volumes are not implemented in the mixer.
34  *   if they show better response than DAC analog volumes, we can use them
35  *   instead.
36  *
37  * - Aureon boards are equipped with AC97 codec, too.  it's used to do
38  *   the analog mixing but not easily controllable (it's not connected
39  *   directly from envy24ht chip).  so let's leave it as it is.
40  *
41  *
42  *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
43  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
44  *
45  *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
46  *       added 64x/128x oversampling switch (should be 64x only for 96khz)
47  *       fixed some recording labels (still need to check the rest)
48  *       recording is working probably thanks to correct wm8770 initialization
49  *
50  *   version 0.5: Initial release:
51  *           working: analog output, mixer, headphone amplifier switch
52  *       not working: prety much everything else, at least i could verify that
53  *                    we have no digital output, no capture, pretty bad clicks and poops
54  *                    on mixer switch and other coll stuff.
55  *
56  * - Prodigy boards are equipped with AC97 STAC9744 chip , too.  it's used to do
57  *   the analog mixing but not easily controllable (it's not connected
58  *   directly from envy24ht chip).  so let's leave it as it is.
59  *
60  */      
61
62 #include <sound/driver.h>
63 #include <asm/io.h>
64 #include <linux/delay.h>
65 #include <linux/interrupt.h>
66 #include <linux/init.h>
67 #include <linux/slab.h>
68 #include <sound/core.h>
69
70 #include "ice1712.h"
71 #include "envy24ht.h"
72 #include "aureon.h"
73
74 /* WM8770 registers */
75 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
76 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
77 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
78 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
79 #define WM_PHASE_SWAP           0x12    /* DAC phase */
80 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
81 #define WM_MUTE                 0x14    /* mute controls */
82 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
83 #define WM_INT_CTRL             0x16    /* interface control */
84 #define WM_MASTER               0x17    /* master clock and mode */
85 #define WM_POWERDOWN            0x18    /* power-down controls */
86 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
87 #define WM_ADC_MUX              0x1b    /* input MUX */
88 #define WM_OUT_MUX1             0x1c    /* output MUX */
89 #define WM_OUT_MUX2             0x1e    /* output MUX */
90 #define WM_RESET                0x1f    /* software reset */
91
92 static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
93         unsigned int tmp;
94
95         /* Send address to XILINX chip */
96         tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
97         snd_ice1712_gpio_write(ice, tmp);
98         udelay(10);
99         tmp |= AUREON_AC97_ADDR;
100         snd_ice1712_gpio_write(ice, tmp);
101         udelay(10);
102         tmp &= ~AUREON_AC97_ADDR;
103         snd_ice1712_gpio_write(ice, tmp);
104         udelay(10);     
105
106         /* Send low-order byte to XILINX chip */
107         tmp &= ~AUREON_AC97_DATA_MASK;
108         tmp |= val & AUREON_AC97_DATA_MASK;
109         snd_ice1712_gpio_write(ice, tmp);
110         udelay(10);
111         tmp |= AUREON_AC97_DATA_LOW;
112         snd_ice1712_gpio_write(ice, tmp);
113         udelay(10);
114         tmp &= ~AUREON_AC97_DATA_LOW;
115         snd_ice1712_gpio_write(ice, tmp);
116         udelay(10);
117         
118         /* Send high-order byte to XILINX chip */
119         tmp &= ~AUREON_AC97_DATA_MASK;
120         tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
121
122         snd_ice1712_gpio_write(ice, tmp);
123         udelay(10);
124         tmp |= AUREON_AC97_DATA_HIGH;
125         snd_ice1712_gpio_write(ice, tmp);
126         udelay(10);
127         tmp &= ~AUREON_AC97_DATA_HIGH;
128         snd_ice1712_gpio_write(ice, tmp);
129         udelay(10);
130         
131         /* Instruct XILINX chip to parse the data to the STAC9744 chip */
132         tmp |= AUREON_AC97_COMMIT;
133         snd_ice1712_gpio_write(ice, tmp);
134         udelay(10);
135         tmp &= ~AUREON_AC97_COMMIT;
136         snd_ice1712_gpio_write(ice, tmp);
137         udelay(10);
138         
139         /* Store the data in out private buffer */
140         ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
141 }
142
143 static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
144 {
145        return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
146 }
147
148 /*
149  * Initialize STAC9744 chip
150  */
151 static int aureon_ac97_init (ice1712_t *ice) {
152         int i;
153         static unsigned short ac97_defaults[] = {
154                 0x00, 0x9640,
155                 0x02, 0x8000,
156                 0x04, 0x8000,
157                 0x06, 0x8000,
158                 0x0C, 0x8008,
159                 0x0E, 0x8008,
160                 0x10, 0x8808,
161                 0x12, 0x8808,
162                 0x14, 0x8808,
163                 0x16, 0x8808,
164                 0x18, 0x8808,
165                 0x1C, 0x8000,
166                 0x26, 0x000F,
167                 0x28, 0x0201,
168                 0x2C, 0xBB80,
169                 0x32, 0xBB80,
170                 0x7C, 0x8384,
171                 0x7E, 0x7644,
172                 (unsigned short)-1
173         };
174         unsigned int tmp;
175
176         /* Cold reset */
177         tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
178         snd_ice1712_gpio_write(ice, tmp);
179         udelay(3);
180         
181         tmp &= ~AUREON_AC97_RESET;
182         snd_ice1712_gpio_write(ice, tmp);
183         udelay(3);
184         
185         tmp |= AUREON_AC97_RESET;
186         snd_ice1712_gpio_write(ice, tmp);
187         udelay(3);
188         
189         memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
190         for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
191                 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
192                 
193         aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
194
195         return 0;
196 }
197
198 #define AUREON_AC97_STEREO      0x80
199
200 /*
201  * AC'97 volume controls
202  */
203 static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
204 {
205         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
206         uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
207         uinfo->value.integer.min = 0;
208         uinfo->value.integer.max = 31;
209         return 0;
210 }
211
212 static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
213 {
214         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
215         unsigned short vol;
216
217         down(&ice->gpio_mutex);
218
219         vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
220         ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
221         if (kcontrol->private_value & AUREON_AC97_STEREO)
222                 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
223
224         up(&ice->gpio_mutex);
225         return 0;
226 }
227
228 static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
229 {
230         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
231         unsigned short ovol, nvol;
232         int change;
233         
234         snd_ice1712_save_gpio_status(ice);
235
236         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
237         nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
238         if (kcontrol->private_value & AUREON_AC97_STEREO)
239                 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
240         nvol |= ovol & ~0x1F1F;
241         
242         if ((change = (ovol != nvol)))
243                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
244
245         snd_ice1712_restore_gpio_status(ice);
246
247         return change;          
248 }
249
250 /*
251  * AC'97 mute controls
252  */
253 #define aureon_ac97_mute_info   aureon_mono_bool_info
254
255 static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
256 {
257         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
258
259         down(&ice->gpio_mutex);
260
261         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
262
263         up(&ice->gpio_mutex);
264         return 0;
265 }
266
267 static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
268 {
269         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
270         unsigned short ovol, nvol;
271         int change;
272
273         snd_ice1712_save_gpio_status(ice);
274         
275         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
276         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
277         
278         if ((change = (ovol != nvol)))
279                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
280                 
281         snd_ice1712_restore_gpio_status(ice);
282
283         return change;
284 }
285
286 /*
287  * AC'97 mute controls
288  */
289 #define aureon_ac97_micboost_info       aureon_mono_bool_info
290
291 static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
292 {
293         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
294
295         down(&ice->gpio_mutex);
296
297         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
298
299         up(&ice->gpio_mutex);
300         return 0;
301 }
302
303 static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
304 {
305         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
306         unsigned short ovol, nvol;
307         int change;
308
309         snd_ice1712_save_gpio_status(ice);
310         
311         ovol = aureon_ac97_read(ice, AC97_MIC);
312         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
313         
314         if ((change = (ovol != nvol)))
315                 aureon_ac97_write(ice, AC97_MIC, nvol);
316                 
317         snd_ice1712_restore_gpio_status(ice);
318
319         return change;
320 }
321
322 /*
323  * write data in the SPI mode
324  */
325 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
326 {
327         unsigned int tmp;
328         unsigned int cscs;
329         int i;
330
331         tmp = snd_ice1712_gpio_read(ice);
332
333         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
334                 cscs = PRODIGY_CS8415_CS;
335         else
336                 cscs = AUREON_CS8415_CS;
337
338         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_WM_DATA|AUREON_WM_CLK|
339                                          AUREON_WM_CS|cscs));
340         tmp |= AUREON_WM_RW;
341         tmp &= ~cs;
342         snd_ice1712_gpio_write(ice, tmp);
343         udelay(1);
344
345         for (i = bits - 1; i >= 0; i--) {
346                 tmp &= ~AUREON_WM_CLK;
347                 snd_ice1712_gpio_write(ice, tmp);
348                 udelay(1);
349                 if (data & (1 << i))
350                         tmp |= AUREON_WM_DATA;
351                 else
352                         tmp &= ~AUREON_WM_DATA;
353                 snd_ice1712_gpio_write(ice, tmp);
354                 udelay(1);
355                 tmp |= AUREON_WM_CLK;
356                 snd_ice1712_gpio_write(ice, tmp);
357                 udelay(1);
358         }
359
360         tmp &= ~AUREON_WM_CLK;
361         tmp |= cs;
362         snd_ice1712_gpio_write(ice, tmp);
363         udelay(1);
364         tmp |= AUREON_WM_CLK;
365         snd_ice1712_gpio_write(ice, tmp);
366         udelay(1);
367 }
368      
369
370 /*
371  * get the current register value of WM codec
372  */
373 static unsigned short wm_get(ice1712_t *ice, int reg)
374 {
375         reg <<= 1;
376         return ((unsigned short)ice->akm[0].images[reg] << 8) |
377                 ice->akm[0].images[reg + 1];
378 }
379
380 /*
381  * set the register value of WM codec
382  */
383 static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
384 {
385         aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
386 }
387
388 /*
389  * set the register value of WM codec and remember it
390  */
391 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
392 {
393         wm_put_nocache(ice, reg, val);
394         reg <<= 1;
395         ice->akm[0].images[reg] = val >> 8;
396         ice->akm[0].images[reg + 1] = val;
397 }
398
399 /*
400  */
401 static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
402 {
403         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
404         uinfo->count = 1;
405         uinfo->value.integer.min = 0;
406         uinfo->value.integer.max = 1;
407         return 0;
408 }
409
410 /*
411  * AC'97 master playback mute controls (Mute on WM8770 chip)
412  */
413 #define aureon_ac97_mmute_info  aureon_mono_bool_info
414
415 static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
416 {
417         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
418
419         down(&ice->gpio_mutex);
420
421         ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
422
423         up(&ice->gpio_mutex);
424         return 0;
425 }
426
427 static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
428         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
429         unsigned short ovol, nvol;
430         int change;
431         
432         snd_ice1712_save_gpio_status(ice);
433         
434         ovol = wm_get(ice, WM_OUT_MUX1);
435         nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
436         if ((change = (ovol != nvol)))
437                 wm_put(ice, WM_OUT_MUX1, nvol);
438                 
439         snd_ice1712_restore_gpio_status(ice);
440
441         return change;
442 }
443
444 /*
445  * Logarithmic volume values for WM8770
446  * Computed as 20 * Log10(255 / x)
447  */
448 static unsigned char wm_vol[256] = {
449         127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
450         23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
451         17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
452         13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
453         11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
454         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
455         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
456         5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
457         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
458         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
459         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
460         0, 0
461 };
462
463 #define WM_VOL_MAX      (sizeof(wm_vol) - 1)
464 #define WM_VOL_MUTE     0x8000
465
466 static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
467 {
468         unsigned char nvol;
469         
470         if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
471                 nvol = 0;
472         else
473                 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
474         
475         wm_put(ice, index, nvol);
476         wm_put_nocache(ice, index, 0x180 | nvol);
477 }
478
479 /*
480  * DAC mute control
481  */
482 #define wm_pcm_mute_info        aureon_mono_bool_info
483
484 static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
485 {
486         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
487
488         down(&ice->gpio_mutex);
489         ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
490         up(&ice->gpio_mutex);
491         return 0;
492 }
493
494 static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
495 {
496         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
497         unsigned short nval, oval;
498         int change;
499
500         snd_ice1712_save_gpio_status(ice);
501         oval = wm_get(ice, WM_MUTE);
502         nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
503         if ((change = (nval != oval)))
504                 wm_put(ice, WM_MUTE, nval);
505         snd_ice1712_restore_gpio_status(ice);
506
507         return change;
508 }
509
510 /*
511  * Master volume attenuation mixer control
512  */
513 static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
514 {
515         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
516         uinfo->count = 2;
517         uinfo->value.integer.min = 0;
518         uinfo->value.integer.max = WM_VOL_MAX;
519         return 0;
520 }
521
522 static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
523 {
524         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
525         int i;
526         for (i=0; i<2; i++)
527                 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
528         return 0;
529 }
530
531 static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
532 {
533         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
534         int ch, change = 0;
535
536         snd_ice1712_save_gpio_status(ice);
537         for (ch = 0; ch < 2; ch++) {
538                 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
539                         int dac;
540                         ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
541                         ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
542                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
543                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
544                                            ice->spec.aureon.vol[dac + ch],
545                                            ice->spec.aureon.master[ch]);
546                         change = 1;
547                 }
548         }
549         snd_ice1712_restore_gpio_status(ice);
550         return change;
551 }
552
553 /*
554  * DAC volume attenuation mixer control
555  */
556 static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
557 {
558         int voices = kcontrol->private_value >> 8;
559         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
560         uinfo->count = voices;
561         uinfo->value.integer.min = 0;           /* mute (-101dB) */
562         uinfo->value.integer.max = 0x7F;        /* 0dB */
563         return 0;
564 }
565
566 static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
567 {
568         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
569         int i, ofs, voices;
570
571         voices = kcontrol->private_value >> 8;
572         ofs = kcontrol->private_value & 0xff;
573         for (i = 0; i < voices; i++)
574                 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
575         return 0;
576 }
577
578 static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
579 {
580         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
581         int i, idx, ofs, voices;
582         int change = 0;
583
584         voices = kcontrol->private_value >> 8;
585         ofs = kcontrol->private_value & 0xff;
586         snd_ice1712_save_gpio_status(ice);
587         for (i = 0; i < voices; i++) {
588                 idx  = WM_DAC_ATTEN + ofs + i;
589                 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
590                         ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
591                         ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
592                         wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
593                                    ice->spec.aureon.master[i]);
594                         change = 1;
595                 }
596         }
597         snd_ice1712_restore_gpio_status(ice);
598         return change;
599 }
600
601 /*
602  * WM8770 mute control
603  */
604 static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
605         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
606         uinfo->count = kcontrol->private_value >> 8;
607         uinfo->value.integer.min = 0;
608         uinfo->value.integer.max = 1;
609         return 0;
610 }
611
612 static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
613 {
614         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
615         int voices, ofs, i;
616         
617         voices = kcontrol->private_value >> 8;
618         ofs = kcontrol->private_value & 0xFF;
619
620         for (i = 0; i < voices; i++)
621                 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
622         return 0;
623 }
624
625 static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
626 {
627         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
628         int change = 0, voices, ofs, i;
629
630         voices = kcontrol->private_value >> 8;
631         ofs = kcontrol->private_value & 0xFF;
632
633         snd_ice1712_save_gpio_status(ice);
634         for (i = 0; i < voices; i++) {
635                 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
636                 if (ucontrol->value.integer.value[i] != val) {
637                         ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
638                         ice->spec.aureon.vol[ofs + i] |=
639                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
640                         wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
641                                    ice->spec.aureon.master[i]);
642                         change = 1;
643                 }
644         }
645         snd_ice1712_restore_gpio_status(ice);
646
647         return change;
648 }
649
650 /*
651  * WM8770 master mute control
652  */
653 static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
654         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
655         uinfo->count = 2;
656         uinfo->value.integer.min = 0;
657         uinfo->value.integer.max = 1;
658         return 0;
659 }
660
661 static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
662 {
663         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
664         
665         ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
666         ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
667         return 0;
668 }
669
670 static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
671 {
672         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
673         int change = 0, i;
674
675         snd_ice1712_save_gpio_status(ice);
676         for (i = 0; i < 2; i++) {
677                 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
678                 if (ucontrol->value.integer.value[i] != val) {
679                         int dac;
680                         ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
681                         ice->spec.aureon.master[i] |=
682                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
683                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
684                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
685                                            ice->spec.aureon.vol[dac + i],
686                                            ice->spec.aureon.master[i]);
687                         change = 1;
688                 }
689         }
690         snd_ice1712_restore_gpio_status(ice);
691
692         return change;
693 }
694
695 /* digital master volume */
696 #define PCM_0dB 0xff
697 #define PCM_RES 128     /* -64dB */
698 #define PCM_MIN (PCM_0dB - PCM_RES)
699 static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
700 {
701         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
702         uinfo->count = 1;
703         uinfo->value.integer.min = 0;           /* mute (-64dB) */
704         uinfo->value.integer.max = PCM_RES;     /* 0dB */
705         return 0;
706 }
707
708 static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
709 {
710         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
711         unsigned short val;
712
713         down(&ice->gpio_mutex);
714         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
715         val = val > PCM_MIN ? (val - PCM_MIN) : 0;
716         ucontrol->value.integer.value[0] = val;
717         up(&ice->gpio_mutex);
718         return 0;
719 }
720
721 static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
722 {
723         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
724         unsigned short ovol, nvol;
725         int change = 0;
726
727         snd_ice1712_save_gpio_status(ice);
728         nvol = ucontrol->value.integer.value[0];
729         nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
730         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
731         if (ovol != nvol) {
732                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
733                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
734                 change = 1;
735         }
736         snd_ice1712_restore_gpio_status(ice);
737         return change;
738 }
739
740 /*
741  * ADC mute control
742  */
743 static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
744 {
745         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
746         uinfo->count = 2;
747         uinfo->value.integer.min = 0;
748         uinfo->value.integer.max = 1;
749         return 0;
750 }
751
752 static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
753 {
754         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
755         unsigned short val;
756         int i;
757
758         down(&ice->gpio_mutex);
759         for (i = 0; i < 2; i++) {
760                 val = wm_get(ice, WM_ADC_GAIN + i);
761                 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
762         }
763         up(&ice->gpio_mutex);
764         return 0;
765 }
766
767 static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
768 {
769         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
770         unsigned short new, old;
771         int i, change = 0;
772
773         snd_ice1712_save_gpio_status(ice);
774         for (i = 0; i < 2; i++) {
775                 old = wm_get(ice, WM_ADC_GAIN + i);
776                 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
777                 if (new != old) {
778                         wm_put(ice, WM_ADC_GAIN + i, new);
779                         change = 1;
780                 }
781         }
782         snd_ice1712_restore_gpio_status(ice);
783
784         return change;
785 }
786
787 /*
788  * ADC gain mixer control
789  */
790 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
791 {
792         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
793         uinfo->count = 2;
794         uinfo->value.integer.min = 0;           /* -12dB */
795         uinfo->value.integer.max = 0x1f;        /* 19dB */
796         return 0;
797 }
798
799 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
800 {
801         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
802         int i, idx;
803         unsigned short vol;
804
805         down(&ice->gpio_mutex);
806         for (i = 0; i < 2; i++) {
807                 idx = WM_ADC_GAIN + i;
808                 vol = wm_get(ice, idx) & 0x1f;
809                 ucontrol->value.integer.value[i] = vol;
810         }
811         up(&ice->gpio_mutex);
812         return 0;
813 }
814
815 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
816 {
817         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
818         int i, idx;
819         unsigned short ovol, nvol;
820         int change = 0;
821
822         snd_ice1712_save_gpio_status(ice);
823         for (i = 0; i < 2; i++) {
824                 idx  = WM_ADC_GAIN + i;
825                 nvol = ucontrol->value.integer.value[i];
826                 ovol = wm_get(ice, idx);
827                 if ((ovol & 0x1f) != nvol) {
828                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
829                         change = 1;
830                 }
831         }
832         snd_ice1712_restore_gpio_status(ice);
833         return change;
834 }
835
836 /*
837  * ADC input mux mixer control
838  */
839 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
840 {
841         static char *texts[] = {
842                 "CD",           //AIN1
843                 "Aux",          //AIN2
844                 "Line",         //AIN3
845                 "Mic",          //AIN4
846                 "AC97"          //AIN5
847         };
848         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
849         uinfo->count = 2;
850         uinfo->value.enumerated.items = 5;
851         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
852                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
853         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
854         return 0;
855 }
856
857 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
858 {
859         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
860         unsigned short val;
861
862         down(&ice->gpio_mutex);
863         val = wm_get(ice, WM_ADC_MUX);
864         ucontrol->value.integer.value[0] = val & 7;
865         ucontrol->value.integer.value[1] = (val >> 4) & 7;
866         up(&ice->gpio_mutex);
867         return 0;
868 }
869
870 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
871 {
872         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
873         unsigned short oval, nval;
874         int change;
875
876         snd_ice1712_save_gpio_status(ice);
877         oval = wm_get(ice, WM_ADC_MUX);
878         nval = oval & ~0x77;
879         nval |= ucontrol->value.integer.value[0] & 7;
880         nval |= (ucontrol->value.integer.value[1] & 7) << 4;
881         change = (oval != nval);
882         if (change)
883                 wm_put(ice, WM_ADC_MUX, nval);
884         snd_ice1712_restore_gpio_status(ice);
885         return 0;
886 }
887
888 /*
889  * Headphone Amplifier
890  */
891 static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
892 {
893         unsigned int tmp, tmp2;
894
895         tmp2 = tmp = snd_ice1712_gpio_read(ice);
896         if (enable)
897                 tmp |= AUREON_HP_SEL;
898         else
899                 tmp &= ~ AUREON_HP_SEL;
900         if (tmp != tmp2) {
901                 snd_ice1712_gpio_write(ice, tmp);
902                 return 1;
903         }
904         return 0;
905 }
906
907 static int aureon_get_headphone_amp(ice1712_t *ice)
908 {
909         unsigned int tmp = snd_ice1712_gpio_read(ice);
910
911         return ( tmp & AUREON_HP_SEL )!= 0;
912 }
913
914 #define aureon_hpamp_info       aureon_mono_bool_info
915
916 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
917 {
918         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
919
920         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
921         return 0;
922 }
923
924
925 static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
926 {
927         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
928
929         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
930 }
931
932 /*
933  * Deemphasis
934  */
935
936 #define aureon_deemp_info       aureon_mono_bool_info
937
938 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
939 {
940         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
941         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
942         return 0;
943 }
944
945 static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
946 {
947         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
948         int temp, temp2;
949         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
950         if (ucontrol->value.integer.value[0])
951                 temp |= 0xf;
952         else
953                 temp &= ~0xf;
954         if (temp != temp2) {
955                 wm_put(ice, WM_DAC_CTRL2, temp);
956                 return 1;
957         }
958         return 0;
959 }
960
961 /*
962  * ADC Oversampling
963  */
964 static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
965 {
966         static char *texts[2] = { "128x", "64x" };
967
968         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
969         uinfo->count = 1;
970         uinfo->value.enumerated.items = 2;
971
972         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
973                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
974         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
975
976         return 0;
977 }
978
979 static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
980 {
981         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
982         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
983         return 0;
984 }
985
986 static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
987 {
988         int temp, temp2;
989         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
990
991         temp2 = temp = wm_get(ice, WM_MASTER);
992
993         if (ucontrol->value.enumerated.item[0])
994                 temp |= 0x8;
995         else
996                 temp &= ~0x8;
997
998         if (temp != temp2) {
999                 wm_put(ice, WM_MASTER, temp);
1000                 return 1;
1001         }
1002         return 0;
1003 }
1004
1005 /*
1006  * mixers
1007  */
1008
1009 static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
1010         {
1011                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1012                 .name = "Master Playback Switch",
1013                 .info = wm_master_mute_info,
1014                 .get = wm_master_mute_get,
1015                 .put = wm_master_mute_put
1016         },
1017         {
1018                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1019                 .name = "Master Playback Volume",
1020                 .info = wm_master_vol_info,
1021                 .get = wm_master_vol_get,
1022                 .put = wm_master_vol_put
1023         },
1024         {
1025                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1026                 .name = "Front Playback Switch",
1027                 .info = wm_mute_info,
1028                 .get = wm_mute_get,
1029                 .put = wm_mute_put,
1030                 .private_value = (2 << 8) | 0
1031         },
1032         {
1033                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1034                 .name = "Front Playback Volume",
1035                 .info = wm_vol_info,
1036                 .get = wm_vol_get,
1037                 .put = wm_vol_put,
1038                 .private_value = (2 << 8) | 0
1039         },
1040         {
1041                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1042                 .name = "Rear Playback Switch",
1043                 .info = wm_mute_info,
1044                 .get = wm_mute_get,
1045                 .put = wm_mute_put,
1046                 .private_value = (2 << 8) | 2
1047         },
1048         {
1049                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1050                 .name = "Rear Playback Volume",
1051                 .info = wm_vol_info,
1052                 .get = wm_vol_get,
1053                 .put = wm_vol_put,
1054                 .private_value = (2 << 8) | 2
1055         },
1056         {
1057                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1058                 .name = "Center Playback Switch",
1059                 .info = wm_mute_info,
1060                 .get = wm_mute_get,
1061                 .put = wm_mute_put,
1062                 .private_value = (1 << 8) | 4
1063         },
1064         {
1065                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1066                 .name = "Center Playback Volume",
1067                 .info = wm_vol_info,
1068                 .get = wm_vol_get,
1069                 .put = wm_vol_put,
1070                 .private_value = (1 << 8) | 4
1071         },
1072         {
1073                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1074                 .name = "LFE Playback Switch",
1075                 .info = wm_mute_info,
1076                 .get = wm_mute_get,
1077                 .put = wm_mute_put,
1078                 .private_value = (1 << 8) | 5
1079         },
1080         {
1081                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1082                 .name = "LFE Playback Volume",
1083                 .info = wm_vol_info,
1084                 .get = wm_vol_get,
1085                 .put = wm_vol_put,
1086                 .private_value = (1 << 8) | 5
1087         },
1088         {
1089                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1090                 .name = "Side Playback Switch",
1091                 .info = wm_mute_info,
1092                 .get = wm_mute_get,
1093                 .put = wm_mute_put,
1094                 .private_value = (2 << 8) | 6
1095         },
1096         {
1097                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1098                 .name = "Side Playback Volume",
1099                 .info = wm_vol_info,
1100                 .get = wm_vol_get,
1101                 .put = wm_vol_put,
1102                 .private_value = (2 << 8) | 6
1103         }
1104 };
1105
1106 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
1107         {
1108                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1109                 .name = "PCM Playback Switch",
1110                 .info = wm_pcm_mute_info,
1111                 .get = wm_pcm_mute_get,
1112                 .put = wm_pcm_mute_put
1113         },
1114         {
1115                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1116                 .name = "PCM Playback Volume",
1117                 .info = wm_pcm_vol_info,
1118                 .get = wm_pcm_vol_get,
1119                 .put = wm_pcm_vol_put
1120         },
1121         {
1122                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1123                 .name = "Capture Switch",
1124                 .info = wm_adc_mute_info,
1125                 .get = wm_adc_mute_get,
1126                 .put = wm_adc_mute_put,
1127         },
1128         {
1129                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1130                 .name = "Capture Volume",
1131                 .info = wm_adc_vol_info,
1132                 .get = wm_adc_vol_get,
1133                 .put = wm_adc_vol_put
1134         },
1135         {
1136                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1137                 .name = "Capture Source",
1138                 .info = wm_adc_mux_info,
1139                 .get = wm_adc_mux_get,
1140                 .put = wm_adc_mux_put,
1141                 .private_value = 5
1142         },
1143         {
1144                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1145                 .name = "Headphone Amplifier Switch",
1146                 .info = aureon_hpamp_info,
1147                 .get = aureon_hpamp_get,
1148                 .put = aureon_hpamp_put
1149         },
1150         {
1151                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1152                 .name = "DAC Deemphasis Switch",
1153                 .info = aureon_deemp_info,
1154                 .get = aureon_deemp_get,
1155                 .put = aureon_deemp_put
1156         },
1157         {
1158                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1159                 .name = "ADC Oversampling",
1160                 .info = aureon_oversampling_info,
1161                 .get = aureon_oversampling_get,
1162                 .put = aureon_oversampling_put
1163         },
1164 };
1165
1166 static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
1167         {
1168                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1169                 .name = "AC97 Playback Switch",
1170                 .info = aureon_ac97_mmute_info,
1171                 .get = aureon_ac97_mmute_get,
1172                 .put = aureon_ac97_mmute_put,
1173                 .private_value = AC97_MASTER
1174         },
1175         {
1176                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1177                 .name = "AC97 Playback Volume",
1178                 .info = aureon_ac97_vol_info,
1179                 .get = aureon_ac97_vol_get,
1180                 .put = aureon_ac97_vol_put,
1181                 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1182         },
1183         {
1184                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1185                 .name = "CD Playback Switch",
1186                 .info = aureon_ac97_mute_info,
1187                 .get = aureon_ac97_mute_get,
1188                 .put = aureon_ac97_mute_put,
1189                 .private_value = AC97_CD
1190         },
1191         {
1192                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1193                 .name = "CD Playback Volume",
1194                 .info = aureon_ac97_vol_info,
1195                 .get = aureon_ac97_vol_get,
1196                 .put = aureon_ac97_vol_put,
1197                 .private_value = AC97_CD|AUREON_AC97_STEREO
1198         },
1199         {
1200                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1201                 .name = "Aux Playback Switch",
1202                 .info = aureon_ac97_mute_info,
1203                 .get = aureon_ac97_mute_get,
1204                 .put = aureon_ac97_mute_put,
1205                 .private_value = AC97_AUX,
1206         },
1207         {
1208                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1209                 .name = "Aux Playback Volume",
1210                 .info = aureon_ac97_vol_info,
1211                 .get = aureon_ac97_vol_get,
1212                 .put = aureon_ac97_vol_put,
1213                 .private_value = AC97_AUX|AUREON_AC97_STEREO
1214         },
1215         {
1216                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1217                 .name = "Line Playback Switch",
1218                 .info = aureon_ac97_mute_info,
1219                 .get = aureon_ac97_mute_get,
1220                 .put = aureon_ac97_mute_put,
1221                 .private_value = AC97_LINE
1222         },
1223         {
1224                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1225                 .name = "Line Playback Volume",
1226                 .info = aureon_ac97_vol_info,
1227                 .get = aureon_ac97_vol_get,
1228                 .put = aureon_ac97_vol_put,
1229                 .private_value = AC97_LINE|AUREON_AC97_STEREO
1230         },
1231         {
1232                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1233                 .name = "Mic Playback Switch",
1234                 .info = aureon_ac97_mute_info,
1235                 .get = aureon_ac97_mute_get,
1236                 .put = aureon_ac97_mute_put,
1237                 .private_value = AC97_MIC
1238         },
1239         {
1240                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1241                 .name = "Mic Playback Volume",
1242                 .info = aureon_ac97_vol_info,
1243                 .get = aureon_ac97_vol_get,
1244                 .put = aureon_ac97_vol_put,
1245                 .private_value = AC97_MIC
1246         },
1247         {
1248                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1249                 .name = "Mic Boost",
1250                 .info = aureon_ac97_micboost_info,
1251                 .get = aureon_ac97_micboost_get,
1252                 .put = aureon_ac97_micboost_put
1253         }
1254 };
1255  
1256 static int __devinit aureon_add_controls(ice1712_t *ice)
1257 {
1258         unsigned int i, counts;
1259         int err;
1260
1261         counts = ARRAY_SIZE(aureon_dac_controls);
1262         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1263                 counts -= 2; /* no side */
1264         for (i = 0; i < counts; i++) {
1265                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1266                 if (err < 0)
1267                         return err;
1268         }
1269
1270         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1271                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1272                 if (err < 0)
1273                         return err;
1274         }
1275         
1276         for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1277                 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1278                 if (err < 0)
1279                         return err;
1280         }
1281         
1282         return 0;
1283 }
1284
1285
1286 /*
1287  * initialize the chip
1288  */
1289 static int __devinit aureon_init(ice1712_t *ice)
1290 {
1291         static unsigned short wm_inits_aureon[] = {
1292                 /* These come first to reduce init pop noise */
1293                 0x1b, 0x005,            /* ADC Mux (AC'97 source) */
1294                 0x1c, 0x00B,            /* Out Mux1 (VOUT1 = ADC+AUX, VOUT2 = ADC) */
1295                 0x1d, 0x009,            /* Out Mux2 (VOUT2 = ADC, VOUT3 = ADC) */
1296
1297                 0x18, 0x000,            /* All power-up */
1298
1299                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
1300                 0x17, 0x022,            /* 256fs, slave mode */
1301                 0x00, 0,                /* DAC1 analog mute */
1302                 0x01, 0,                /* DAC2 analog mute */
1303                 0x02, 0,                /* DAC3 analog mute */
1304                 0x03, 0,                /* DAC4 analog mute */
1305                 0x04, 0,                /* DAC5 analog mute */
1306                 0x05, 0,                /* DAC6 analog mute */
1307                 0x06, 0,                /* DAC7 analog mute */
1308                 0x07, 0,                /* DAC8 analog mute */
1309                 0x08, 0x100,            /* master analog mute */
1310                 0x09, 0xff,             /* DAC1 digital full */
1311                 0x0a, 0xff,             /* DAC2 digital full */
1312                 0x0b, 0xff,             /* DAC3 digital full */
1313                 0x0c, 0xff,             /* DAC4 digital full */
1314                 0x0d, 0xff,             /* DAC5 digital full */
1315                 0x0e, 0xff,             /* DAC6 digital full */
1316                 0x0f, 0xff,             /* DAC7 digital full */
1317                 0x10, 0xff,             /* DAC8 digital full */
1318                 0x11, 0x1ff,            /* master digital full */
1319                 0x12, 0x000,            /* phase normal */
1320                 0x13, 0x090,            /* unmute DAC L/R */
1321                 0x14, 0x000,            /* all unmute */
1322                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1323                 0x19, 0x000,            /* -12dB ADC/L */
1324                 0x1a, 0x000,            /* -12dB ADC/R */
1325                 (unsigned short)-1
1326         };
1327         static unsigned short wm_inits_prodigy[] = {
1328
1329                 /* These come first to reduce init pop noise */
1330                 0x1b, 0x000,            /* ADC Mux */
1331                 0x1c, 0x009,            /* Out Mux1 */
1332                 0x1d, 0x009,            /* Out Mux2 */
1333
1334                 0x18, 0x000,            /* All power-up */
1335
1336                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
1337                 0x17, 0x006,            /* 128fs, slave mode */
1338
1339                 0x00, 0,                /* DAC1 analog mute */
1340                 0x01, 0,                /* DAC2 analog mute */
1341                 0x02, 0,                /* DAC3 analog mute */
1342                 0x03, 0,                /* DAC4 analog mute */
1343                 0x04, 0,                /* DAC5 analog mute */
1344                 0x05, 0,                /* DAC6 analog mute */
1345                 0x06, 0,                /* DAC7 analog mute */
1346                 0x07, 0,                /* DAC8 analog mute */
1347                 0x08, 0x100,            /* master analog mute */
1348
1349                 0x09, 0x7f,             /* DAC1 digital full */
1350                 0x0a, 0x7f,             /* DAC2 digital full */
1351                 0x0b, 0x7f,             /* DAC3 digital full */
1352                 0x0c, 0x7f,             /* DAC4 digital full */
1353                 0x0d, 0x7f,             /* DAC5 digital full */
1354                 0x0e, 0x7f,             /* DAC6 digital full */
1355                 0x0f, 0x7f,             /* DAC7 digital full */
1356                 0x10, 0x7f,             /* DAC8 digital full */
1357                 0x11, 0x1FF,            /* master digital full */
1358
1359                 0x12, 0x000,            /* phase normal */
1360                 0x13, 0x090,            /* unmute DAC L/R */
1361                 0x14, 0x000,            /* all unmute */
1362                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1363
1364                 0x19, 0x000,            /* -12dB ADC/L */
1365                 0x1a, 0x000,            /* -12dB ADC/R */
1366                 (unsigned short)-1
1367
1368         };
1369         static unsigned short cs_inits[] = {
1370                 0x0441, /* RUN */
1371                 0x0180, /* no mute, OMCK output on RMCK pin */
1372                 0x0201, /* S/PDIF source on RXP1 */
1373                 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1374                 (unsigned short)-1
1375         };
1376         unsigned int tmp;
1377         unsigned short *p;
1378         unsigned int cscs;
1379         int err, i;
1380
1381         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1382                 ice->num_total_dacs = 6;
1383                 ice->num_total_adcs = 2;
1384         } else {
1385                 /* aureon 7.1 and prodigy 7.1 */
1386                 ice->num_total_dacs = 8;
1387                 ice->num_total_adcs = 2;
1388         }
1389
1390         /* to remeber the register values of CS8415 */
1391         ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
1392         if (! ice->akm)
1393                 return -ENOMEM;
1394         ice->akm_codecs = 1;
1395         
1396         if ((err = aureon_ac97_init(ice)) != 0)
1397                 return err;
1398
1399         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1400                 cscs = PRODIGY_CS8415_CS;
1401         else
1402                 cscs = AUREON_CS8415_CS;
1403
1404         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1405
1406         /* reset the wm codec as the SPI mode */
1407         snd_ice1712_save_gpio_status(ice);
1408         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|
1409                                          cscs|AUREON_HP_SEL));
1410
1411         tmp = snd_ice1712_gpio_read(ice);
1412         tmp &= ~AUREON_WM_RESET;
1413         snd_ice1712_gpio_write(ice, tmp);
1414         udelay(1);
1415         tmp |= AUREON_WM_CS | cscs;
1416         snd_ice1712_gpio_write(ice, tmp);
1417         udelay(1);
1418         tmp |= AUREON_WM_RESET;
1419         snd_ice1712_gpio_write(ice, tmp);
1420         udelay(1);
1421
1422         /* initialize WM8770 codec */
1423         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1424                 p = wm_inits_prodigy;
1425         else
1426                 p = wm_inits_aureon;
1427         for (; *p != (unsigned short)-1; p += 2)
1428                 wm_put(ice, p[0], p[1]);
1429
1430         /* initialize CS8415A codec */
1431         for (p = cs_inits; *p != (unsigned short)-1; p++)
1432                 aureon_spi_write(ice, cscs,
1433                                  *p | 0x200000, 24);
1434
1435         aureon_set_headphone_amp(ice, 1);
1436
1437         snd_ice1712_restore_gpio_status(ice);
1438         
1439         ice->spec.aureon.master[0] = WM_VOL_MUTE;
1440         ice->spec.aureon.master[1] = WM_VOL_MUTE;
1441         for (i = 0; i < ice->num_total_dacs; i++) {
1442                 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1443                 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1444         }
1445
1446         return 0;
1447 }
1448
1449
1450 /*
1451  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1452  * hence the driver needs to sets up it properly.
1453  */
1454
1455 static unsigned char aureon51_eeprom[] __devinitdata = {
1456         0x0a,   /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1457         0x80,   /* ACLINK: I2S */
1458         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1459         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1460         0xff,   /* GPIO_DIR */
1461         0xff,   /* GPIO_DIR1 */
1462         0x5f,   /* GPIO_DIR2 */
1463         0x00,   /* GPIO_MASK */
1464         0x00,   /* GPIO_MASK1 */
1465         0x00,   /* GPIO_MASK2 */
1466         0x00,   /* GPIO_STATE */
1467         0x00,   /* GPIO_STATE1 */
1468         0x00,   /* GPIO_STATE2 */
1469 };
1470
1471 static unsigned char aureon71_eeprom[] __devinitdata = {
1472         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1473         0x80,   /* ACLINK: I2S */
1474         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1475         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1476         0xff,   /* GPIO_DIR */
1477         0xff,   /* GPIO_DIR1 */
1478         0x5f,   /* GPIO_DIR2 */
1479         0x00,   /* GPIO_MASK */
1480         0x00,   /* GPIO_MASK1 */
1481         0x00,   /* GPIO_MASK2 */
1482         0x00,   /* GPIO_STATE */
1483         0x00,   /* GPIO_STATE1 */
1484         0x00,   /* GPIO_STATE2 */
1485 };
1486
1487 static unsigned char prodigy71_eeprom[] __devinitdata = {
1488         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1489         0x80,   /* ACLINK: I2S */
1490         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1491         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1492         0xff,   /* GPIO_DIR */
1493         0xff,   /* GPIO_DIR1 */
1494         0x5f,   /* GPIO_DIR2 */
1495         0x00,   /* GPIO_MASK */
1496         0x00,   /* GPIO_MASK1 */
1497         0x00,   /* GPIO_MASK2 */
1498         0x00,   /* GPIO_STATE */
1499         0x00,   /* GPIO_STATE1 */
1500         0x00,   /* GPIO_STATE2 */
1501 };
1502
1503 /* entry point */
1504 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1505         {
1506                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1507                 .name = "Terratec Aureon 5.1-Sky",
1508                 .model = "aureon51",
1509                 .chip_init = aureon_init,
1510                 .build_controls = aureon_add_controls,
1511                 .eeprom_size = sizeof(aureon51_eeprom),
1512                 .eeprom_data = aureon51_eeprom,
1513                 .driver = "Aureon51",
1514         },
1515         {
1516                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1517                 .name = "Terratec Aureon 7.1-Space",
1518                 .model = "aureon71",
1519                 .chip_init = aureon_init,
1520                 .build_controls = aureon_add_controls,
1521                 .eeprom_size = sizeof(aureon71_eeprom),
1522                 .eeprom_data = aureon71_eeprom,
1523                 .driver = "Aureon71",
1524         },
1525         {
1526                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1527                 .name = "Terratec Aureon 7.1-Universe",
1528                 /* model not needed - identical with 7.1-Space */
1529                 .chip_init = aureon_init,
1530                 .build_controls = aureon_add_controls,
1531                 .eeprom_size = sizeof(aureon71_eeprom),
1532                 .eeprom_data = aureon71_eeprom,
1533                 .driver = "Aureon71",
1534         },
1535         {
1536                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1537                 .name = "Audiotrak Prodigy 7.1",
1538                 .model = "prodigy71",
1539                 .chip_init = aureon_init,
1540                 .build_controls = aureon_add_controls,
1541                 .eeprom_size = sizeof(prodigy71_eeprom),
1542                 .eeprom_data = prodigy71_eeprom,
1543                 .driver = "Prodigy71", /* should be identical with Aureon71 */
1544         },
1545         { } /* terminator */
1546 };