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