xref: /linux/sound/pci/ice1712/aureon.c (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
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 };
1995