brintos

brintos / linux-shallow public Read only

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