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