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