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