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