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