Merge branch 'upstream' of git://lost.foo-projects.org/~ahkok/git/netdev-2.6 into...
[linux-2.6] / sound / pci / ice1712 / aureon.c
1 /*
2  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  *   Lowlevel functions for Terratec Aureon cards
5  *
6  *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  *
23  * NOTES:
24  *
25  * - we reuse the 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                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1285                         tmp |= AUREON_HP_SEL;
1286                 else
1287                         tmp |= PRODIGY_HP_SEL;
1288         else
1289                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1290                         tmp &= ~ AUREON_HP_SEL;
1291                 else
1292                         tmp &= ~ PRODIGY_HP_SEL;
1293         if (tmp != tmp2) {
1294                 snd_ice1712_gpio_write(ice, tmp);
1295                 return 1;
1296         }
1297         return 0;
1298 }
1299
1300 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1301 {
1302         unsigned int tmp = snd_ice1712_gpio_read(ice);
1303
1304         return ( tmp & AUREON_HP_SEL )!= 0;
1305 }
1306
1307 #define aureon_hpamp_info       aureon_mono_bool_info
1308
1309 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1310 {
1311         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1312
1313         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1314         return 0;
1315 }
1316
1317
1318 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1319 {
1320         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1321
1322         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1323 }
1324
1325 /*
1326  * Deemphasis
1327  */
1328
1329 #define aureon_deemp_info       aureon_mono_bool_info
1330
1331 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1332 {
1333         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1334         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1335         return 0;
1336 }
1337
1338 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1339 {
1340         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1341         int temp, temp2;
1342         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1343         if (ucontrol->value.integer.value[0])
1344                 temp |= 0xf;
1345         else
1346                 temp &= ~0xf;
1347         if (temp != temp2) {
1348                 wm_put(ice, WM_DAC_CTRL2, temp);
1349                 return 1;
1350         }
1351         return 0;
1352 }
1353
1354 /*
1355  * ADC Oversampling
1356  */
1357 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1358 {
1359         static char *texts[2] = { "128x", "64x" };
1360
1361         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1362         uinfo->count = 1;
1363         uinfo->value.enumerated.items = 2;
1364
1365         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1366                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1367         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1368
1369         return 0;
1370 }
1371
1372 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1373 {
1374         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1375         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1376         return 0;
1377 }
1378
1379 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1380 {
1381         int temp, temp2;
1382         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1383
1384         temp2 = temp = wm_get(ice, WM_MASTER);
1385
1386         if (ucontrol->value.enumerated.item[0])
1387                 temp |= 0x8;
1388         else
1389                 temp &= ~0x8;
1390
1391         if (temp != temp2) {
1392                 wm_put(ice, WM_MASTER, temp);
1393                 return 1;
1394         }
1395         return 0;
1396 }
1397
1398 /*
1399  * mixers
1400  */
1401
1402 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1403         {
1404                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1405                 .name = "Master Playback Switch",
1406                 .info = wm_master_mute_info,
1407                 .get = wm_master_mute_get,
1408                 .put = wm_master_mute_put
1409         },
1410         {
1411                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412                 .name = "Master Playback Volume",
1413                 .info = wm_master_vol_info,
1414                 .get = wm_master_vol_get,
1415                 .put = wm_master_vol_put
1416         },
1417         {
1418                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419                 .name = "Front Playback Switch",
1420                 .info = wm_mute_info,
1421                 .get = wm_mute_get,
1422                 .put = wm_mute_put,
1423                 .private_value = (2 << 8) | 0
1424         },
1425         {
1426                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1427                 .name = "Front Playback Volume",
1428                 .info = wm_vol_info,
1429                 .get = wm_vol_get,
1430                 .put = wm_vol_put,
1431                 .private_value = (2 << 8) | 0
1432         },
1433         {
1434                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1435                 .name = "Rear Playback Switch",
1436                 .info = wm_mute_info,
1437                 .get = wm_mute_get,
1438                 .put = wm_mute_put,
1439                 .private_value = (2 << 8) | 2
1440         },
1441         {
1442                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443                 .name = "Rear Playback Volume",
1444                 .info = wm_vol_info,
1445                 .get = wm_vol_get,
1446                 .put = wm_vol_put,
1447                 .private_value = (2 << 8) | 2
1448         },
1449         {
1450                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451                 .name = "Center Playback Switch",
1452                 .info = wm_mute_info,
1453                 .get = wm_mute_get,
1454                 .put = wm_mute_put,
1455                 .private_value = (1 << 8) | 4
1456         },
1457         {
1458                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1459                 .name = "Center Playback Volume",
1460                 .info = wm_vol_info,
1461                 .get = wm_vol_get,
1462                 .put = wm_vol_put,
1463                 .private_value = (1 << 8) | 4
1464         },
1465         {
1466                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467                 .name = "LFE Playback Switch",
1468                 .info = wm_mute_info,
1469                 .get = wm_mute_get,
1470                 .put = wm_mute_put,
1471                 .private_value = (1 << 8) | 5
1472         },
1473         {
1474                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475                 .name = "LFE Playback Volume",
1476                 .info = wm_vol_info,
1477                 .get = wm_vol_get,
1478                 .put = wm_vol_put,
1479                 .private_value = (1 << 8) | 5
1480         },
1481         {
1482                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1483                 .name = "Side Playback Switch",
1484                 .info = wm_mute_info,
1485                 .get = wm_mute_get,
1486                 .put = wm_mute_put,
1487                 .private_value = (2 << 8) | 6
1488         },
1489         {
1490                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1491                 .name = "Side Playback Volume",
1492                 .info = wm_vol_info,
1493                 .get = wm_vol_get,
1494                 .put = wm_vol_put,
1495                 .private_value = (2 << 8) | 6
1496         }
1497 };
1498
1499 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1500         {
1501                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1502                 .name = "PCM Playback Switch",
1503                 .info = wm_pcm_mute_info,
1504                 .get = wm_pcm_mute_get,
1505                 .put = wm_pcm_mute_put
1506         },
1507         {
1508                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509                 .name = "PCM Playback Volume",
1510                 .info = wm_pcm_vol_info,
1511                 .get = wm_pcm_vol_get,
1512                 .put = wm_pcm_vol_put
1513         },
1514         {
1515                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1516                 .name = "Capture Switch",
1517                 .info = wm_adc_mute_info,
1518                 .get = wm_adc_mute_get,
1519                 .put = wm_adc_mute_put,
1520         },
1521         {
1522                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1523                 .name = "Capture Volume",
1524                 .info = wm_adc_vol_info,
1525                 .get = wm_adc_vol_get,
1526                 .put = wm_adc_vol_put
1527         },
1528         {
1529                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1530                 .name = "Capture Source",
1531                 .info = wm_adc_mux_info,
1532                 .get = wm_adc_mux_get,
1533                 .put = wm_adc_mux_put,
1534                 .private_value = 5
1535         },
1536         {
1537                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1538                 .name = "External Amplifier",
1539                 .info = aureon_hpamp_info,
1540                 .get = aureon_hpamp_get,
1541                 .put = aureon_hpamp_put
1542         },
1543         {
1544                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1545                 .name = "DAC Deemphasis Switch",
1546                 .info = aureon_deemp_info,
1547                 .get = aureon_deemp_get,
1548                 .put = aureon_deemp_put
1549         },
1550         {
1551                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1552                 .name = "ADC Oversampling",
1553                 .info = aureon_oversampling_info,
1554                 .get = aureon_oversampling_get,
1555                 .put = aureon_oversampling_put
1556         }
1557 };
1558
1559 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1560         {
1561                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1562                 .name = "AC97 Playback Switch",
1563                 .info = aureon_ac97_mmute_info,
1564                 .get = aureon_ac97_mmute_get,
1565                 .put = aureon_ac97_mmute_put,
1566                 .private_value = AC97_MASTER
1567         },
1568         {
1569                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1570                 .name = "AC97 Playback Volume",
1571                 .info = aureon_ac97_vol_info,
1572                 .get = aureon_ac97_vol_get,
1573                 .put = aureon_ac97_vol_put,
1574                 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1575         },
1576         {
1577                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1578                 .name = "CD Playback Switch",
1579                 .info = aureon_ac97_mute_info,
1580                 .get = aureon_ac97_mute_get,
1581                 .put = aureon_ac97_mute_put,
1582                 .private_value = AC97_CD
1583         },
1584         {
1585                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586                 .name = "CD Playback Volume",
1587                 .info = aureon_ac97_vol_info,
1588                 .get = aureon_ac97_vol_get,
1589                 .put = aureon_ac97_vol_put,
1590                 .private_value = AC97_CD|AUREON_AC97_STEREO
1591         },
1592         {
1593                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1594                 .name = "Aux Playback Switch",
1595                 .info = aureon_ac97_mute_info,
1596                 .get = aureon_ac97_mute_get,
1597                 .put = aureon_ac97_mute_put,
1598                 .private_value = AC97_AUX,
1599         },
1600         {
1601                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1602                 .name = "Aux Playback Volume",
1603                 .info = aureon_ac97_vol_info,
1604                 .get = aureon_ac97_vol_get,
1605                 .put = aureon_ac97_vol_put,
1606                 .private_value = AC97_AUX|AUREON_AC97_STEREO
1607         },
1608         {
1609                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1610                 .name = "Line Playback Switch",
1611                 .info = aureon_ac97_mute_info,
1612                 .get = aureon_ac97_mute_get,
1613                 .put = aureon_ac97_mute_put,
1614                 .private_value = AC97_LINE
1615         },
1616         {
1617                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618                 .name = "Line Playback Volume",
1619                 .info = aureon_ac97_vol_info,
1620                 .get = aureon_ac97_vol_get,
1621                 .put = aureon_ac97_vol_put,
1622                 .private_value = AC97_LINE|AUREON_AC97_STEREO
1623         },
1624         {
1625                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1626                 .name = "Mic Playback Switch",
1627                 .info = aureon_ac97_mute_info,
1628                 .get = aureon_ac97_mute_get,
1629                 .put = aureon_ac97_mute_put,
1630                 .private_value = AC97_MIC
1631         },
1632         {
1633                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1634                 .name = "Mic Playback Volume",
1635                 .info = aureon_ac97_vol_info,
1636                 .get = aureon_ac97_vol_get,
1637                 .put = aureon_ac97_vol_put,
1638                 .private_value = AC97_MIC
1639         },
1640         {
1641                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1642                 .name = "Mic Boost (+20dB)",
1643                 .info = aureon_ac97_micboost_info,
1644                 .get = aureon_ac97_micboost_get,
1645                 .put = aureon_ac97_micboost_put
1646         }
1647 };
1648
1649 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1650         {
1651                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1652                 .name = "AC97 Playback Switch",
1653                 .info = aureon_ac97_mmute_info,
1654                 .get = aureon_ac97_mmute_get,
1655                 .put = aureon_ac97_mmute_put,
1656                 .private_value = AC97_MASTER
1657         },
1658         {
1659                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660                 .name = "AC97 Playback Volume",
1661                 .info = aureon_ac97_vol_info,
1662                 .get = aureon_ac97_vol_get,
1663                 .put = aureon_ac97_vol_put,
1664                 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1665         },
1666         {
1667                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1668                 .name = "CD Playback Switch",
1669                 .info = aureon_ac97_mute_info,
1670                 .get = aureon_ac97_mute_get,
1671                 .put = aureon_ac97_mute_put,
1672                 .private_value = AC97_AUX
1673         },
1674         {
1675                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1676                 .name = "CD Playback Volume",
1677                 .info = aureon_ac97_vol_info,
1678                 .get = aureon_ac97_vol_get,
1679                 .put = aureon_ac97_vol_put,
1680                 .private_value = AC97_AUX|AUREON_AC97_STEREO
1681         },
1682         {
1683                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1684                 .name = "Phono Playback Switch",
1685                 .info = aureon_ac97_mute_info,
1686                 .get = aureon_ac97_mute_get,
1687                 .put = aureon_ac97_mute_put,
1688                 .private_value = AC97_CD,
1689         },
1690         {
1691                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1692                 .name = "Phono Playback Volume",
1693                 .info = aureon_ac97_vol_info,
1694                 .get = aureon_ac97_vol_get,
1695                 .put = aureon_ac97_vol_put,
1696                 .private_value = AC97_CD|AUREON_AC97_STEREO
1697         },
1698         {
1699                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700                 .name = "Line Playback Switch",
1701                 .info = aureon_ac97_mute_info,
1702                 .get = aureon_ac97_mute_get,
1703                 .put = aureon_ac97_mute_put,
1704                 .private_value = AC97_LINE
1705         },
1706         {
1707                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708                 .name = "Line Playback Volume",
1709                 .info = aureon_ac97_vol_info,
1710                 .get = aureon_ac97_vol_get,
1711                 .put = aureon_ac97_vol_put,
1712                 .private_value = AC97_LINE|AUREON_AC97_STEREO
1713         },
1714         {
1715                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1716                 .name = "Mic Playback Switch",
1717                 .info = aureon_ac97_mute_info,
1718                 .get = aureon_ac97_mute_get,
1719                 .put = aureon_ac97_mute_put,
1720                 .private_value = AC97_MIC
1721         },
1722         {
1723                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1724                 .name = "Mic Playback Volume",
1725                 .info = aureon_ac97_vol_info,
1726                 .get = aureon_ac97_vol_get,
1727                 .put = aureon_ac97_vol_put,
1728                 .private_value = AC97_MIC
1729         },
1730         {
1731                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1732                 .name = "Mic Boost (+20dB)",
1733                 .info = aureon_ac97_micboost_info,
1734                 .get = aureon_ac97_micboost_get,
1735                 .put = aureon_ac97_micboost_put
1736         },
1737         {
1738                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1739                 .name = "Aux Playback Switch",
1740                 .info = aureon_ac97_mute_info,
1741                 .get = aureon_ac97_mute_get,
1742                 .put = aureon_ac97_mute_put,
1743                 .private_value = AC97_VIDEO,
1744         },
1745         {
1746                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1747                 .name = "Aux Playback Volume",
1748                 .info = aureon_ac97_vol_info,
1749                 .get = aureon_ac97_vol_get,
1750                 .put = aureon_ac97_vol_put,
1751                 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1752         },
1753         {
1754                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1755                 .name = "Aux Source",
1756                 .info = aureon_universe_inmux_info,
1757                 .get = aureon_universe_inmux_get,
1758                 .put = aureon_universe_inmux_put
1759         }
1760
1761 };
1762
1763         
1764 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1765         {
1766                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1767                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1768                 .info = aureon_cs8415_mute_info,
1769                 .get = aureon_cs8415_mute_get,
1770                 .put = aureon_cs8415_mute_put
1771         },
1772         {
1773                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1774                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1775                 .info = aureon_cs8415_mux_info,
1776                 .get = aureon_cs8415_mux_get,
1777                 .put = aureon_cs8415_mux_put,
1778         },
1779         {
1780                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1781                 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1782                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1783                 .info = aureon_cs8415_qsub_info,
1784                 .get = aureon_cs8415_qsub_get,
1785         },
1786         {
1787                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1788                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1789                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1790                 .info = aureon_cs8415_spdif_info,
1791                 .get = aureon_cs8415_mask_get
1792         },
1793         {
1794                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1795                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1796                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1797                 .info = aureon_cs8415_spdif_info,
1798                 .get = aureon_cs8415_spdif_get
1799         },
1800         {
1801                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1802                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1803                 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1804                 .info = aureon_cs8415_rate_info,
1805                 .get = aureon_cs8415_rate_get
1806         }
1807 };
1808
1809  
1810 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1811 {
1812         unsigned int i, counts;
1813         int err;
1814
1815         counts = ARRAY_SIZE(aureon_dac_controls);
1816         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1817                 counts -= 2; /* no side */
1818         for (i = 0; i < counts; i++) {
1819                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1820                 if (err < 0)
1821                         return err;
1822         }
1823
1824         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1825                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1826                 if (err < 0)
1827                         return err;
1828         }
1829         
1830         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1831                 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1832                         err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1833                         if (err < 0)
1834                                 return err;
1835                 }
1836         }
1837         else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1838                 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1839                         err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1840                         if (err < 0)
1841                                 return err;
1842                 }
1843         }
1844
1845         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1846                 unsigned char id;
1847                 snd_ice1712_save_gpio_status(ice);
1848                 id = aureon_cs8415_get(ice, CS8415_ID);
1849                 if (id != 0x41)
1850                         snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1851                 else if ((id & 0x0F) != 0x01)
1852                         snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1853                 else {
1854                         for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1855                                 struct snd_kcontrol *kctl;
1856                                 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1857                                 if (err < 0)
1858                                         return err;
1859                                 if (i > 1)
1860                                         kctl->id.device = ice->pcm->device;
1861                         }
1862                 }
1863                 snd_ice1712_restore_gpio_status(ice);
1864         }
1865         
1866         return 0;
1867 }
1868
1869
1870 /*
1871  * initialize the chip
1872  */
1873 static int __devinit aureon_init(struct snd_ice1712 *ice)
1874 {
1875         static unsigned short wm_inits_aureon[] = {
1876                 /* These come first to reduce init pop noise */
1877                 0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1878                 0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1879                 0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1880
1881                 0x18, 0x000,            /* All power-up */
1882
1883                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
1884                 0x17, 0x022,            /* 256fs, slave mode */
1885                 0x00, 0,                /* DAC1 analog mute */
1886                 0x01, 0,                /* DAC2 analog mute */
1887                 0x02, 0,                /* DAC3 analog mute */
1888                 0x03, 0,                /* DAC4 analog mute */
1889                 0x04, 0,                /* DAC5 analog mute */
1890                 0x05, 0,                /* DAC6 analog mute */
1891                 0x06, 0,                /* DAC7 analog mute */
1892                 0x07, 0,                /* DAC8 analog mute */
1893                 0x08, 0x100,            /* master analog mute */
1894                 0x09, 0xff,             /* DAC1 digital full */
1895                 0x0a, 0xff,             /* DAC2 digital full */
1896                 0x0b, 0xff,             /* DAC3 digital full */
1897                 0x0c, 0xff,             /* DAC4 digital full */
1898                 0x0d, 0xff,             /* DAC5 digital full */
1899                 0x0e, 0xff,             /* DAC6 digital full */
1900                 0x0f, 0xff,             /* DAC7 digital full */
1901                 0x10, 0xff,             /* DAC8 digital full */
1902                 0x11, 0x1ff,            /* master digital full */
1903                 0x12, 0x000,            /* phase normal */
1904                 0x13, 0x090,            /* unmute DAC L/R */
1905                 0x14, 0x000,            /* all unmute */
1906                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1907                 0x19, 0x000,            /* -12dB ADC/L */
1908                 0x1a, 0x000,            /* -12dB ADC/R */
1909                 (unsigned short)-1
1910         };
1911         static unsigned short wm_inits_prodigy[] = {
1912
1913                 /* These come first to reduce init pop noise */
1914                 0x1b, 0x000,            /* ADC Mux */
1915                 0x1c, 0x009,            /* Out Mux1 */
1916                 0x1d, 0x009,            /* Out Mux2 */
1917
1918                 0x18, 0x000,            /* All power-up */
1919
1920                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
1921                 0x17, 0x006,            /* 128fs, slave mode */
1922
1923                 0x00, 0,                /* DAC1 analog mute */
1924                 0x01, 0,                /* DAC2 analog mute */
1925                 0x02, 0,                /* DAC3 analog mute */
1926                 0x03, 0,                /* DAC4 analog mute */
1927                 0x04, 0,                /* DAC5 analog mute */
1928                 0x05, 0,                /* DAC6 analog mute */
1929                 0x06, 0,                /* DAC7 analog mute */
1930                 0x07, 0,                /* DAC8 analog mute */
1931                 0x08, 0x100,            /* master analog mute */
1932
1933                 0x09, 0x7f,             /* DAC1 digital full */
1934                 0x0a, 0x7f,             /* DAC2 digital full */
1935                 0x0b, 0x7f,             /* DAC3 digital full */
1936                 0x0c, 0x7f,             /* DAC4 digital full */
1937                 0x0d, 0x7f,             /* DAC5 digital full */
1938                 0x0e, 0x7f,             /* DAC6 digital full */
1939                 0x0f, 0x7f,             /* DAC7 digital full */
1940                 0x10, 0x7f,             /* DAC8 digital full */
1941                 0x11, 0x1FF,            /* master digital full */
1942
1943                 0x12, 0x000,            /* phase normal */
1944                 0x13, 0x090,            /* unmute DAC L/R */
1945                 0x14, 0x000,            /* all unmute */
1946                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1947
1948                 0x19, 0x000,            /* -12dB ADC/L */
1949                 0x1a, 0x000,            /* -12dB ADC/R */
1950                 (unsigned short)-1
1951
1952         };
1953         static unsigned short cs_inits[] = {
1954                 0x0441, /* RUN */
1955                 0x0180, /* no mute, OMCK output on RMCK pin */
1956                 0x0201, /* S/PDIF source on RXP1 */
1957                 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1958                 (unsigned short)-1
1959         };
1960         unsigned int tmp;
1961         unsigned short *p;
1962         int err, i;
1963
1964         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1965                 ice->num_total_dacs = 6;
1966                 ice->num_total_adcs = 2;
1967         } else {
1968                 /* aureon 7.1 and prodigy 7.1 */
1969                 ice->num_total_dacs = 8;
1970                 ice->num_total_adcs = 2;
1971         }
1972
1973         /* to remeber the register values of CS8415 */
1974         ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1975         if (! ice->akm)
1976                 return -ENOMEM;
1977         ice->akm_codecs = 1;
1978         
1979         if ((err = aureon_ac97_init(ice)) != 0)
1980                 return err;
1981
1982         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1983
1984         /* reset the wm codec as the SPI mode */
1985         snd_ice1712_save_gpio_status(ice);
1986         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1987
1988         tmp = snd_ice1712_gpio_read(ice);
1989         tmp &= ~AUREON_WM_RESET;
1990         snd_ice1712_gpio_write(ice, tmp);
1991         udelay(1);
1992         tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1993         snd_ice1712_gpio_write(ice, tmp);
1994         udelay(1);
1995         tmp |= AUREON_WM_RESET;
1996         snd_ice1712_gpio_write(ice, tmp);
1997         udelay(1);
1998
1999         /* initialize WM8770 codec */
2000         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2001                 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT)
2002                 p = wm_inits_prodigy;
2003         else
2004                 p = wm_inits_aureon;
2005         for (; *p != (unsigned short)-1; p += 2)
2006                 wm_put(ice, p[0], p[1]);
2007
2008         /* initialize CS8415A codec */
2009         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
2010                 for (p = cs_inits; *p != (unsigned short)-1; p++)
2011                         aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2012                 ice->spec.aureon.cs8415_mux = 1;
2013
2014                 aureon_set_headphone_amp(ice, 1);
2015         }
2016
2017         snd_ice1712_restore_gpio_status(ice);
2018
2019         /* initialize PCA9554 pin directions & set default input*/
2020         aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2021         aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2022         
2023         ice->spec.aureon.master[0] = WM_VOL_MUTE;
2024         ice->spec.aureon.master[1] = WM_VOL_MUTE;
2025         for (i = 0; i < ice->num_total_dacs; i++) {
2026                 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2027                 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2028         }
2029
2030         return 0;
2031 }
2032
2033
2034 /*
2035  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2036  * hence the driver needs to sets up it properly.
2037  */
2038
2039 static unsigned char aureon51_eeprom[] __devinitdata = {
2040         0x0a,   /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
2041         0x80,   /* ACLINK: I2S */
2042         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
2043         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
2044         0xff,   /* GPIO_DIR */
2045         0xff,   /* GPIO_DIR1 */
2046         0x5f,   /* GPIO_DIR2 */
2047         0x00,   /* GPIO_MASK */
2048         0x00,   /* GPIO_MASK1 */
2049         0x00,   /* GPIO_MASK2 */
2050         0x00,   /* GPIO_STATE */
2051         0x00,   /* GPIO_STATE1 */
2052         0x00,   /* GPIO_STATE2 */
2053 };
2054
2055 static unsigned char aureon71_eeprom[] __devinitdata = {
2056         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
2057         0x80,   /* ACLINK: I2S */
2058         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
2059         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
2060         0xff,   /* GPIO_DIR */
2061         0xff,   /* GPIO_DIR1 */
2062         0x5f,   /* GPIO_DIR2 */
2063         0x00,   /* GPIO_MASK */
2064         0x00,   /* GPIO_MASK1 */
2065         0x00,   /* GPIO_MASK2 */
2066         0x00,   /* GPIO_STATE */
2067         0x00,   /* GPIO_STATE1 */
2068         0x00,   /* GPIO_STATE2 */
2069 };
2070
2071 static unsigned char prodigy71_eeprom[] __devinitdata = {
2072         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
2073         0x80,   /* ACLINK: I2S */
2074         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
2075         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
2076         0xff,   /* GPIO_DIR */
2077         0xff,   /* GPIO_DIR1 */
2078         0x5f,   /* GPIO_DIR2 */
2079         0x00,   /* GPIO_MASK */
2080         0x00,   /* GPIO_MASK1 */
2081         0x00,   /* GPIO_MASK2 */
2082         0x00,   /* GPIO_STATE */
2083         0x00,   /* GPIO_STATE1 */
2084         0x00,   /* GPIO_STATE2 */
2085 };
2086
2087 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2088         0x4b,   /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
2089         0x80,   /* ACLINK: I2S */
2090         0xfc,   /* I2S: vol, 96k, 24bit, 192k */
2091         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
2092         0xff,   /* GPIO_DIR */
2093         0xff,   /* GPIO_DIR1 */
2094         0x5f,   /* GPIO_DIR2 */
2095         0x00,   /* GPIO_MASK */
2096         0x00,   /* GPIO_MASK1 */
2097         0x00,   /* GPIO_MASK2 */
2098         0x00,   /* GPIO_STATE */
2099         0x00,   /* GPIO_STATE1 */
2100         0x00,   /* GPIO_STATE2 */
2101 };
2102         
2103
2104 /* entry point */
2105 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2106         {
2107                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2108                 .name = "Terratec Aureon 5.1-Sky",
2109                 .model = "aureon51",
2110                 .chip_init = aureon_init,
2111                 .build_controls = aureon_add_controls,
2112                 .eeprom_size = sizeof(aureon51_eeprom),
2113                 .eeprom_data = aureon51_eeprom,
2114                 .driver = "Aureon51",
2115         },
2116         {
2117                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2118                 .name = "Terratec Aureon 7.1-Space",
2119                 .model = "aureon71",
2120                 .chip_init = aureon_init,
2121                 .build_controls = aureon_add_controls,
2122                 .eeprom_size = sizeof(aureon71_eeprom),
2123                 .eeprom_data = aureon71_eeprom,
2124                 .driver = "Aureon71",
2125         },
2126         {
2127                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2128                 .name = "Terratec Aureon 7.1-Universe",
2129                 .model = "universe",
2130                 .chip_init = aureon_init,
2131                 .build_controls = aureon_add_controls,
2132                 .eeprom_size = sizeof(aureon71_eeprom),
2133                 .eeprom_data = aureon71_eeprom,
2134                 .driver = "Aureon71Universe",
2135         },
2136         {
2137                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2138                 .name = "Audiotrak Prodigy 7.1",
2139                 .model = "prodigy71",
2140                 .chip_init = aureon_init,
2141                 .build_controls = aureon_add_controls,
2142                 .eeprom_size = sizeof(prodigy71_eeprom),
2143                 .eeprom_data = prodigy71_eeprom,
2144                 .driver = "Prodigy71", /* should be identical with Aureon71 */
2145         },
2146         {
2147                 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2148                 .name = "Audiotrak Prodigy 7.1 LT",
2149                 .model = "prodigy71lt",
2150                 .chip_init = aureon_init,
2151                 .build_controls = aureon_add_controls,
2152                 .eeprom_size = sizeof(prodigy71lt_eeprom),
2153                 .eeprom_data = prodigy71lt_eeprom,
2154                 .driver = "Prodigy71LT",
2155         },
2156         { } /* terminator */
2157 };