625a9a32b7c7a3aaecd954753da006975a71730a
[linux-2.6.git] / sound / pci / ice1712 / aureon.c
1 /*
2  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  *   Lowlevel functions for Terratec Aureon cards
5  *
6  *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  *
23  * NOTES:
24  *
25  * - we reuse the 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   aureon_mono_bool_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       aureon_mono_bool_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 static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
625 {
626         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
627         uinfo->count = 1;
628         uinfo->value.integer.min = 0;
629         uinfo->value.integer.max = 1;
630         return 0;
631 }
632
633 /*
634  * AC'97 master playback mute controls (Mute on WM8770 chip)
635  */
636 #define aureon_ac97_mmute_info  aureon_mono_bool_info
637
638 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
639 {
640         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
641
642         mutex_lock(&ice->gpio_mutex);
643
644         ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
645
646         mutex_unlock(&ice->gpio_mutex);
647         return 0;
648 }
649
650 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
651         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
652         unsigned short ovol, nvol;
653         int change;
654         
655         snd_ice1712_save_gpio_status(ice);
656         
657         ovol = wm_get(ice, WM_OUT_MUX1);
658         nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
659         if ((change = (ovol != nvol)))
660                 wm_put(ice, WM_OUT_MUX1, nvol);
661                 
662         snd_ice1712_restore_gpio_status(ice);
663
664         return change;
665 }
666
667 static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
668 static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
669 static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
670 static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
671 static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
672
673 /*
674  * Logarithmic volume values for WM8770
675  * Computed as 20 * Log10(255 / x)
676  */
677 static const unsigned char wm_vol[256] = {
678         127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
679         23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
680         17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
681         13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
682         11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
683         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,
684         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,
685         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,
686         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,
687         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,
688         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,
689         0, 0
690 };
691
692 #define WM_VOL_MAX      (sizeof(wm_vol) - 1)
693 #define WM_VOL_MUTE     0x8000
694
695 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
696 {
697         unsigned char nvol;
698         
699         if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
700                 nvol = 0;
701         else
702                 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
703         
704         wm_put(ice, index, nvol);
705         wm_put_nocache(ice, index, 0x180 | nvol);
706 }
707
708 /*
709  * DAC mute control
710  */
711 #define wm_pcm_mute_info        aureon_mono_bool_info
712
713 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
714 {
715         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
716
717         mutex_lock(&ice->gpio_mutex);
718         ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
719         mutex_unlock(&ice->gpio_mutex);
720         return 0;
721 }
722
723 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
724 {
725         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
726         unsigned short nval, oval;
727         int change;
728
729         snd_ice1712_save_gpio_status(ice);
730         oval = wm_get(ice, WM_MUTE);
731         nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
732         if ((change = (nval != oval)))
733                 wm_put(ice, WM_MUTE, nval);
734         snd_ice1712_restore_gpio_status(ice);
735
736         return change;
737 }
738
739 /*
740  * Master volume attenuation mixer control
741  */
742 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
743 {
744         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
745         uinfo->count = 2;
746         uinfo->value.integer.min = 0;
747         uinfo->value.integer.max = WM_VOL_MAX;
748         return 0;
749 }
750
751 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
752 {
753         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
754         int i;
755         for (i=0; i<2; i++)
756                 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
757         return 0;
758 }
759
760 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
761 {
762         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
763         int ch, change = 0;
764
765         snd_ice1712_save_gpio_status(ice);
766         for (ch = 0; ch < 2; ch++) {
767                 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
768                         int dac;
769                         ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
770                         ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
771                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
772                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
773                                            ice->spec.aureon.vol[dac + ch],
774                                            ice->spec.aureon.master[ch]);
775                         change = 1;
776                 }
777         }
778         snd_ice1712_restore_gpio_status(ice);
779         return change;
780 }
781
782 /*
783  * DAC volume attenuation mixer control
784  */
785 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
786 {
787         int voices = kcontrol->private_value >> 8;
788         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
789         uinfo->count = voices;
790         uinfo->value.integer.min = 0;           /* mute (-101dB) */
791         uinfo->value.integer.max = 0x7F;        /* 0dB */
792         return 0;
793 }
794
795 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
796 {
797         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
798         int i, ofs, voices;
799
800         voices = kcontrol->private_value >> 8;
801         ofs = kcontrol->private_value & 0xff;
802         for (i = 0; i < voices; i++)
803                 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
804         return 0;
805 }
806
807 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
808 {
809         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
810         int i, idx, ofs, voices;
811         int change = 0;
812
813         voices = kcontrol->private_value >> 8;
814         ofs = kcontrol->private_value & 0xff;
815         snd_ice1712_save_gpio_status(ice);
816         for (i = 0; i < voices; i++) {
817                 idx  = WM_DAC_ATTEN + ofs + i;
818                 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
819                         ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
820                         ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[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 static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
883         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
884         uinfo->count = 2;
885         uinfo->value.integer.min = 0;
886         uinfo->value.integer.max = 1;
887         return 0;
888 }
889
890 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
891 {
892         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
893         
894         ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
895         ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
896         return 0;
897 }
898
899 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
900 {
901         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
902         int change = 0, i;
903
904         snd_ice1712_save_gpio_status(ice);
905         for (i = 0; i < 2; i++) {
906                 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
907                 if (ucontrol->value.integer.value[i] != val) {
908                         int dac;
909                         ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
910                         ice->spec.aureon.master[i] |=
911                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
912                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
913                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
914                                            ice->spec.aureon.vol[dac + i],
915                                            ice->spec.aureon.master[i]);
916                         change = 1;
917                 }
918         }
919         snd_ice1712_restore_gpio_status(ice);
920
921         return change;
922 }
923
924 /* digital master volume */
925 #define PCM_0dB 0xff
926 #define PCM_RES 128     /* -64dB */
927 #define PCM_MIN (PCM_0dB - PCM_RES)
928 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
929 {
930         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
931         uinfo->count = 1;
932         uinfo->value.integer.min = 0;           /* mute (-64dB) */
933         uinfo->value.integer.max = PCM_RES;     /* 0dB */
934         return 0;
935 }
936
937 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
938 {
939         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
940         unsigned short val;
941
942         mutex_lock(&ice->gpio_mutex);
943         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
944         val = val > PCM_MIN ? (val - PCM_MIN) : 0;
945         ucontrol->value.integer.value[0] = val;
946         mutex_unlock(&ice->gpio_mutex);
947         return 0;
948 }
949
950 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
951 {
952         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
953         unsigned short ovol, nvol;
954         int change = 0;
955
956         snd_ice1712_save_gpio_status(ice);
957         nvol = ucontrol->value.integer.value[0];
958         nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
959         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
960         if (ovol != nvol) {
961                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
962                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
963                 change = 1;
964         }
965         snd_ice1712_restore_gpio_status(ice);
966         return change;
967 }
968
969 /*
970  * ADC mute control
971  */
972 static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
973 {
974         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
975         uinfo->count = 2;
976         uinfo->value.integer.min = 0;
977         uinfo->value.integer.max = 1;
978         return 0;
979 }
980
981 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
982 {
983         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
984         unsigned short val;
985         int i;
986
987         mutex_lock(&ice->gpio_mutex);
988         for (i = 0; i < 2; i++) {
989                 val = wm_get(ice, WM_ADC_GAIN + i);
990                 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
991         }
992         mutex_unlock(&ice->gpio_mutex);
993         return 0;
994 }
995
996 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
997 {
998         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
999         unsigned short new, old;
1000         int i, change = 0;
1001
1002         snd_ice1712_save_gpio_status(ice);
1003         for (i = 0; i < 2; i++) {
1004                 old = wm_get(ice, WM_ADC_GAIN + i);
1005                 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1006                 if (new != old) {
1007                         wm_put(ice, WM_ADC_GAIN + i, new);
1008                         change = 1;
1009                 }
1010         }
1011         snd_ice1712_restore_gpio_status(ice);
1012
1013         return change;
1014 }
1015
1016 /*
1017  * ADC gain mixer control
1018  */
1019 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1020 {
1021         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1022         uinfo->count = 2;
1023         uinfo->value.integer.min = 0;           /* -12dB */
1024         uinfo->value.integer.max = 0x1f;        /* 19dB */
1025         return 0;
1026 }
1027
1028 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1029 {
1030         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031         int i, idx;
1032         unsigned short vol;
1033
1034         mutex_lock(&ice->gpio_mutex);
1035         for (i = 0; i < 2; i++) {
1036                 idx = WM_ADC_GAIN + i;
1037                 vol = wm_get(ice, idx) & 0x1f;
1038                 ucontrol->value.integer.value[i] = vol;
1039         }
1040         mutex_unlock(&ice->gpio_mutex);
1041         return 0;
1042 }
1043
1044 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045 {
1046         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1047         int i, idx;
1048         unsigned short ovol, nvol;
1049         int change = 0;
1050
1051         snd_ice1712_save_gpio_status(ice);
1052         for (i = 0; i < 2; i++) {
1053                 idx  = WM_ADC_GAIN + i;
1054                 nvol = ucontrol->value.integer.value[i];
1055                 ovol = wm_get(ice, idx);
1056                 if ((ovol & 0x1f) != nvol) {
1057                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058                         change = 1;
1059                 }
1060         }
1061         snd_ice1712_restore_gpio_status(ice);
1062         return change;
1063 }
1064
1065 /*
1066  * ADC input mux mixer control
1067  */
1068 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1069 {
1070         static const char * const texts[] = {
1071                 "CD",           //AIN1
1072                 "Aux",          //AIN2
1073                 "Line",         //AIN3
1074                 "Mic",          //AIN4
1075                 "AC97"          //AIN5
1076         };
1077         static const char * const universe_texts[] = {
1078                 "Aux1",         //AIN1
1079                 "CD",           //AIN2
1080                 "Phono",        //AIN3
1081                 "Line",         //AIN4
1082                 "Aux2",         //AIN5
1083                 "Mic",          //AIN6
1084                 "Aux3",         //AIN7
1085                 "AC97"          //AIN8
1086         };
1087         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1088
1089         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1090         uinfo->count = 2;
1091         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1092                 uinfo->value.enumerated.items = 8;
1093                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1094                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1095                 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1096         }
1097         else {
1098                 uinfo->value.enumerated.items = 5;
1099                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1100                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1101                 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1102         }
1103         return 0;
1104 }
1105
1106 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1107 {
1108         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1109         unsigned short val;
1110
1111         mutex_lock(&ice->gpio_mutex);
1112         val = wm_get(ice, WM_ADC_MUX);
1113         ucontrol->value.enumerated.item[0] = val & 7;
1114         ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1115         mutex_unlock(&ice->gpio_mutex);
1116         return 0;
1117 }
1118
1119 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1120 {
1121         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1122         unsigned short oval, nval;
1123         int change;
1124
1125         snd_ice1712_save_gpio_status(ice);
1126         oval = wm_get(ice, WM_ADC_MUX);
1127         nval = oval & ~0x77;
1128         nval |= ucontrol->value.enumerated.item[0] & 7;
1129         nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1130         change = (oval != nval);
1131         if (change)
1132                 wm_put(ice, WM_ADC_MUX, nval);
1133         snd_ice1712_restore_gpio_status(ice);
1134         return change;
1135 }
1136
1137 /*
1138  * CS8415 Input mux
1139  */
1140 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1141 {
1142         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1143         static const char * const aureon_texts[] = {
1144                 "CD",           //RXP0
1145                 "Optical"       //RXP1
1146         };
1147         static const char * const prodigy_texts[] = {
1148                 "CD",
1149                 "Coax"
1150         };
1151         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1152         uinfo->count = 1;
1153         uinfo->value.enumerated.items = 2;
1154         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1155                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1156         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1157                 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1158         else
1159                 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1160         return 0;
1161 }
1162
1163 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1164 {
1165         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1166
1167         //snd_ice1712_save_gpio_status(ice);
1168         //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1169         ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1170         //snd_ice1712_restore_gpio_status(ice);
1171         return 0;
1172 }
1173
1174 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1175 {
1176         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1177         unsigned short oval, nval;
1178         int change;
1179
1180         snd_ice1712_save_gpio_status(ice);
1181         oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1182         nval = oval & ~0x07;
1183         nval |= ucontrol->value.enumerated.item[0] & 7;
1184         change = (oval != nval);
1185         if (change)
1186                 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1187         snd_ice1712_restore_gpio_status(ice);
1188         ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1189         return change;
1190 }
1191
1192 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1193 {
1194         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1195         uinfo->count = 1;
1196         uinfo->value.integer.min = 0;
1197         uinfo->value.integer.max = 192000;
1198         return 0;
1199 }
1200
1201 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1202 {
1203         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1204         unsigned char ratio;
1205         ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1206         ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1207         return 0;
1208 }
1209
1210 /*
1211  * CS8415A Mute
1212  */
1213 static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1214 {
1215         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1216         uinfo->count = 1;
1217         return 0;
1218 }
1219
1220 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1221 {
1222         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1223         snd_ice1712_save_gpio_status(ice);
1224         ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1225         snd_ice1712_restore_gpio_status(ice);
1226         return 0;
1227 }
1228
1229 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1230 {
1231         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1232         unsigned char oval, nval;
1233         int change;
1234         snd_ice1712_save_gpio_status(ice);
1235         oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1236         if (ucontrol->value.integer.value[0])
1237                 nval = oval & ~0x20;
1238         else
1239                 nval = oval | 0x20;
1240         if ((change = (oval != nval)))
1241                 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1242         snd_ice1712_restore_gpio_status(ice);
1243         return change;
1244 }
1245
1246 /*
1247  * CS8415A Q-Sub info
1248  */
1249 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1250         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1251         uinfo->count = 10;
1252         return 0;
1253 }
1254
1255 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1256         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1257         
1258         snd_ice1712_save_gpio_status(ice);
1259         aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1260         snd_ice1712_restore_gpio_status(ice);
1261
1262         return 0;
1263 }
1264
1265 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1266         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1267         uinfo->count = 1;
1268         return 0;
1269 }
1270
1271 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1272         memset(ucontrol->value.iec958.status, 0xFF, 24);
1273         return 0;
1274 }
1275
1276 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1277         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1278
1279         snd_ice1712_save_gpio_status(ice);
1280         aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1281         snd_ice1712_restore_gpio_status(ice);
1282         return 0;
1283 }
1284
1285 /*
1286  * Headphone Amplifier
1287  */
1288 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1289 {
1290         unsigned int tmp, tmp2;
1291
1292         tmp2 = tmp = snd_ice1712_gpio_read(ice);
1293         if (enable)
1294                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1295                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1296                         tmp |= AUREON_HP_SEL;
1297                 else
1298                         tmp |= PRODIGY_HP_SEL;
1299         else
1300                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1301                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1302                         tmp &= ~ AUREON_HP_SEL;
1303                 else
1304                         tmp &= ~ PRODIGY_HP_SEL;
1305         if (tmp != tmp2) {
1306                 snd_ice1712_gpio_write(ice, tmp);
1307                 return 1;
1308         }
1309         return 0;
1310 }
1311
1312 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1313 {
1314         unsigned int tmp = snd_ice1712_gpio_read(ice);
1315
1316         return ( tmp & AUREON_HP_SEL )!= 0;
1317 }
1318
1319 #define aureon_hpamp_info       aureon_mono_bool_info
1320
1321 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1322 {
1323         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1324
1325         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1326         return 0;
1327 }
1328
1329
1330 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1331 {
1332         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1333
1334         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1335 }
1336
1337 /*
1338  * Deemphasis
1339  */
1340
1341 #define aureon_deemp_info       aureon_mono_bool_info
1342
1343 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1344 {
1345         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1346         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1347         return 0;
1348 }
1349
1350 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1351 {
1352         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1353         int temp, temp2;
1354         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1355         if (ucontrol->value.integer.value[0])
1356                 temp |= 0xf;
1357         else
1358                 temp &= ~0xf;
1359         if (temp != temp2) {
1360                 wm_put(ice, WM_DAC_CTRL2, temp);
1361                 return 1;
1362         }
1363         return 0;
1364 }
1365
1366 /*
1367  * ADC Oversampling
1368  */
1369 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1370 {
1371         static const char * const texts[2] = { "128x", "64x"    };
1372
1373         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1374         uinfo->count = 1;
1375         uinfo->value.enumerated.items = 2;
1376
1377         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1378                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1379         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1380
1381         return 0;
1382 }
1383
1384 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1385 {
1386         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1387         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1388         return 0;
1389 }
1390
1391 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1392 {
1393         int temp, temp2;
1394         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1395
1396         temp2 = temp = wm_get(ice, WM_MASTER);
1397
1398         if (ucontrol->value.enumerated.item[0])
1399                 temp |= 0x8;
1400         else
1401                 temp &= ~0x8;
1402
1403         if (temp != temp2) {
1404                 wm_put(ice, WM_MASTER, temp);
1405                 return 1;
1406         }
1407         return 0;
1408 }
1409
1410 /*
1411  * mixers
1412  */
1413
1414 static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1415         {
1416                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1417                 .name = "Master Playback Switch",
1418                 .info = wm_master_mute_info,
1419                 .get = wm_master_mute_get,
1420                 .put = wm_master_mute_put
1421         },
1422         {
1423                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1424                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1425                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1426                 .name = "Master Playback Volume",
1427                 .info = wm_master_vol_info,
1428                 .get = wm_master_vol_get,
1429                 .put = wm_master_vol_put,
1430                 .tlv = { .p = db_scale_wm_dac }
1431         },
1432         {
1433                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1434                 .name = "Front Playback Switch",
1435                 .info = wm_mute_info,
1436                 .get = wm_mute_get,
1437                 .put = wm_mute_put,
1438                 .private_value = (2 << 8) | 0
1439         },
1440         {
1441                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1442                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1443                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1444                 .name = "Front Playback Volume",
1445                 .info = wm_vol_info,
1446                 .get = wm_vol_get,
1447                 .put = wm_vol_put,
1448                 .private_value = (2 << 8) | 0,
1449                 .tlv = { .p = db_scale_wm_dac }
1450         },
1451         {
1452                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1453                 .name = "Rear Playback Switch",
1454                 .info = wm_mute_info,
1455                 .get = wm_mute_get,
1456                 .put = wm_mute_put,
1457                 .private_value = (2 << 8) | 2
1458         },
1459         {
1460                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1461                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1462                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1463                 .name = "Rear Playback Volume",
1464                 .info = wm_vol_info,
1465                 .get = wm_vol_get,
1466                 .put = wm_vol_put,
1467                 .private_value = (2 << 8) | 2,
1468                 .tlv = { .p = db_scale_wm_dac }
1469         },
1470         {
1471                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1472                 .name = "Center Playback Switch",
1473                 .info = wm_mute_info,
1474                 .get = wm_mute_get,
1475                 .put = wm_mute_put,
1476                 .private_value = (1 << 8) | 4
1477         },
1478         {
1479                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1480                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1481                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1482                 .name = "Center Playback Volume",
1483                 .info = wm_vol_info,
1484                 .get = wm_vol_get,
1485                 .put = wm_vol_put,
1486                 .private_value = (1 << 8) | 4,
1487                 .tlv = { .p = db_scale_wm_dac }
1488         },
1489         {
1490                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1491                 .name = "LFE Playback Switch",
1492                 .info = wm_mute_info,
1493                 .get = wm_mute_get,
1494                 .put = wm_mute_put,
1495                 .private_value = (1 << 8) | 5
1496         },
1497         {
1498                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1499                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1500                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1501                 .name = "LFE Playback Volume",
1502                 .info = wm_vol_info,
1503                 .get = wm_vol_get,
1504                 .put = wm_vol_put,
1505                 .private_value = (1 << 8) | 5,
1506                 .tlv = { .p = db_scale_wm_dac }
1507         },
1508         {
1509                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1510                 .name = "Side Playback Switch",
1511                 .info = wm_mute_info,
1512                 .get = wm_mute_get,
1513                 .put = wm_mute_put,
1514                 .private_value = (2 << 8) | 6
1515         },
1516         {
1517                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1518                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1519                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1520                 .name = "Side Playback Volume",
1521                 .info = wm_vol_info,
1522                 .get = wm_vol_get,
1523                 .put = wm_vol_put,
1524                 .private_value = (2 << 8) | 6,
1525                 .tlv = { .p = db_scale_wm_dac }
1526         }
1527 };
1528
1529 static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
1530         {
1531                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1532                 .name = "PCM Playback Switch",
1533                 .info = wm_pcm_mute_info,
1534                 .get = wm_pcm_mute_get,
1535                 .put = wm_pcm_mute_put
1536         },
1537         {
1538                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1539                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1540                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1541                 .name = "PCM Playback Volume",
1542                 .info = wm_pcm_vol_info,
1543                 .get = wm_pcm_vol_get,
1544                 .put = wm_pcm_vol_put,
1545                 .tlv = { .p = db_scale_wm_pcm }
1546         },
1547         {
1548                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549                 .name = "Capture Switch",
1550                 .info = wm_adc_mute_info,
1551                 .get = wm_adc_mute_get,
1552                 .put = wm_adc_mute_put,
1553         },
1554         {
1555                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1556                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1557                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1558                 .name = "Capture Volume",
1559                 .info = wm_adc_vol_info,
1560                 .get = wm_adc_vol_get,
1561                 .put = wm_adc_vol_put,
1562                 .tlv = { .p = db_scale_wm_adc }
1563         },
1564         {
1565                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566                 .name = "Capture Source",
1567                 .info = wm_adc_mux_info,
1568                 .get = wm_adc_mux_get,
1569                 .put = wm_adc_mux_put,
1570                 .private_value = 5
1571         },
1572         {
1573                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1574                 .name = "External Amplifier",
1575                 .info = aureon_hpamp_info,
1576                 .get = aureon_hpamp_get,
1577                 .put = aureon_hpamp_put
1578         },
1579         {
1580                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1581                 .name = "DAC Deemphasis Switch",
1582                 .info = aureon_deemp_info,
1583                 .get = aureon_deemp_get,
1584                 .put = aureon_deemp_put
1585         },
1586         {
1587                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1588                 .name = "ADC Oversampling",
1589                 .info = aureon_oversampling_info,
1590                 .get = aureon_oversampling_get,
1591                 .put = aureon_oversampling_put
1592         }
1593 };
1594
1595 static const struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1596         {
1597                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1598                 .name = "AC97 Playback Switch",
1599                 .info = aureon_ac97_mmute_info,
1600                 .get = aureon_ac97_mmute_get,
1601                 .put = aureon_ac97_mmute_put,
1602                 .private_value = AC97_MASTER
1603         },
1604         {
1605                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1606                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1607                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1608                 .name = "AC97 Playback Volume",
1609                 .info = aureon_ac97_vol_info,
1610                 .get = aureon_ac97_vol_get,
1611                 .put = aureon_ac97_vol_put,
1612                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1613                 .tlv = { .p = db_scale_ac97_master }
1614         },
1615         {
1616                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1617                 .name = "CD Playback Switch",
1618                 .info = aureon_ac97_mute_info,
1619                 .get = aureon_ac97_mute_get,
1620                 .put = aureon_ac97_mute_put,
1621                 .private_value = AC97_CD
1622         },
1623         {
1624                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1625                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1626                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1627                 .name = "CD Playback Volume",
1628                 .info = aureon_ac97_vol_info,
1629                 .get = aureon_ac97_vol_get,
1630                 .put = aureon_ac97_vol_put,
1631                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1632                 .tlv = { .p = db_scale_ac97_gain }
1633         },
1634         {
1635                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1636                 .name = "Aux Playback Switch",
1637                 .info = aureon_ac97_mute_info,
1638                 .get = aureon_ac97_mute_get,
1639                 .put = aureon_ac97_mute_put,
1640                 .private_value = AC97_AUX,
1641         },
1642         {
1643                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1644                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1645                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1646                 .name = "Aux Playback Volume",
1647                 .info = aureon_ac97_vol_info,
1648                 .get = aureon_ac97_vol_get,
1649                 .put = aureon_ac97_vol_put,
1650                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1651                 .tlv = { .p = db_scale_ac97_gain }
1652         },
1653         {
1654                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1655                 .name = "Line Playback Switch",
1656                 .info = aureon_ac97_mute_info,
1657                 .get = aureon_ac97_mute_get,
1658                 .put = aureon_ac97_mute_put,
1659                 .private_value = AC97_LINE
1660         },
1661         {
1662                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1663                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1664                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1665                 .name = "Line Playback Volume",
1666                 .info = aureon_ac97_vol_info,
1667                 .get = aureon_ac97_vol_get,
1668                 .put = aureon_ac97_vol_put,
1669                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1670                 .tlv = { .p = db_scale_ac97_gain }
1671         },
1672         {
1673                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1674                 .name = "Mic Playback Switch",
1675                 .info = aureon_ac97_mute_info,
1676                 .get = aureon_ac97_mute_get,
1677                 .put = aureon_ac97_mute_put,
1678                 .private_value = AC97_MIC
1679         },
1680         {
1681                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1682                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1683                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1684                 .name = "Mic Playback Volume",
1685                 .info = aureon_ac97_vol_info,
1686                 .get = aureon_ac97_vol_get,
1687                 .put = aureon_ac97_vol_put,
1688                 .private_value = AC97_MIC,
1689                 .tlv = { .p = db_scale_ac97_gain }
1690         },
1691         {
1692                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1693                 .name = "Mic Boost (+20dB)",
1694                 .info = aureon_ac97_micboost_info,
1695                 .get = aureon_ac97_micboost_get,
1696                 .put = aureon_ac97_micboost_put
1697         }
1698 };
1699
1700 static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1701         {
1702                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1703                 .name = "AC97 Playback Switch",
1704                 .info = aureon_ac97_mmute_info,
1705                 .get = aureon_ac97_mmute_get,
1706                 .put = aureon_ac97_mmute_put,
1707                 .private_value = AC97_MASTER
1708         },
1709         {
1710                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1711                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1712                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1713                 .name = "AC97 Playback Volume",
1714                 .info = aureon_ac97_vol_info,
1715                 .get = aureon_ac97_vol_get,
1716                 .put = aureon_ac97_vol_put,
1717                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1718                 .tlv = { .p = db_scale_ac97_master }
1719         },
1720         {
1721                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1722                 .name = "CD Playback Switch",
1723                 .info = aureon_ac97_mute_info,
1724                 .get = aureon_ac97_mute_get,
1725                 .put = aureon_ac97_mute_put,
1726                 .private_value = AC97_AUX
1727         },
1728         {
1729                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1731                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1732                 .name = "CD Playback Volume",
1733                 .info = aureon_ac97_vol_info,
1734                 .get = aureon_ac97_vol_get,
1735                 .put = aureon_ac97_vol_put,
1736                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1737                 .tlv = { .p = db_scale_ac97_gain }
1738         },
1739         {
1740                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1741                 .name = "Phono Playback Switch",
1742                 .info = aureon_ac97_mute_info,
1743                 .get = aureon_ac97_mute_get,
1744                 .put = aureon_ac97_mute_put,
1745                 .private_value = AC97_CD
1746         },
1747         {
1748                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1749                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1750                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1751                 .name = "Phono Playback Volume",
1752                 .info = aureon_ac97_vol_info,
1753                 .get = aureon_ac97_vol_get,
1754                 .put = aureon_ac97_vol_put,
1755                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1756                 .tlv = { .p = db_scale_ac97_gain }
1757         },
1758         {
1759                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1760                 .name = "Line Playback Switch",
1761                 .info = aureon_ac97_mute_info,
1762                 .get = aureon_ac97_mute_get,
1763                 .put = aureon_ac97_mute_put,
1764                 .private_value = AC97_LINE
1765         },
1766         {
1767                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1768                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1769                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1770                 .name = "Line Playback Volume",
1771                 .info = aureon_ac97_vol_info,
1772                 .get = aureon_ac97_vol_get,
1773                 .put = aureon_ac97_vol_put,
1774                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1775                 .tlv = { .p = db_scale_ac97_gain }
1776         },
1777         {
1778                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1779                 .name = "Mic Playback Switch",
1780                 .info = aureon_ac97_mute_info,
1781                 .get = aureon_ac97_mute_get,
1782                 .put = aureon_ac97_mute_put,
1783                 .private_value = AC97_MIC
1784         },
1785         {
1786                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1787                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1788                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1789                 .name = "Mic Playback Volume",
1790                 .info = aureon_ac97_vol_info,
1791                 .get = aureon_ac97_vol_get,
1792                 .put = aureon_ac97_vol_put,
1793                 .private_value = AC97_MIC,
1794                 .tlv = { .p = db_scale_ac97_gain }
1795         },
1796         {
1797                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1798                 .name = "Mic Boost (+20dB)",
1799                 .info = aureon_ac97_micboost_info,
1800                 .get = aureon_ac97_micboost_get,
1801                 .put = aureon_ac97_micboost_put
1802         },
1803         {
1804                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1805                 .name = "Aux Playback Switch",
1806                 .info = aureon_ac97_mute_info,
1807                 .get = aureon_ac97_mute_get,
1808                 .put = aureon_ac97_mute_put,
1809                 .private_value = AC97_VIDEO,
1810         },
1811         {
1812                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1813                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1814                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1815                 .name = "Aux Playback Volume",
1816                 .info = aureon_ac97_vol_info,
1817                 .get = aureon_ac97_vol_get,
1818                 .put = aureon_ac97_vol_put,
1819                 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1820                 .tlv = { .p = db_scale_ac97_gain }
1821         },
1822         {
1823                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1824                 .name = "Aux Source",
1825                 .info = aureon_universe_inmux_info,
1826                 .get = aureon_universe_inmux_get,
1827                 .put = aureon_universe_inmux_put
1828         }
1829
1830 };
1831
1832 static const struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1833         {
1834                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1835                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1836                 .info = aureon_cs8415_mute_info,
1837                 .get = aureon_cs8415_mute_get,
1838                 .put = aureon_cs8415_mute_put
1839         },
1840         {
1841                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1842                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1843                 .info = aureon_cs8415_mux_info,
1844                 .get = aureon_cs8415_mux_get,
1845                 .put = aureon_cs8415_mux_put,
1846         },
1847         {
1848                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1849                 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1850                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1851                 .info = aureon_cs8415_qsub_info,
1852                 .get = aureon_cs8415_qsub_get,
1853         },
1854         {
1855                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1856                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1857                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1858                 .info = aureon_cs8415_spdif_info,
1859                 .get = aureon_cs8415_mask_get
1860         },
1861         {
1862                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1863                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1864                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1865                 .info = aureon_cs8415_spdif_info,
1866                 .get = aureon_cs8415_spdif_get
1867         },
1868         {
1869                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1870                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1871                 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1872                 .info = aureon_cs8415_rate_info,
1873                 .get = aureon_cs8415_rate_get
1874         }
1875 };
1876
1877 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1878 {
1879         unsigned int i, counts;
1880         int err;
1881
1882         counts = ARRAY_SIZE(aureon_dac_controls);
1883         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1884                 counts -= 2; /* no side */
1885         for (i = 0; i < counts; i++) {
1886                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1887                 if (err < 0)
1888                         return err;
1889         }
1890
1891         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1892                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1893                 if (err < 0)
1894                         return err;
1895         }
1896         
1897         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1898                 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1899                         err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1900                         if (err < 0)
1901                                 return err;
1902                 }
1903         }
1904         else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1905                  ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1906                 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1907                         err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1908                         if (err < 0)
1909                                 return err;
1910                 }
1911         }
1912
1913         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1914             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1915                 unsigned char id;
1916                 snd_ice1712_save_gpio_status(ice);
1917                 id = aureon_cs8415_get(ice, CS8415_ID);
1918                 if (id != 0x41)
1919                         snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1920                 else if ((id & 0x0F) != 0x01)
1921                         snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1922                 else {
1923                         for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1924                                 struct snd_kcontrol *kctl;
1925                                 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1926                                 if (err < 0)
1927                                         return err;
1928                                 if (i > 1)
1929                                         kctl->id.device = ice->pcm->device;
1930                         }
1931                 }
1932                 snd_ice1712_restore_gpio_status(ice);
1933         }
1934         
1935         return 0;
1936 }
1937
1938
1939 /*
1940  * initialize the chip
1941  */
1942 static int __devinit aureon_init(struct snd_ice1712 *ice)
1943 {
1944         static const unsigned short wm_inits_aureon[] = {
1945                 /* These come first to reduce init pop noise */
1946                 0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1947                 0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1948                 0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1949
1950                 0x18, 0x000,            /* All power-up */
1951
1952                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
1953                 0x17, 0x022,            /* 256fs, slave mode */
1954                 0x00, 0,                /* DAC1 analog mute */
1955                 0x01, 0,                /* DAC2 analog mute */
1956                 0x02, 0,                /* DAC3 analog mute */
1957                 0x03, 0,                /* DAC4 analog mute */
1958                 0x04, 0,                /* DAC5 analog mute */
1959                 0x05, 0,                /* DAC6 analog mute */
1960                 0x06, 0,                /* DAC7 analog mute */
1961                 0x07, 0,                /* DAC8 analog mute */
1962                 0x08, 0x100,            /* master analog mute */
1963                 0x09, 0xff,             /* DAC1 digital full */
1964                 0x0a, 0xff,             /* DAC2 digital full */
1965                 0x0b, 0xff,             /* DAC3 digital full */
1966                 0x0c, 0xff,             /* DAC4 digital full */
1967                 0x0d, 0xff,             /* DAC5 digital full */
1968                 0x0e, 0xff,             /* DAC6 digital full */
1969                 0x0f, 0xff,             /* DAC7 digital full */
1970                 0x10, 0xff,             /* DAC8 digital full */
1971                 0x11, 0x1ff,            /* master digital full */
1972                 0x12, 0x000,            /* phase normal */
1973                 0x13, 0x090,            /* unmute DAC L/R */
1974                 0x14, 0x000,            /* all unmute */
1975                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1976                 0x19, 0x000,            /* -12dB ADC/L */
1977                 0x1a, 0x000,            /* -12dB ADC/R */
1978                 (unsigned short)-1
1979         };
1980         static const unsigned short wm_inits_prodigy[] = {
1981
1982                 /* These come first to reduce init pop noise */
1983                 0x1b, 0x000,            /* ADC Mux */
1984                 0x1c, 0x009,            /* Out Mux1 */
1985                 0x1d, 0x009,            /* Out Mux2 */
1986
1987                 0x18, 0x000,            /* All power-up */
1988
1989                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
1990                 0x17, 0x006,            /* 128fs, slave mode */
1991
1992                 0x00, 0,                /* DAC1 analog mute */
1993                 0x01, 0,                /* DAC2 analog mute */
1994                 0x02, 0,                /* DAC3 analog mute */
1995                 0x03, 0,                /* DAC4 analog mute */
1996                 0x04, 0,                /* DAC5 analog mute */
1997                 0x05, 0,                /* DAC6 analog mute */
1998                 0x06, 0,                /* DAC7 analog mute */
1999                 0x07, 0,                /* DAC8 analog mute */
2000                 0x08, 0x100,            /* master analog mute */
2001
2002                 0x09, 0x7f,             /* DAC1 digital full */
2003                 0x0a, 0x7f,             /* DAC2 digital full */
2004                 0x0b, 0x7f,             /* DAC3 digital full */
2005                 0x0c, 0x7f,             /* DAC4 digital full */
2006                 0x0d, 0x7f,             /* DAC5 digital full */
2007                 0x0e, 0x7f,             /* DAC6 digital full */
2008                 0x0f, 0x7f,             /* DAC7 digital full */
2009                 0x10, 0x7f,             /* DAC8 digital full */
2010                 0x11, 0x1FF,            /* master digital full */
2011
2012                 0x12, 0x000,            /* phase normal */
2013                 0x13, 0x090,            /* unmute DAC L/R */
2014                 0x14, 0x000,            /* all unmute */
2015                 0x15, 0x000,            /* no deemphasis, no ZFLG */
2016
2017                 0x19, 0x000,            /* -12dB ADC/L */
2018                 0x1a, 0x000,            /* -12dB ADC/R */
2019                 (unsigned short)-1
2020
2021         };
2022         static const unsigned short cs_inits[] = {
2023                 0x0441, /* RUN */
2024                 0x0180, /* no mute, OMCK output on RMCK pin */
2025                 0x0201, /* S/PDIF source on RXP1 */
2026                 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2027                 (unsigned short)-1
2028         };
2029         unsigned int tmp;
2030         const unsigned short *p;
2031         int err, i;
2032
2033         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2034                 ice->num_total_dacs = 6;
2035                 ice->num_total_adcs = 2;
2036         } else {
2037                 /* aureon 7.1 and prodigy 7.1 */
2038                 ice->num_total_dacs = 8;
2039                 ice->num_total_adcs = 2;
2040         }
2041
2042         /* to remeber the register values of CS8415 */
2043         ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2044         if (! ice->akm)
2045                 return -ENOMEM;
2046         ice->akm_codecs = 1;
2047         
2048         if ((err = aureon_ac97_init(ice)) != 0)
2049                 return err;
2050
2051         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2052
2053         /* reset the wm codec as the SPI mode */
2054         snd_ice1712_save_gpio_status(ice);
2055         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2056
2057         tmp = snd_ice1712_gpio_read(ice);
2058         tmp &= ~AUREON_WM_RESET;
2059         snd_ice1712_gpio_write(ice, tmp);
2060         udelay(1);
2061         tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2062         snd_ice1712_gpio_write(ice, tmp);
2063         udelay(1);
2064         tmp |= AUREON_WM_RESET;
2065         snd_ice1712_gpio_write(ice, tmp);
2066         udelay(1);
2067
2068         /* initialize WM8770 codec */
2069         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2070                 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2071                 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2072                 p = wm_inits_prodigy;
2073         else
2074                 p = wm_inits_aureon;
2075         for (; *p != (unsigned short)-1; p += 2)
2076                 wm_put(ice, p[0], p[1]);
2077
2078         /* initialize CS8415A codec */
2079         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2080             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2081                 for (p = cs_inits; *p != (unsigned short)-1; p++)
2082                         aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2083                 ice->spec.aureon.cs8415_mux = 1;
2084
2085                 aureon_set_headphone_amp(ice, 1);
2086         }
2087
2088         snd_ice1712_restore_gpio_status(ice);
2089
2090         /* initialize PCA9554 pin directions & set default input*/
2091         aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2092         aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2093         
2094         ice->spec.aureon.master[0] = WM_VOL_MUTE;
2095         ice->spec.aureon.master[1] = WM_VOL_MUTE;
2096         for (i = 0; i < ice->num_total_dacs; i++) {
2097                 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2098                 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2099         }
2100
2101         return 0;
2102 }
2103
2104
2105 /*
2106  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2107  * hence the driver needs to sets up it properly.
2108  */
2109
2110 static const unsigned char aureon51_eeprom[] __devinitdata = {
2111         [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
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
2126 static const unsigned char aureon71_eeprom[] __devinitdata = {
2127         [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
2128         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2129         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2130         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2131         [ICE_EEP2_GPIO_DIR]    = 0xff,
2132         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2133         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2134         [ICE_EEP2_GPIO_MASK]   = 0x00,
2135         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2136         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2137         [ICE_EEP2_GPIO_STATE]  = 0x00,
2138         [ICE_EEP2_GPIO_STATE1] = 0x00,
2139         [ICE_EEP2_GPIO_STATE2] = 0x00,
2140 };
2141 #define prodigy71_eeprom aureon71_eeprom
2142
2143 static const unsigned char prodigy71lt_eeprom[] __devinitdata = {
2144         [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
2145         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2146         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2147         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2148         [ICE_EEP2_GPIO_DIR]    = 0xff,
2149         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2150         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2151         [ICE_EEP2_GPIO_MASK]   = 0x00,
2152         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2153         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2154         [ICE_EEP2_GPIO_STATE]  = 0x00,
2155         [ICE_EEP2_GPIO_STATE1] = 0x00,
2156         [ICE_EEP2_GPIO_STATE2] = 0x00,
2157 };
2158 #define prodigy71xt_eeprom prodigy71lt_eeprom
2159
2160 /* entry point */
2161 const struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2162         {
2163                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2164                 .name = "Terratec Aureon 5.1-Sky",
2165                 .model = "aureon51",
2166                 .chip_init = aureon_init,
2167                 .build_controls = aureon_add_controls,
2168                 .eeprom_size = sizeof(aureon51_eeprom),
2169                 .eeprom_data = aureon51_eeprom,
2170                 .driver = "Aureon51",
2171         },
2172         {
2173                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2174                 .name = "Terratec Aureon 7.1-Space",
2175                 .model = "aureon71",
2176                 .chip_init = aureon_init,
2177                 .build_controls = aureon_add_controls,
2178                 .eeprom_size = sizeof(aureon71_eeprom),
2179                 .eeprom_data = aureon71_eeprom,
2180                 .driver = "Aureon71",
2181         },
2182         {
2183                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2184                 .name = "Terratec Aureon 7.1-Universe",
2185                 .model = "universe",
2186                 .chip_init = aureon_init,
2187                 .build_controls = aureon_add_controls,
2188                 .eeprom_size = sizeof(aureon71_eeprom),
2189                 .eeprom_data = aureon71_eeprom,
2190                 .driver = "Aureon71Univ", /* keep in 15 letters */
2191         },
2192         {
2193                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2194                 .name = "Audiotrak Prodigy 7.1",
2195                 .model = "prodigy71",
2196                 .chip_init = aureon_init,
2197                 .build_controls = aureon_add_controls,
2198                 .eeprom_size = sizeof(prodigy71_eeprom),
2199                 .eeprom_data = prodigy71_eeprom,
2200                 .driver = "Prodigy71", /* should be identical with Aureon71 */
2201         },
2202         {
2203                 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2204                 .name = "Audiotrak Prodigy 7.1 LT",
2205                 .model = "prodigy71lt",
2206                 .chip_init = aureon_init,
2207                 .build_controls = aureon_add_controls,
2208                 .eeprom_size = sizeof(prodigy71lt_eeprom),
2209                 .eeprom_data = prodigy71lt_eeprom,
2210                 .driver = "Prodigy71LT",
2211         },
2212         {
2213                 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2214                 .name = "Audiotrak Prodigy 7.1 XT",
2215                 .model = "prodigy71xt",
2216                 .chip_init = aureon_init,
2217                 .build_controls = aureon_add_controls,
2218                 .eeprom_size = sizeof(prodigy71xt_eeprom),
2219                 .eeprom_data = prodigy71xt_eeprom,
2220                 .driver = "Prodigy71LT",
2221         },
2222         { } /* terminator */
2223 };