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