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