Merge branch 'master'
[linux-2.6] / 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  * - DAC digital volumes are not implemented in the mixer.
31  *   if they show better response than DAC analog volumes, we can use them
32  *   instead.
33  *
34  *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
36  *
37  *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
38  *       added 64x/128x oversampling switch (should be 64x only for 96khz)
39  *       fixed some recording labels (still need to check the rest)
40  *       recording is working probably thanks to correct wm8770 initialization
41  *
42  *   version 0.5: Initial release:
43  *           working: analog output, mixer, headphone amplifier switch
44  *       not working: prety much everything else, at least i could verify that
45  *                    we have no digital output, no capture, pretty bad clicks and poops
46  *                    on mixer switch and other coll stuff.
47  *
48  */      
49
50 #include <sound/driver.h>
51 #include <asm/io.h>
52 #include <linux/delay.h>
53 #include <linux/interrupt.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <sound/core.h>
57
58 #include "ice1712.h"
59 #include "envy24ht.h"
60 #include "aureon.h"
61
62 /* WM8770 registers */
63 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
64 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
65 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
66 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
67 #define WM_PHASE_SWAP           0x12    /* DAC phase */
68 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
69 #define WM_MUTE                 0x14    /* mute controls */
70 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
71 #define WM_INT_CTRL             0x16    /* interface control */
72 #define WM_MASTER               0x17    /* master clock and mode */
73 #define WM_POWERDOWN            0x18    /* power-down controls */
74 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
75 #define WM_ADC_MUX              0x1b    /* input MUX */
76 #define WM_OUT_MUX1             0x1c    /* output MUX */
77 #define WM_OUT_MUX2             0x1e    /* output MUX */
78 #define WM_RESET                0x1f    /* software reset */
79
80 /* CS8415A registers */
81 #define CS8415_CTRL1    0x01
82 #define CS8415_CTRL2    0x02
83 #define CS8415_QSUB             0x14
84 #define CS8415_RATIO    0x1E
85 #define CS8415_C_BUFFER 0x20
86 #define CS8415_ID               0x7F
87
88 static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
89         unsigned int tmp;
90
91         /* Send address to XILINX chip */
92         tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
93         snd_ice1712_gpio_write(ice, tmp);
94         udelay(10);
95         tmp |= AUREON_AC97_ADDR;
96         snd_ice1712_gpio_write(ice, tmp);
97         udelay(10);
98         tmp &= ~AUREON_AC97_ADDR;
99         snd_ice1712_gpio_write(ice, tmp);
100         udelay(10);     
101
102         /* Send low-order byte to XILINX chip */
103         tmp &= ~AUREON_AC97_DATA_MASK;
104         tmp |= val & AUREON_AC97_DATA_MASK;
105         snd_ice1712_gpio_write(ice, tmp);
106         udelay(10);
107         tmp |= AUREON_AC97_DATA_LOW;
108         snd_ice1712_gpio_write(ice, tmp);
109         udelay(10);
110         tmp &= ~AUREON_AC97_DATA_LOW;
111         snd_ice1712_gpio_write(ice, tmp);
112         udelay(10);
113         
114         /* Send high-order byte to XILINX chip */
115         tmp &= ~AUREON_AC97_DATA_MASK;
116         tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
117
118         snd_ice1712_gpio_write(ice, tmp);
119         udelay(10);
120         tmp |= AUREON_AC97_DATA_HIGH;
121         snd_ice1712_gpio_write(ice, tmp);
122         udelay(10);
123         tmp &= ~AUREON_AC97_DATA_HIGH;
124         snd_ice1712_gpio_write(ice, tmp);
125         udelay(10);
126         
127         /* Instruct XILINX chip to parse the data to the STAC9744 chip */
128         tmp |= AUREON_AC97_COMMIT;
129         snd_ice1712_gpio_write(ice, tmp);
130         udelay(10);
131         tmp &= ~AUREON_AC97_COMMIT;
132         snd_ice1712_gpio_write(ice, tmp);
133         udelay(10);
134         
135         /* Store the data in out private buffer */
136         ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
137 }
138
139 static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
140 {
141        return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
142 }
143
144 /*
145  * Initialize STAC9744 chip
146  */
147 static int aureon_ac97_init (ice1712_t *ice) {
148         int i;
149         static unsigned short ac97_defaults[] = {
150                 0x00, 0x9640,
151                 0x02, 0x8000,
152                 0x04, 0x8000,
153                 0x06, 0x8000,
154                 0x0C, 0x8008,
155                 0x0E, 0x8008,
156                 0x10, 0x8808,
157                 0x12, 0x8808,
158                 0x14, 0x8808,
159                 0x16, 0x8808,
160                 0x18, 0x8808,
161                 0x1C, 0x8000,
162                 0x26, 0x000F,
163                 0x28, 0x0201,
164                 0x2C, 0xBB80,
165                 0x32, 0xBB80,
166                 0x7C, 0x8384,
167                 0x7E, 0x7644,
168                 (unsigned short)-1
169         };
170         unsigned int tmp;
171
172         /* Cold reset */
173         tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
174         snd_ice1712_gpio_write(ice, tmp);
175         udelay(3);
176         
177         tmp &= ~AUREON_AC97_RESET;
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         memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
186         for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
187                 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
188                 
189         aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
190
191         return 0;
192 }
193
194 #define AUREON_AC97_STEREO      0x80
195
196 /*
197  * AC'97 volume controls
198  */
199 static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
200 {
201         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
202         uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
203         uinfo->value.integer.min = 0;
204         uinfo->value.integer.max = 31;
205         return 0;
206 }
207
208 static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
209 {
210         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
211         unsigned short vol;
212
213         down(&ice->gpio_mutex);
214
215         vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
216         ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
217         if (kcontrol->private_value & AUREON_AC97_STEREO)
218                 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
219
220         up(&ice->gpio_mutex);
221         return 0;
222 }
223
224 static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
225 {
226         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
227         unsigned short ovol, nvol;
228         int change;
229         
230         snd_ice1712_save_gpio_status(ice);
231
232         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
233         nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
234         if (kcontrol->private_value & AUREON_AC97_STEREO)
235                 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
236         nvol |= ovol & ~0x1F1F;
237         
238         if ((change = (ovol != nvol)))
239                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
240
241         snd_ice1712_restore_gpio_status(ice);
242
243         return change;          
244 }
245
246 /*
247  * AC'97 mute controls
248  */
249 #define aureon_ac97_mute_info   aureon_mono_bool_info
250
251 static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
252 {
253         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
254
255         down(&ice->gpio_mutex);
256
257         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
258
259         up(&ice->gpio_mutex);
260         return 0;
261 }
262
263 static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
264 {
265         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
266         unsigned short ovol, nvol;
267         int change;
268
269         snd_ice1712_save_gpio_status(ice);
270         
271         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
272         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
273         
274         if ((change = (ovol != nvol)))
275                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
276                 
277         snd_ice1712_restore_gpio_status(ice);
278
279         return change;
280 }
281
282 /*
283  * AC'97 mute controls
284  */
285 #define aureon_ac97_micboost_info       aureon_mono_bool_info
286
287 static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
288 {
289         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
290
291         down(&ice->gpio_mutex);
292
293         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
294
295         up(&ice->gpio_mutex);
296         return 0;
297 }
298
299 static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
300 {
301         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
302         unsigned short ovol, nvol;
303         int change;
304
305         snd_ice1712_save_gpio_status(ice);
306         
307         ovol = aureon_ac97_read(ice, AC97_MIC);
308         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
309         
310         if ((change = (ovol != nvol)))
311                 aureon_ac97_write(ice, AC97_MIC, nvol);
312                 
313         snd_ice1712_restore_gpio_status(ice);
314
315         return change;
316 }
317
318 /*
319  * write data in the SPI mode
320  */
321 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
322 {
323         unsigned int tmp;
324         int i;
325
326         tmp = snd_ice1712_gpio_read(ice);
327
328         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
329                                          AUREON_WM_CS|AUREON_CS8415_CS));
330         tmp |= AUREON_WM_RW;
331         tmp &= ~cs;
332         snd_ice1712_gpio_write(ice, tmp);
333         udelay(1);
334
335         for (i = bits - 1; i >= 0; i--) {
336                 tmp &= ~AUREON_SPI_CLK;
337                 snd_ice1712_gpio_write(ice, tmp);
338                 udelay(1);
339                 if (data & (1 << i))
340                         tmp |= AUREON_SPI_MOSI;
341                 else
342                         tmp &= ~AUREON_SPI_MOSI;
343                 snd_ice1712_gpio_write(ice, tmp);
344                 udelay(1);
345                 tmp |= AUREON_SPI_CLK;
346                 snd_ice1712_gpio_write(ice, tmp);
347                 udelay(1);
348         }
349
350         tmp &= ~AUREON_SPI_CLK;
351         tmp |= cs;
352         snd_ice1712_gpio_write(ice, tmp);
353         udelay(1);
354         tmp |= AUREON_SPI_CLK;
355         snd_ice1712_gpio_write(ice, tmp);
356         udelay(1);
357 }
358
359 /*
360  * Read data in SPI mode
361  */
362 static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
363         int i, j;
364         unsigned int tmp;
365
366         tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
367         snd_ice1712_gpio_write(ice, tmp);
368         tmp &= ~cs;
369         snd_ice1712_gpio_write(ice, tmp);
370         udelay(1);
371
372         for (i=bits-1; i>=0; i--) {
373                 if (data & (1 << i))
374                         tmp |= AUREON_SPI_MOSI;
375                 else
376                         tmp &= ~AUREON_SPI_MOSI;
377                 snd_ice1712_gpio_write(ice, tmp);
378                 udelay(1);
379
380                 tmp |= AUREON_SPI_CLK;
381                 snd_ice1712_gpio_write(ice, tmp);
382                 udelay(1);
383
384                 tmp &= ~AUREON_SPI_CLK;
385                 snd_ice1712_gpio_write(ice, tmp);
386                 udelay(1);
387         }
388
389         for (j=0; j<size; j++) {
390                 unsigned char outdata = 0;
391                 for (i=7; i>=0; i--) {
392                         tmp = snd_ice1712_gpio_read(ice);
393                         outdata <<= 1;
394                         outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
395                         udelay(1);
396
397                         tmp |= AUREON_SPI_CLK;
398                         snd_ice1712_gpio_write(ice, tmp);
399                         udelay(1);
400
401                         tmp &= ~AUREON_SPI_CLK;
402                         snd_ice1712_gpio_write(ice, tmp);
403                         udelay(1);
404                 }
405                 buffer[j] = outdata;
406         }
407
408         tmp |= cs;
409         snd_ice1712_gpio_write(ice, tmp);
410 }
411
412 static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) {
413         unsigned char val;
414         aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
415         aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
416         return val;
417 }
418
419 static void aureon_cs8415_read(ice1712_t *ice, int reg, unsigned char *buffer, int size) {
420         aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
421         aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
422 }
423
424 static void aureon_cs8415_put(ice1712_t *ice, int reg, unsigned char val) {
425         aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
426 }
427
428 /*
429  * get the current register value of WM codec
430  */
431 static unsigned short wm_get(ice1712_t *ice, int reg)
432 {
433         reg <<= 1;
434         return ((unsigned short)ice->akm[0].images[reg] << 8) |
435                 ice->akm[0].images[reg + 1];
436 }
437
438 /*
439  * set the register value of WM codec
440  */
441 static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
442 {
443         aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
444 }
445
446 /*
447  * set the register value of WM codec and remember it
448  */
449 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
450 {
451         wm_put_nocache(ice, reg, val);
452         reg <<= 1;
453         ice->akm[0].images[reg] = val >> 8;
454         ice->akm[0].images[reg + 1] = val;
455 }
456
457 /*
458  */
459 static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
460 {
461         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
462         uinfo->count = 1;
463         uinfo->value.integer.min = 0;
464         uinfo->value.integer.max = 1;
465         return 0;
466 }
467
468 /*
469  * AC'97 master playback mute controls (Mute on WM8770 chip)
470  */
471 #define aureon_ac97_mmute_info  aureon_mono_bool_info
472
473 static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
474 {
475         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
476
477         down(&ice->gpio_mutex);
478
479         ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
480
481         up(&ice->gpio_mutex);
482         return 0;
483 }
484
485 static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
486         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
487         unsigned short ovol, nvol;
488         int change;
489         
490         snd_ice1712_save_gpio_status(ice);
491         
492         ovol = wm_get(ice, WM_OUT_MUX1);
493         nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
494         if ((change = (ovol != nvol)))
495                 wm_put(ice, WM_OUT_MUX1, nvol);
496                 
497         snd_ice1712_restore_gpio_status(ice);
498
499         return change;
500 }
501
502 /*
503  * Logarithmic volume values for WM8770
504  * Computed as 20 * Log10(255 / x)
505  */
506 static unsigned char wm_vol[256] = {
507         127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
508         23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
509         17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
510         13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
511         11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
512         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,
513         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,
514         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,
515         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,
516         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,
517         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,
518         0, 0
519 };
520
521 #define WM_VOL_MAX      (sizeof(wm_vol) - 1)
522 #define WM_VOL_MUTE     0x8000
523
524 static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
525 {
526         unsigned char nvol;
527         
528         if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
529                 nvol = 0;
530         else
531                 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
532         
533         wm_put(ice, index, nvol);
534         wm_put_nocache(ice, index, 0x180 | nvol);
535 }
536
537 /*
538  * DAC mute control
539  */
540 #define wm_pcm_mute_info        aureon_mono_bool_info
541
542 static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
543 {
544         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
545
546         down(&ice->gpio_mutex);
547         ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
548         up(&ice->gpio_mutex);
549         return 0;
550 }
551
552 static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
553 {
554         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
555         unsigned short nval, oval;
556         int change;
557
558         snd_ice1712_save_gpio_status(ice);
559         oval = wm_get(ice, WM_MUTE);
560         nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
561         if ((change = (nval != oval)))
562                 wm_put(ice, WM_MUTE, nval);
563         snd_ice1712_restore_gpio_status(ice);
564
565         return change;
566 }
567
568 /*
569  * Master volume attenuation mixer control
570  */
571 static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
572 {
573         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
574         uinfo->count = 2;
575         uinfo->value.integer.min = 0;
576         uinfo->value.integer.max = WM_VOL_MAX;
577         return 0;
578 }
579
580 static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
581 {
582         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
583         int i;
584         for (i=0; i<2; i++)
585                 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
586         return 0;
587 }
588
589 static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
590 {
591         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
592         int ch, change = 0;
593
594         snd_ice1712_save_gpio_status(ice);
595         for (ch = 0; ch < 2; ch++) {
596                 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
597                         int dac;
598                         ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
599                         ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
600                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
601                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
602                                            ice->spec.aureon.vol[dac + ch],
603                                            ice->spec.aureon.master[ch]);
604                         change = 1;
605                 }
606         }
607         snd_ice1712_restore_gpio_status(ice);
608         return change;
609 }
610
611 /*
612  * DAC volume attenuation mixer control
613  */
614 static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
615 {
616         int voices = kcontrol->private_value >> 8;
617         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
618         uinfo->count = voices;
619         uinfo->value.integer.min = 0;           /* mute (-101dB) */
620         uinfo->value.integer.max = 0x7F;        /* 0dB */
621         return 0;
622 }
623
624 static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
625 {
626         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
627         int i, ofs, voices;
628
629         voices = kcontrol->private_value >> 8;
630         ofs = kcontrol->private_value & 0xff;
631         for (i = 0; i < voices; i++)
632                 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
633         return 0;
634 }
635
636 static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
637 {
638         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
639         int i, idx, ofs, voices;
640         int change = 0;
641
642         voices = kcontrol->private_value >> 8;
643         ofs = kcontrol->private_value & 0xff;
644         snd_ice1712_save_gpio_status(ice);
645         for (i = 0; i < voices; i++) {
646                 idx  = WM_DAC_ATTEN + ofs + i;
647                 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
648                         ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
649                         ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
650                         wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
651                                    ice->spec.aureon.master[i]);
652                         change = 1;
653                 }
654         }
655         snd_ice1712_restore_gpio_status(ice);
656         return change;
657 }
658
659 /*
660  * WM8770 mute control
661  */
662 static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
663         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
664         uinfo->count = kcontrol->private_value >> 8;
665         uinfo->value.integer.min = 0;
666         uinfo->value.integer.max = 1;
667         return 0;
668 }
669
670 static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
671 {
672         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
673         int voices, ofs, i;
674         
675         voices = kcontrol->private_value >> 8;
676         ofs = kcontrol->private_value & 0xFF;
677
678         for (i = 0; i < voices; i++)
679                 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
680         return 0;
681 }
682
683 static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
684 {
685         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
686         int change = 0, voices, ofs, i;
687
688         voices = kcontrol->private_value >> 8;
689         ofs = kcontrol->private_value & 0xFF;
690
691         snd_ice1712_save_gpio_status(ice);
692         for (i = 0; i < voices; i++) {
693                 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
694                 if (ucontrol->value.integer.value[i] != val) {
695                         ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
696                         ice->spec.aureon.vol[ofs + i] |=
697                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
698                         wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
699                                    ice->spec.aureon.master[i]);
700                         change = 1;
701                 }
702         }
703         snd_ice1712_restore_gpio_status(ice);
704
705         return change;
706 }
707
708 /*
709  * WM8770 master mute control
710  */
711 static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
712         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
713         uinfo->count = 2;
714         uinfo->value.integer.min = 0;
715         uinfo->value.integer.max = 1;
716         return 0;
717 }
718
719 static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
720 {
721         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
722         
723         ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
724         ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
725         return 0;
726 }
727
728 static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
729 {
730         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
731         int change = 0, i;
732
733         snd_ice1712_save_gpio_status(ice);
734         for (i = 0; i < 2; i++) {
735                 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
736                 if (ucontrol->value.integer.value[i] != val) {
737                         int dac;
738                         ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
739                         ice->spec.aureon.master[i] |=
740                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
741                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
742                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
743                                            ice->spec.aureon.vol[dac + i],
744                                            ice->spec.aureon.master[i]);
745                         change = 1;
746                 }
747         }
748         snd_ice1712_restore_gpio_status(ice);
749
750         return change;
751 }
752
753 /* digital master volume */
754 #define PCM_0dB 0xff
755 #define PCM_RES 128     /* -64dB */
756 #define PCM_MIN (PCM_0dB - PCM_RES)
757 static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
758 {
759         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
760         uinfo->count = 1;
761         uinfo->value.integer.min = 0;           /* mute (-64dB) */
762         uinfo->value.integer.max = PCM_RES;     /* 0dB */
763         return 0;
764 }
765
766 static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
767 {
768         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
769         unsigned short val;
770
771         down(&ice->gpio_mutex);
772         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
773         val = val > PCM_MIN ? (val - PCM_MIN) : 0;
774         ucontrol->value.integer.value[0] = val;
775         up(&ice->gpio_mutex);
776         return 0;
777 }
778
779 static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
780 {
781         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
782         unsigned short ovol, nvol;
783         int change = 0;
784
785         snd_ice1712_save_gpio_status(ice);
786         nvol = ucontrol->value.integer.value[0];
787         nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
788         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
789         if (ovol != nvol) {
790                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
791                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
792                 change = 1;
793         }
794         snd_ice1712_restore_gpio_status(ice);
795         return change;
796 }
797
798 /*
799  * ADC mute control
800  */
801 static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
802 {
803         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
804         uinfo->count = 2;
805         uinfo->value.integer.min = 0;
806         uinfo->value.integer.max = 1;
807         return 0;
808 }
809
810 static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
811 {
812         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
813         unsigned short val;
814         int i;
815
816         down(&ice->gpio_mutex);
817         for (i = 0; i < 2; i++) {
818                 val = wm_get(ice, WM_ADC_GAIN + i);
819                 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
820         }
821         up(&ice->gpio_mutex);
822         return 0;
823 }
824
825 static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
826 {
827         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
828         unsigned short new, old;
829         int i, change = 0;
830
831         snd_ice1712_save_gpio_status(ice);
832         for (i = 0; i < 2; i++) {
833                 old = wm_get(ice, WM_ADC_GAIN + i);
834                 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
835                 if (new != old) {
836                         wm_put(ice, WM_ADC_GAIN + i, new);
837                         change = 1;
838                 }
839         }
840         snd_ice1712_restore_gpio_status(ice);
841
842         return change;
843 }
844
845 /*
846  * ADC gain mixer control
847  */
848 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
849 {
850         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
851         uinfo->count = 2;
852         uinfo->value.integer.min = 0;           /* -12dB */
853         uinfo->value.integer.max = 0x1f;        /* 19dB */
854         return 0;
855 }
856
857 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
858 {
859         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
860         int i, idx;
861         unsigned short vol;
862
863         down(&ice->gpio_mutex);
864         for (i = 0; i < 2; i++) {
865                 idx = WM_ADC_GAIN + i;
866                 vol = wm_get(ice, idx) & 0x1f;
867                 ucontrol->value.integer.value[i] = vol;
868         }
869         up(&ice->gpio_mutex);
870         return 0;
871 }
872
873 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
874 {
875         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
876         int i, idx;
877         unsigned short ovol, nvol;
878         int change = 0;
879
880         snd_ice1712_save_gpio_status(ice);
881         for (i = 0; i < 2; i++) {
882                 idx  = WM_ADC_GAIN + i;
883                 nvol = ucontrol->value.integer.value[i];
884                 ovol = wm_get(ice, idx);
885                 if ((ovol & 0x1f) != nvol) {
886                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
887                         change = 1;
888                 }
889         }
890         snd_ice1712_restore_gpio_status(ice);
891         return change;
892 }
893
894 /*
895  * ADC input mux mixer control
896  */
897 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
898 {
899         static char *texts[] = {
900                 "CD",           //AIN1
901                 "Aux",          //AIN2
902                 "Line",         //AIN3
903                 "Mic",          //AIN4
904                 "AC97"          //AIN5
905         };
906         static char *universe_texts[] = {
907                 "Aux1",         //AIN1
908                 "CD",           //AIN2
909                 "Phono",        //AIN3
910                 "Line",         //AIN4
911                 "Aux2",         //AIN5
912                 "Mic",          //AIN6
913                 "Aux3",         //AIN7
914                 "AC97"          //AIN8
915         };
916         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
917
918         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
919         uinfo->count = 2;
920         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
921                 uinfo->value.enumerated.items = 8;
922                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
923                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
924                 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
925         }
926         else {
927                 uinfo->value.enumerated.items = 5;
928                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
929                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
930                 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
931         }
932         return 0;
933 }
934
935 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
936 {
937         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
938         unsigned short val;
939
940         down(&ice->gpio_mutex);
941         val = wm_get(ice, WM_ADC_MUX);
942         ucontrol->value.integer.value[0] = val & 7;
943         ucontrol->value.integer.value[1] = (val >> 4) & 7;
944         up(&ice->gpio_mutex);
945         return 0;
946 }
947
948 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
949 {
950         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
951         unsigned short oval, nval;
952         int change;
953
954         snd_ice1712_save_gpio_status(ice);
955         oval = wm_get(ice, WM_ADC_MUX);
956         nval = oval & ~0x77;
957         nval |= ucontrol->value.integer.value[0] & 7;
958         nval |= (ucontrol->value.integer.value[1] & 7) << 4;
959         change = (oval != nval);
960         if (change)
961                 wm_put(ice, WM_ADC_MUX, nval);
962         snd_ice1712_restore_gpio_status(ice);
963         return change;
964 }
965
966 /*
967  * CS8415 Input mux
968  */
969 static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
970 {
971         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
972         static char *aureon_texts[] = {
973                 "CD",           //RXP0
974                 "Optical"       //RXP1
975         };
976         static char *prodigy_texts[] = {
977                 "CD",
978                 "Coax"
979         };
980         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
981         uinfo->count = 1;
982         uinfo->value.enumerated.items = 2;
983         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
984                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
985         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
986                 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
987         else
988                 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
989         return 0;
990 }
991
992 static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
993 {
994         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
995
996         //snd_ice1712_save_gpio_status(ice);
997         //val = aureon_cs8415_get(ice, CS8415_CTRL2);
998         ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
999         //snd_ice1712_restore_gpio_status(ice);
1000         return 0;
1001 }
1002
1003 static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
1004 {
1005         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1006         unsigned short oval, nval;
1007         int change;
1008
1009         snd_ice1712_save_gpio_status(ice);
1010         oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1011         nval = oval & ~0x07;
1012         nval |= ucontrol->value.integer.value[0] & 7;
1013         change = (oval != nval);
1014         if (change)
1015                 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1016         snd_ice1712_restore_gpio_status(ice);
1017         ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
1018         return change;
1019 }
1020
1021 static int aureon_cs8415_rate_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1022 {
1023         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1024         uinfo->count = 1;
1025         uinfo->value.integer.min = 0;
1026         uinfo->value.integer.max = 192000;
1027         return 0;
1028 }
1029
1030 static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1031 {
1032         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1033         unsigned char ratio;
1034         ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1035         ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1036         return 0;
1037 }
1038
1039 /*
1040  * CS8415A Mute
1041  */
1042 static int aureon_cs8415_mute_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1043 {
1044         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1045         uinfo->count = 1;
1046         return 0;
1047 }
1048
1049 static int aureon_cs8415_mute_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1050 {
1051         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1052         snd_ice1712_save_gpio_status(ice);
1053         ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1054         snd_ice1712_restore_gpio_status(ice);
1055         return 0;
1056 }
1057
1058 static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1059 {
1060         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1061         unsigned char oval, nval;
1062         int change;
1063         snd_ice1712_save_gpio_status(ice);
1064         oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1065         if (ucontrol->value.integer.value[0])
1066                 nval = oval & ~0x20;
1067         else
1068                 nval = oval | 0x20;
1069         if ((change = (oval != nval)))
1070                 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1071         snd_ice1712_restore_gpio_status(ice);
1072         return change;
1073 }
1074
1075 /*
1076  * CS8415A Q-Sub info
1077  */
1078 static int aureon_cs8415_qsub_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1079         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1080         uinfo->count = 10;
1081         return 0;
1082 }
1083
1084 static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1085         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1086         
1087         snd_ice1712_save_gpio_status(ice);
1088         aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1089         snd_ice1712_restore_gpio_status(ice);
1090
1091         return 0;
1092 }
1093
1094 static int aureon_cs8415_spdif_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1095         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1096         uinfo->count = 1;
1097         return 0;
1098 }
1099
1100 static int aureon_cs8415_mask_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1101         memset(ucontrol->value.iec958.status, 0xFF, 24);
1102         return 0;
1103 }
1104
1105 static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1106         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1107
1108         snd_ice1712_save_gpio_status(ice);
1109         aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1110         snd_ice1712_restore_gpio_status(ice);
1111         return 0;
1112 }
1113
1114 /*
1115  * Headphone Amplifier
1116  */
1117 static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
1118 {
1119         unsigned int tmp, tmp2;
1120
1121         tmp2 = tmp = snd_ice1712_gpio_read(ice);
1122         if (enable)
1123                 tmp |= AUREON_HP_SEL;
1124         else
1125                 tmp &= ~ AUREON_HP_SEL;
1126         if (tmp != tmp2) {
1127                 snd_ice1712_gpio_write(ice, tmp);
1128                 return 1;
1129         }
1130         return 0;
1131 }
1132
1133 static int aureon_get_headphone_amp(ice1712_t *ice)
1134 {
1135         unsigned int tmp = snd_ice1712_gpio_read(ice);
1136
1137         return ( tmp & AUREON_HP_SEL )!= 0;
1138 }
1139
1140 #define aureon_hpamp_info       aureon_mono_bool_info
1141
1142 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1143 {
1144         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1145
1146         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1147         return 0;
1148 }
1149
1150
1151 static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1152 {
1153         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1154
1155         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1156 }
1157
1158 /*
1159  * Deemphasis
1160  */
1161
1162 #define aureon_deemp_info       aureon_mono_bool_info
1163
1164 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1165 {
1166         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1167         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1168         return 0;
1169 }
1170
1171 static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1172 {
1173         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1174         int temp, temp2;
1175         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1176         if (ucontrol->value.integer.value[0])
1177                 temp |= 0xf;
1178         else
1179                 temp &= ~0xf;
1180         if (temp != temp2) {
1181                 wm_put(ice, WM_DAC_CTRL2, temp);
1182                 return 1;
1183         }
1184         return 0;
1185 }
1186
1187 /*
1188  * ADC Oversampling
1189  */
1190 static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
1191 {
1192         static char *texts[2] = { "128x", "64x" };
1193
1194         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1195         uinfo->count = 1;
1196         uinfo->value.enumerated.items = 2;
1197
1198         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1199                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1200         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1201
1202         return 0;
1203 }
1204
1205 static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1206 {
1207         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1208         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1209         return 0;
1210 }
1211
1212 static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1213 {
1214         int temp, temp2;
1215         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1216
1217         temp2 = temp = wm_get(ice, WM_MASTER);
1218
1219         if (ucontrol->value.enumerated.item[0])
1220                 temp |= 0x8;
1221         else
1222                 temp &= ~0x8;
1223
1224         if (temp != temp2) {
1225                 wm_put(ice, WM_MASTER, temp);
1226                 return 1;
1227         }
1228         return 0;
1229 }
1230
1231 /*
1232  * mixers
1233  */
1234
1235 static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
1236         {
1237                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1238                 .name = "Master Playback Switch",
1239                 .info = wm_master_mute_info,
1240                 .get = wm_master_mute_get,
1241                 .put = wm_master_mute_put
1242         },
1243         {
1244                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1245                 .name = "Master Playback Volume",
1246                 .info = wm_master_vol_info,
1247                 .get = wm_master_vol_get,
1248                 .put = wm_master_vol_put
1249         },
1250         {
1251                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1252                 .name = "Front Playback Switch",
1253                 .info = wm_mute_info,
1254                 .get = wm_mute_get,
1255                 .put = wm_mute_put,
1256                 .private_value = (2 << 8) | 0
1257         },
1258         {
1259                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1260                 .name = "Front Playback Volume",
1261                 .info = wm_vol_info,
1262                 .get = wm_vol_get,
1263                 .put = wm_vol_put,
1264                 .private_value = (2 << 8) | 0
1265         },
1266         {
1267                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1268                 .name = "Rear Playback Switch",
1269                 .info = wm_mute_info,
1270                 .get = wm_mute_get,
1271                 .put = wm_mute_put,
1272                 .private_value = (2 << 8) | 2
1273         },
1274         {
1275                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276                 .name = "Rear Playback Volume",
1277                 .info = wm_vol_info,
1278                 .get = wm_vol_get,
1279                 .put = wm_vol_put,
1280                 .private_value = (2 << 8) | 2
1281         },
1282         {
1283                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1284                 .name = "Center Playback Switch",
1285                 .info = wm_mute_info,
1286                 .get = wm_mute_get,
1287                 .put = wm_mute_put,
1288                 .private_value = (1 << 8) | 4
1289         },
1290         {
1291                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1292                 .name = "Center Playback Volume",
1293                 .info = wm_vol_info,
1294                 .get = wm_vol_get,
1295                 .put = wm_vol_put,
1296                 .private_value = (1 << 8) | 4
1297         },
1298         {
1299                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1300                 .name = "LFE Playback Switch",
1301                 .info = wm_mute_info,
1302                 .get = wm_mute_get,
1303                 .put = wm_mute_put,
1304                 .private_value = (1 << 8) | 5
1305         },
1306         {
1307                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308                 .name = "LFE Playback Volume",
1309                 .info = wm_vol_info,
1310                 .get = wm_vol_get,
1311                 .put = wm_vol_put,
1312                 .private_value = (1 << 8) | 5
1313         },
1314         {
1315                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1316                 .name = "Side Playback Switch",
1317                 .info = wm_mute_info,
1318                 .get = wm_mute_get,
1319                 .put = wm_mute_put,
1320                 .private_value = (2 << 8) | 6
1321         },
1322         {
1323                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1324                 .name = "Side Playback Volume",
1325                 .info = wm_vol_info,
1326                 .get = wm_vol_get,
1327                 .put = wm_vol_put,
1328                 .private_value = (2 << 8) | 6
1329         }
1330 };
1331
1332 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
1333         {
1334                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1335                 .name = "PCM Playback Switch",
1336                 .info = wm_pcm_mute_info,
1337                 .get = wm_pcm_mute_get,
1338                 .put = wm_pcm_mute_put
1339         },
1340         {
1341                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1342                 .name = "PCM Playback Volume",
1343                 .info = wm_pcm_vol_info,
1344                 .get = wm_pcm_vol_get,
1345                 .put = wm_pcm_vol_put
1346         },
1347         {
1348                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1349                 .name = "Capture Switch",
1350                 .info = wm_adc_mute_info,
1351                 .get = wm_adc_mute_get,
1352                 .put = wm_adc_mute_put,
1353         },
1354         {
1355                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1356                 .name = "Capture Volume",
1357                 .info = wm_adc_vol_info,
1358                 .get = wm_adc_vol_get,
1359                 .put = wm_adc_vol_put
1360         },
1361         {
1362                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1363                 .name = "Capture Source",
1364                 .info = wm_adc_mux_info,
1365                 .get = wm_adc_mux_get,
1366                 .put = wm_adc_mux_put,
1367                 .private_value = 5
1368         },
1369         {
1370                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1371                 .name = "External Amplifier",
1372                 .info = aureon_hpamp_info,
1373                 .get = aureon_hpamp_get,
1374                 .put = aureon_hpamp_put
1375         },
1376         {
1377                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1378                 .name = "DAC Deemphasis Switch",
1379                 .info = aureon_deemp_info,
1380                 .get = aureon_deemp_get,
1381                 .put = aureon_deemp_put
1382         },
1383         {
1384                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1385                 .name = "ADC Oversampling",
1386                 .info = aureon_oversampling_info,
1387                 .get = aureon_oversampling_get,
1388                 .put = aureon_oversampling_put
1389         }
1390 };
1391
1392 static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
1393         {
1394                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395                 .name = "AC97 Playback Switch",
1396                 .info = aureon_ac97_mmute_info,
1397                 .get = aureon_ac97_mmute_get,
1398                 .put = aureon_ac97_mmute_put,
1399                 .private_value = AC97_MASTER
1400         },
1401         {
1402                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1403                 .name = "AC97 Playback Volume",
1404                 .info = aureon_ac97_vol_info,
1405                 .get = aureon_ac97_vol_get,
1406                 .put = aureon_ac97_vol_put,
1407                 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1408         },
1409         {
1410                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1411                 .name = "CD Playback Switch",
1412                 .info = aureon_ac97_mute_info,
1413                 .get = aureon_ac97_mute_get,
1414                 .put = aureon_ac97_mute_put,
1415                 .private_value = AC97_CD
1416         },
1417         {
1418                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419                 .name = "CD Playback Volume",
1420                 .info = aureon_ac97_vol_info,
1421                 .get = aureon_ac97_vol_get,
1422                 .put = aureon_ac97_vol_put,
1423                 .private_value = AC97_CD|AUREON_AC97_STEREO
1424         },
1425         {
1426                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1427                 .name = "Aux Playback Switch",
1428                 .info = aureon_ac97_mute_info,
1429                 .get = aureon_ac97_mute_get,
1430                 .put = aureon_ac97_mute_put,
1431                 .private_value = AC97_AUX,
1432         },
1433         {
1434                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1435                 .name = "Aux Playback Volume",
1436                 .info = aureon_ac97_vol_info,
1437                 .get = aureon_ac97_vol_get,
1438                 .put = aureon_ac97_vol_put,
1439                 .private_value = AC97_AUX|AUREON_AC97_STEREO
1440         },
1441         {
1442                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443                 .name = "Line Playback Switch",
1444                 .info = aureon_ac97_mute_info,
1445                 .get = aureon_ac97_mute_get,
1446                 .put = aureon_ac97_mute_put,
1447                 .private_value = AC97_LINE
1448         },
1449         {
1450                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451                 .name = "Line Playback Volume",
1452                 .info = aureon_ac97_vol_info,
1453                 .get = aureon_ac97_vol_get,
1454                 .put = aureon_ac97_vol_put,
1455                 .private_value = AC97_LINE|AUREON_AC97_STEREO
1456         },
1457         {
1458                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1459                 .name = "Mic Playback Switch",
1460                 .info = aureon_ac97_mute_info,
1461                 .get = aureon_ac97_mute_get,
1462                 .put = aureon_ac97_mute_put,
1463                 .private_value = AC97_MIC
1464         },
1465         {
1466                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467                 .name = "Mic Playback Volume",
1468                 .info = aureon_ac97_vol_info,
1469                 .get = aureon_ac97_vol_get,
1470                 .put = aureon_ac97_vol_put,
1471                 .private_value = AC97_MIC
1472         },
1473         {
1474                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475                 .name = "Mic Boost (+20dB)",
1476                 .info = aureon_ac97_micboost_info,
1477                 .get = aureon_ac97_micboost_get,
1478                 .put = aureon_ac97_micboost_put
1479         }
1480 };
1481
1482 static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = {
1483         {
1484                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485                 .name = "AC97 Playback Switch",
1486                 .info = aureon_ac97_mmute_info,
1487                 .get = aureon_ac97_mmute_get,
1488                 .put = aureon_ac97_mmute_put,
1489                 .private_value = AC97_MASTER
1490         },
1491         {
1492                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1493                 .name = "AC97 Playback Volume",
1494                 .info = aureon_ac97_vol_info,
1495                 .get = aureon_ac97_vol_get,
1496                 .put = aureon_ac97_vol_put,
1497                 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1498         },
1499         {
1500                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1501                 .name = "CD Playback Switch",
1502                 .info = aureon_ac97_mute_info,
1503                 .get = aureon_ac97_mute_get,
1504                 .put = aureon_ac97_mute_put,
1505                 .private_value = AC97_AUX
1506         },
1507         {
1508                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509                 .name = "CD Playback Volume",
1510                 .info = aureon_ac97_vol_info,
1511                 .get = aureon_ac97_vol_get,
1512                 .put = aureon_ac97_vol_put,
1513                 .private_value = AC97_AUX|AUREON_AC97_STEREO
1514         },
1515         {
1516                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517                 .name = "Phono Playback Switch",
1518                 .info = aureon_ac97_mute_info,
1519                 .get = aureon_ac97_mute_get,
1520                 .put = aureon_ac97_mute_put,
1521                 .private_value = AC97_CD,
1522         },
1523         {
1524                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1525                 .name = "Phono Playback Volume",
1526                 .info = aureon_ac97_vol_info,
1527                 .get = aureon_ac97_vol_get,
1528                 .put = aureon_ac97_vol_put,
1529                 .private_value = AC97_CD|AUREON_AC97_STEREO
1530         },
1531         {
1532                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533                 .name = "Line Playback Switch",
1534                 .info = aureon_ac97_mute_info,
1535                 .get = aureon_ac97_mute_get,
1536                 .put = aureon_ac97_mute_put,
1537                 .private_value = AC97_LINE
1538         },
1539         {
1540                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541                 .name = "Line Playback Volume",
1542                 .info = aureon_ac97_vol_info,
1543                 .get = aureon_ac97_vol_get,
1544                 .put = aureon_ac97_vol_put,
1545                 .private_value = AC97_LINE|AUREON_AC97_STEREO
1546         },
1547         {
1548                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549                 .name = "Mic Playback Switch",
1550                 .info = aureon_ac97_mute_info,
1551                 .get = aureon_ac97_mute_get,
1552                 .put = aureon_ac97_mute_put,
1553                 .private_value = AC97_MIC
1554         },
1555         {
1556                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557                 .name = "Mic Playback Volume",
1558                 .info = aureon_ac97_vol_info,
1559                 .get = aureon_ac97_vol_get,
1560                 .put = aureon_ac97_vol_put,
1561                 .private_value = AC97_MIC
1562         },
1563         {
1564                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1565                 .name = "Mic Boost (+20dB)",
1566                 .info = aureon_ac97_micboost_info,
1567                 .get = aureon_ac97_micboost_get,
1568                 .put = aureon_ac97_micboost_put
1569         },
1570         {
1571                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572                 .name = "Aux Playback Switch",
1573                 .info = aureon_ac97_mute_info,
1574                 .get = aureon_ac97_mute_get,
1575                 .put = aureon_ac97_mute_put,
1576                 .private_value = AC97_VIDEO,
1577         },
1578         {
1579                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1580                 .name = "Aux Playback Volume",
1581                 .info = aureon_ac97_vol_info,
1582                 .get = aureon_ac97_vol_get,
1583                 .put = aureon_ac97_vol_put,
1584                 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1585         }
1586 };
1587
1588         
1589 static snd_kcontrol_new_t cs8415_controls[] __devinitdata = {
1590         {
1591                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1593                 .info = aureon_cs8415_mute_info,
1594                 .get = aureon_cs8415_mute_get,
1595                 .put = aureon_cs8415_mute_put
1596         },
1597         {
1598                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1599                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1600                 .info = aureon_cs8415_mux_info,
1601                 .get = aureon_cs8415_mux_get,
1602                 .put = aureon_cs8415_mux_put,
1603         },
1604         {
1605                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1606                 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1607                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1608                 .info = aureon_cs8415_qsub_info,
1609                 .get = aureon_cs8415_qsub_get,
1610         },
1611         {
1612                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1613                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1614                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1615                 .info = aureon_cs8415_spdif_info,
1616                 .get = aureon_cs8415_mask_get
1617         },
1618         {
1619                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1620                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1621                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1622                 .info = aureon_cs8415_spdif_info,
1623                 .get = aureon_cs8415_spdif_get
1624         },
1625         {
1626                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1627                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1628                 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1629                 .info = aureon_cs8415_rate_info,
1630                 .get = aureon_cs8415_rate_get
1631         }
1632 };
1633
1634  
1635 static int __devinit aureon_add_controls(ice1712_t *ice)
1636 {
1637         unsigned int i, counts;
1638         int err;
1639
1640         counts = ARRAY_SIZE(aureon_dac_controls);
1641         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1642                 counts -= 2; /* no side */
1643         for (i = 0; i < counts; i++) {
1644                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1645                 if (err < 0)
1646                         return err;
1647         }
1648
1649         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1650                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1651                 if (err < 0)
1652                         return err;
1653         }
1654         
1655         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1656                 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1657                         err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1658                         if (err < 0)
1659                                 return err;
1660                 }
1661         }
1662         else {
1663                 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1664                         err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1665                         if (err < 0)
1666                                 return err;
1667                 }
1668         }
1669
1670         {
1671                 unsigned char id;
1672                 snd_ice1712_save_gpio_status(ice);
1673                 id = aureon_cs8415_get(ice, CS8415_ID);
1674                 if (id != 0x41)
1675                         snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1676                 else if ((id & 0x0F) != 0x01)
1677                         snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1678                 else {
1679                         for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1680                                 snd_kcontrol_t *kctl;
1681                                 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1682                                 if (err < 0)
1683                                         return err;
1684                                 if (i > 1)
1685                                         kctl->id.device = ice->pcm->device;
1686                         }
1687                 }
1688                 snd_ice1712_restore_gpio_status(ice);
1689         }
1690         
1691         return 0;
1692 }
1693
1694
1695 /*
1696  * initialize the chip
1697  */
1698 static int __devinit aureon_init(ice1712_t *ice)
1699 {
1700         static unsigned short wm_inits_aureon[] = {
1701                 /* These come first to reduce init pop noise */
1702                 0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1703                 0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1704                 0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1705
1706                 0x18, 0x000,            /* All power-up */
1707
1708                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
1709                 0x17, 0x022,            /* 256fs, slave mode */
1710                 0x00, 0,                /* DAC1 analog mute */
1711                 0x01, 0,                /* DAC2 analog mute */
1712                 0x02, 0,                /* DAC3 analog mute */
1713                 0x03, 0,                /* DAC4 analog mute */
1714                 0x04, 0,                /* DAC5 analog mute */
1715                 0x05, 0,                /* DAC6 analog mute */
1716                 0x06, 0,                /* DAC7 analog mute */
1717                 0x07, 0,                /* DAC8 analog mute */
1718                 0x08, 0x100,            /* master analog mute */
1719                 0x09, 0xff,             /* DAC1 digital full */
1720                 0x0a, 0xff,             /* DAC2 digital full */
1721                 0x0b, 0xff,             /* DAC3 digital full */
1722                 0x0c, 0xff,             /* DAC4 digital full */
1723                 0x0d, 0xff,             /* DAC5 digital full */
1724                 0x0e, 0xff,             /* DAC6 digital full */
1725                 0x0f, 0xff,             /* DAC7 digital full */
1726                 0x10, 0xff,             /* DAC8 digital full */
1727                 0x11, 0x1ff,            /* master digital full */
1728                 0x12, 0x000,            /* phase normal */
1729                 0x13, 0x090,            /* unmute DAC L/R */
1730                 0x14, 0x000,            /* all unmute */
1731                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1732                 0x19, 0x000,            /* -12dB ADC/L */
1733                 0x1a, 0x000,            /* -12dB ADC/R */
1734                 (unsigned short)-1
1735         };
1736         static unsigned short wm_inits_prodigy[] = {
1737
1738                 /* These come first to reduce init pop noise */
1739                 0x1b, 0x000,            /* ADC Mux */
1740                 0x1c, 0x009,            /* Out Mux1 */
1741                 0x1d, 0x009,            /* Out Mux2 */
1742
1743                 0x18, 0x000,            /* All power-up */
1744
1745                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
1746                 0x17, 0x006,            /* 128fs, slave mode */
1747
1748                 0x00, 0,                /* DAC1 analog mute */
1749                 0x01, 0,                /* DAC2 analog mute */
1750                 0x02, 0,                /* DAC3 analog mute */
1751                 0x03, 0,                /* DAC4 analog mute */
1752                 0x04, 0,                /* DAC5 analog mute */
1753                 0x05, 0,                /* DAC6 analog mute */
1754                 0x06, 0,                /* DAC7 analog mute */
1755                 0x07, 0,                /* DAC8 analog mute */
1756                 0x08, 0x100,            /* master analog mute */
1757
1758                 0x09, 0x7f,             /* DAC1 digital full */
1759                 0x0a, 0x7f,             /* DAC2 digital full */
1760                 0x0b, 0x7f,             /* DAC3 digital full */
1761                 0x0c, 0x7f,             /* DAC4 digital full */
1762                 0x0d, 0x7f,             /* DAC5 digital full */
1763                 0x0e, 0x7f,             /* DAC6 digital full */
1764                 0x0f, 0x7f,             /* DAC7 digital full */
1765                 0x10, 0x7f,             /* DAC8 digital full */
1766                 0x11, 0x1FF,            /* master digital full */
1767
1768                 0x12, 0x000,            /* phase normal */
1769                 0x13, 0x090,            /* unmute DAC L/R */
1770                 0x14, 0x000,            /* all unmute */
1771                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1772
1773                 0x19, 0x000,            /* -12dB ADC/L */
1774                 0x1a, 0x000,            /* -12dB ADC/R */
1775                 (unsigned short)-1
1776
1777         };
1778         static unsigned short cs_inits[] = {
1779                 0x0441, /* RUN */
1780                 0x0180, /* no mute, OMCK output on RMCK pin */
1781                 0x0201, /* S/PDIF source on RXP1 */
1782                 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1783                 (unsigned short)-1
1784         };
1785         unsigned int tmp;
1786         unsigned short *p;
1787         int err, i;
1788
1789         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1790                 ice->num_total_dacs = 6;
1791                 ice->num_total_adcs = 2;
1792         } else {
1793                 /* aureon 7.1 and prodigy 7.1 */
1794                 ice->num_total_dacs = 8;
1795                 ice->num_total_adcs = 2;
1796         }
1797
1798         /* to remeber the register values of CS8415 */
1799         ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
1800         if (! ice->akm)
1801                 return -ENOMEM;
1802         ice->akm_codecs = 1;
1803         
1804         if ((err = aureon_ac97_init(ice)) != 0)
1805                 return err;
1806
1807         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1808
1809         /* reset the wm codec as the SPI mode */
1810         snd_ice1712_save_gpio_status(ice);
1811         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1812
1813         tmp = snd_ice1712_gpio_read(ice);
1814         tmp &= ~AUREON_WM_RESET;
1815         snd_ice1712_gpio_write(ice, tmp);
1816         udelay(1);
1817         tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1818         snd_ice1712_gpio_write(ice, tmp);
1819         udelay(1);
1820         tmp |= AUREON_WM_RESET;
1821         snd_ice1712_gpio_write(ice, tmp);
1822         udelay(1);
1823
1824         /* initialize WM8770 codec */
1825         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1826                 p = wm_inits_prodigy;
1827         else
1828                 p = wm_inits_aureon;
1829         for (; *p != (unsigned short)-1; p += 2)
1830                 wm_put(ice, p[0], p[1]);
1831
1832         /* initialize CS8415A codec */
1833         for (p = cs_inits; *p != (unsigned short)-1; p++)
1834                 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
1835         ice->spec.aureon.cs8415_mux = 1;
1836
1837         aureon_set_headphone_amp(ice, 1);
1838
1839         snd_ice1712_restore_gpio_status(ice);
1840         
1841         ice->spec.aureon.master[0] = WM_VOL_MUTE;
1842         ice->spec.aureon.master[1] = WM_VOL_MUTE;
1843         for (i = 0; i < ice->num_total_dacs; i++) {
1844                 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1845                 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1846         }
1847
1848         return 0;
1849 }
1850
1851
1852 /*
1853  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1854  * hence the driver needs to sets up it properly.
1855  */
1856
1857 static unsigned char aureon51_eeprom[] __devinitdata = {
1858         0x0a,   /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1859         0x80,   /* ACLINK: I2S */
1860         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1861         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1862         0xff,   /* GPIO_DIR */
1863         0xff,   /* GPIO_DIR1 */
1864         0x5f,   /* GPIO_DIR2 */
1865         0x00,   /* GPIO_MASK */
1866         0x00,   /* GPIO_MASK1 */
1867         0x00,   /* GPIO_MASK2 */
1868         0x00,   /* GPIO_STATE */
1869         0x00,   /* GPIO_STATE1 */
1870         0x00,   /* GPIO_STATE2 */
1871 };
1872
1873 static unsigned char aureon71_eeprom[] __devinitdata = {
1874         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1875         0x80,   /* ACLINK: I2S */
1876         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1877         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1878         0xff,   /* GPIO_DIR */
1879         0xff,   /* GPIO_DIR1 */
1880         0x5f,   /* GPIO_DIR2 */
1881         0x00,   /* GPIO_MASK */
1882         0x00,   /* GPIO_MASK1 */
1883         0x00,   /* GPIO_MASK2 */
1884         0x00,   /* GPIO_STATE */
1885         0x00,   /* GPIO_STATE1 */
1886         0x00,   /* GPIO_STATE2 */
1887 };
1888
1889 static unsigned char prodigy71_eeprom[] __devinitdata = {
1890         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1891         0x80,   /* ACLINK: I2S */
1892         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1893         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1894         0xff,   /* GPIO_DIR */
1895         0xff,   /* GPIO_DIR1 */
1896         0x5f,   /* GPIO_DIR2 */
1897         0x00,   /* GPIO_MASK */
1898         0x00,   /* GPIO_MASK1 */
1899         0x00,   /* GPIO_MASK2 */
1900         0x00,   /* GPIO_STATE */
1901         0x00,   /* GPIO_STATE1 */
1902         0x00,   /* GPIO_STATE2 */
1903 };
1904
1905 /* entry point */
1906 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1907         {
1908                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1909                 .name = "Terratec Aureon 5.1-Sky",
1910                 .model = "aureon51",
1911                 .chip_init = aureon_init,
1912                 .build_controls = aureon_add_controls,
1913                 .eeprom_size = sizeof(aureon51_eeprom),
1914                 .eeprom_data = aureon51_eeprom,
1915                 .driver = "Aureon51",
1916         },
1917         {
1918                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1919                 .name = "Terratec Aureon 7.1-Space",
1920                 .model = "aureon71",
1921                 .chip_init = aureon_init,
1922                 .build_controls = aureon_add_controls,
1923                 .eeprom_size = sizeof(aureon71_eeprom),
1924                 .eeprom_data = aureon71_eeprom,
1925                 .driver = "Aureon71",
1926         },
1927         {
1928                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1929                 .name = "Terratec Aureon 7.1-Universe",
1930                 .model = "universe",
1931                 .chip_init = aureon_init,
1932                 .build_controls = aureon_add_controls,
1933                 .eeprom_size = sizeof(aureon71_eeprom),
1934                 .eeprom_data = aureon71_eeprom,
1935                 .driver = "Aureon71Universe",
1936         },
1937         {
1938                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1939                 .name = "Audiotrak Prodigy 7.1",
1940                 .model = "prodigy71",
1941                 .chip_init = aureon_init,
1942                 .build_controls = aureon_add_controls,
1943                 .eeprom_size = sizeof(prodigy71_eeprom),
1944                 .eeprom_data = prodigy71_eeprom,
1945                 .driver = "Prodigy71", /* should be identical with Aureon71 */
1946         },
1947         { } /* terminator */
1948 };