cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aureon.c (61678B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
      4 *
      5 *   Lowlevel functions for Terratec Aureon cards
      6 *
      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 integrate
     13 *   both controls in the future, once if wm codecs are reused in
     14 *   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 them
     18 *   instead.
     19 *
     20 *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
     21 *      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 initialization
     27 *
     28 *   version 0.5: Initial release:
     29 *           working: analog output, mixer, headphone amplifier switch
     30 *       not working: prety much everything else, at least i could verify that
     31 *                    we have no digital output, no capture, pretty bad clicks and poops
     32 *                    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	0x01
     77#define CS8415_CTRL2	0x02
     78#define CS8415_QSUB		0x14
     79#define CS8415_RATIO	0x1E
     80#define CS8415_C_BUFFER	0x20
     81#define CS8415_ID		0x7F
     82
     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 PCA9554
     92 */
     93
     94/*
     95 * Send data to pca9554
     96 */
     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 condition
    120	 * to obtain sane state
    121	 */
    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 between
    137	 */
    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			else
    157				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 chip
    291 */
    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)-1
    316	};
    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	0x80
    343
    344/*
    345 * AC'97 volume controls
    346 */
    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 controls
    397 */
    398#define aureon_ac97_mute_info	snd_ctl_boolean_mono_info
    399
    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 controls
    435 */
    436#define aureon_ac97_micboost_info	snd_ctl_boolean_mono_info
    437
    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 mode
    472 */
    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		else
    506			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 mode
    525 */
    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		else
    542			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 codec
    601 */
    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 codec
    611 */
    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 it
    623 */
    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_info
    635
    636/*
    637 * AC'97 master playback mute controls (Mute on WM8770 chip)
    638 */
    639#define aureon_ac97_mmute_info		snd_ctl_boolean_mono_info
    640
    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	100
    679#define WM_VOL_CNT	101	/* 0dB .. -100dB */
    680#define WM_VOL_MUTE	0x8000
    681
    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 control
    700 */
    701#define wm_pcm_mute_info	snd_ctl_boolean_mono_info
    702
    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 control
    732 */
    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 control
    781 */
    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 control
    835 */
    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 control
    888 */
    889#define wm_master_mute_info		snd_ctl_boolean_stereo_info
    890
    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 0xff
    931#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 control
    978 */
    979#define wm_adc_mute_info		snd_ctl_boolean_stereo_info
    980
    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 control
   1018 */
   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 control
   1067 */
   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	else
   1092		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 mux
   1128 */
   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	else
   1143		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 Mute
   1197 */
   1198#define aureon_cs8415_mute_info		snd_ctl_boolean_mono_info
   1199
   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	else
   1219		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 info
   1229 */
   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 Amplifier
   1273 */
   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		else
   1284			tmp |= PRODIGY_HP_SEL;
   1285	else
   1286		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
   1287		    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
   1288			tmp &= ~AUREON_HP_SEL;
   1289		else
   1290			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_info
   1306
   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 * Deemphasis
   1325 */
   1326
   1327#define aureon_deemp_info	snd_ctl_boolean_mono_info
   1328
   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	else
   1344		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 Oversampling
   1354 */
   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	else
   1379		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 * mixers
   1390 */
   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_put
   1399	},
   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) | 0
   1417	},
   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) | 2
   1436	},
   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) | 4
   1455	},
   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) | 5
   1474	},
   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) | 6
   1493	},
   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_put
   1514	},
   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 = 5
   1549	},
   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_put
   1556	},
   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_put
   1563	},
   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_put
   1570	}
   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_MASTER
   1581	},
   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_CD
   1600	},
   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_LINE
   1638	},
   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_MIC
   1657	},
   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_put
   1675	}
   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_MASTER
   1686	},
   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_AUX
   1705	},
   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_CD
   1724	},
   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_LINE
   1743	},
   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_MIC
   1762	},
   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_put
   1780	},
   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_put
   1806	}
   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_put
   1817	},
   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_get
   1838	},
   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_get
   1845	},
   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_get
   1852	}
   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		if (id != 0x41)
   1896			dev_info(ice->card->dev,
   1897				 "No CS8415 chip. Skipping CS8415 controls.\n");
   1898		else if ((id & 0x0F) != 0x01)
   1899			dev_info(ice->card->dev,
   1900				 "Detected unsupported CS8415 rev. (%c)\n",
   1901				 (char)((id & 0x0F) + 'A' - 1));
   1902		else {
   1903			for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
   1904				struct snd_kcontrol *kctl;
   1905				err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
   1906				if (err < 0)
   1907					return err;
   1908				if (i > 1)
   1909					kctl->id.device = ice->pcm->device;
   1910			}
   1911		}
   1912		snd_ice1712_restore_gpio_status(ice);
   1913	}
   1914
   1915	return 0;
   1916}
   1917
   1918/*
   1919 * reset the chip
   1920 */
   1921static int aureon_reset(struct snd_ice1712 *ice)
   1922{
   1923	static const unsigned short wm_inits_aureon[] = {
   1924		/* These come first to reduce init pop noise */
   1925		0x1b, 0x044,		/* ADC Mux (AC'97 source) */
   1926		0x1c, 0x00B,		/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
   1927		0x1d, 0x009,		/* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
   1928
   1929		0x18, 0x000,		/* All power-up */
   1930
   1931		0x16, 0x122,		/* I2S, normal polarity, 24bit */
   1932		0x17, 0x022,		/* 256fs, slave mode */
   1933		0x00, 0,		/* DAC1 analog mute */
   1934		0x01, 0,		/* DAC2 analog mute */
   1935		0x02, 0,		/* DAC3 analog mute */
   1936		0x03, 0,		/* DAC4 analog mute */
   1937		0x04, 0,		/* DAC5 analog mute */
   1938		0x05, 0,		/* DAC6 analog mute */
   1939		0x06, 0,		/* DAC7 analog mute */
   1940		0x07, 0,		/* DAC8 analog mute */
   1941		0x08, 0x100,		/* master analog mute */
   1942		0x09, 0xff,		/* DAC1 digital full */
   1943		0x0a, 0xff,		/* DAC2 digital full */
   1944		0x0b, 0xff,		/* DAC3 digital full */
   1945		0x0c, 0xff,		/* DAC4 digital full */
   1946		0x0d, 0xff,		/* DAC5 digital full */
   1947		0x0e, 0xff,		/* DAC6 digital full */
   1948		0x0f, 0xff,		/* DAC7 digital full */
   1949		0x10, 0xff,		/* DAC8 digital full */
   1950		0x11, 0x1ff,		/* master digital full */
   1951		0x12, 0x000,		/* phase normal */
   1952		0x13, 0x090,		/* unmute DAC L/R */
   1953		0x14, 0x000,		/* all unmute */
   1954		0x15, 0x000,		/* no deemphasis, no ZFLG */
   1955		0x19, 0x000,		/* -12dB ADC/L */
   1956		0x1a, 0x000,		/* -12dB ADC/R */
   1957		(unsigned short)-1
   1958	};
   1959	static const unsigned short wm_inits_prodigy[] = {
   1960
   1961		/* These come first to reduce init pop noise */
   1962		0x1b, 0x000,		/* ADC Mux */
   1963		0x1c, 0x009,		/* Out Mux1 */
   1964		0x1d, 0x009,		/* Out Mux2 */
   1965
   1966		0x18, 0x000,		/* All power-up */
   1967
   1968		0x16, 0x022,		/* I2S, normal polarity, 24bit, high-pass on */
   1969		0x17, 0x006,		/* 128fs, slave mode */
   1970
   1971		0x00, 0,		/* DAC1 analog mute */
   1972		0x01, 0,		/* DAC2 analog mute */
   1973		0x02, 0,		/* DAC3 analog mute */
   1974		0x03, 0,		/* DAC4 analog mute */
   1975		0x04, 0,		/* DAC5 analog mute */
   1976		0x05, 0,		/* DAC6 analog mute */
   1977		0x06, 0,		/* DAC7 analog mute */
   1978		0x07, 0,		/* DAC8 analog mute */
   1979		0x08, 0x100,		/* master analog mute */
   1980
   1981		0x09, 0x7f,		/* DAC1 digital full */
   1982		0x0a, 0x7f,		/* DAC2 digital full */
   1983		0x0b, 0x7f,		/* DAC3 digital full */
   1984		0x0c, 0x7f,		/* DAC4 digital full */
   1985		0x0d, 0x7f,		/* DAC5 digital full */
   1986		0x0e, 0x7f,		/* DAC6 digital full */
   1987		0x0f, 0x7f,		/* DAC7 digital full */
   1988		0x10, 0x7f,		/* DAC8 digital full */
   1989		0x11, 0x1FF,		/* master digital full */
   1990
   1991		0x12, 0x000,		/* phase normal */
   1992		0x13, 0x090,		/* unmute DAC L/R */
   1993		0x14, 0x000,		/* all unmute */
   1994		0x15, 0x000,		/* no deemphasis, no ZFLG */
   1995
   1996		0x19, 0x000,		/* -12dB ADC/L */
   1997		0x1a, 0x000,		/* -12dB ADC/R */
   1998		(unsigned short)-1
   1999
   2000	};
   2001	static const unsigned short cs_inits[] = {
   2002		0x0441, /* RUN */
   2003		0x0180, /* no mute, OMCK output on RMCK pin */
   2004		0x0201, /* S/PDIF source on RXP1 */
   2005		0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
   2006		(unsigned short)-1
   2007	};
   2008	unsigned int tmp;
   2009	const unsigned short *p;
   2010	int err;
   2011	struct aureon_spec *spec = ice->spec;
   2012
   2013	err = aureon_ac97_init(ice);
   2014	if (err != 0)
   2015		return err;
   2016
   2017	snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
   2018
   2019	/* reset the wm codec as the SPI mode */
   2020	snd_ice1712_save_gpio_status(ice);
   2021	snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
   2022
   2023	tmp = snd_ice1712_gpio_read(ice);
   2024	tmp &= ~AUREON_WM_RESET;
   2025	snd_ice1712_gpio_write(ice, tmp);
   2026	udelay(1);
   2027	tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
   2028	snd_ice1712_gpio_write(ice, tmp);
   2029	udelay(1);
   2030	tmp |= AUREON_WM_RESET;
   2031	snd_ice1712_gpio_write(ice, tmp);
   2032	udelay(1);
   2033
   2034	/* initialize WM8770 codec */
   2035	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
   2036		ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
   2037		ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
   2038		p = wm_inits_prodigy;
   2039	else
   2040		p = wm_inits_aureon;
   2041	for (; *p != (unsigned short)-1; p += 2)
   2042		wm_put(ice, p[0], p[1]);
   2043
   2044	/* initialize CS8415A codec */
   2045	if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
   2046	    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
   2047		for (p = cs_inits; *p != (unsigned short)-1; p++)
   2048			aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
   2049		spec->cs8415_mux = 1;
   2050
   2051		aureon_set_headphone_amp(ice, 1);
   2052	}
   2053
   2054	snd_ice1712_restore_gpio_status(ice);
   2055
   2056	/* initialize PCA9554 pin directions & set default input */
   2057	aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
   2058	aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
   2059	return 0;
   2060}
   2061
   2062/*
   2063 * suspend/resume
   2064 */
   2065#ifdef CONFIG_PM_SLEEP
   2066static int aureon_resume(struct snd_ice1712 *ice)
   2067{
   2068	struct aureon_spec *spec = ice->spec;
   2069	int err, i;
   2070
   2071	err = aureon_reset(ice);
   2072	if (err != 0)
   2073		return err;
   2074
   2075	/* workaround for poking volume with alsamixer after resume:
   2076	 * just set stored volume again */
   2077	for (i = 0; i < ice->num_total_dacs; i++)
   2078		wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
   2079	return 0;
   2080}
   2081#endif
   2082
   2083/*
   2084 * initialize the chip
   2085 */
   2086static int aureon_init(struct snd_ice1712 *ice)
   2087{
   2088	struct aureon_spec *spec;
   2089	int i, err;
   2090
   2091	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
   2092	if (!spec)
   2093		return -ENOMEM;
   2094	ice->spec = spec;
   2095
   2096	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
   2097		ice->num_total_dacs = 6;
   2098		ice->num_total_adcs = 2;
   2099	} else {
   2100		/* aureon 7.1 and prodigy 7.1 */
   2101		ice->num_total_dacs = 8;
   2102		ice->num_total_adcs = 2;
   2103	}
   2104
   2105	/* to remember the register values of CS8415 */
   2106	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
   2107	if (!ice->akm)
   2108		return -ENOMEM;
   2109	ice->akm_codecs = 1;
   2110
   2111	err = aureon_reset(ice);
   2112	if (err != 0)
   2113		return err;
   2114
   2115	spec->master[0] = WM_VOL_MUTE;
   2116	spec->master[1] = WM_VOL_MUTE;
   2117	for (i = 0; i < ice->num_total_dacs; i++) {
   2118		spec->vol[i] = WM_VOL_MUTE;
   2119		wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
   2120	}
   2121
   2122#ifdef CONFIG_PM_SLEEP
   2123	ice->pm_resume = aureon_resume;
   2124	ice->pm_suspend_enabled = 1;
   2125#endif
   2126
   2127	return 0;
   2128}
   2129
   2130
   2131/*
   2132 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
   2133 * hence the driver needs to sets up it properly.
   2134 */
   2135
   2136static const unsigned char aureon51_eeprom[] = {
   2137	[ICE_EEP2_SYSCONF]     = 0x0a,	/* clock 512, spdif-in/ADC, 3DACs */
   2138	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
   2139	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
   2140	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
   2141	[ICE_EEP2_GPIO_DIR]    = 0xff,
   2142	[ICE_EEP2_GPIO_DIR1]   = 0xff,
   2143	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
   2144	[ICE_EEP2_GPIO_MASK]   = 0x00,
   2145	[ICE_EEP2_GPIO_MASK1]  = 0x00,
   2146	[ICE_EEP2_GPIO_MASK2]  = 0x00,
   2147	[ICE_EEP2_GPIO_STATE]  = 0x00,
   2148	[ICE_EEP2_GPIO_STATE1] = 0x00,
   2149	[ICE_EEP2_GPIO_STATE2] = 0x00,
   2150};
   2151
   2152static const unsigned char aureon71_eeprom[] = {
   2153	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
   2154	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
   2155	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
   2156	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
   2157	[ICE_EEP2_GPIO_DIR]    = 0xff,
   2158	[ICE_EEP2_GPIO_DIR1]   = 0xff,
   2159	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
   2160	[ICE_EEP2_GPIO_MASK]   = 0x00,
   2161	[ICE_EEP2_GPIO_MASK1]  = 0x00,
   2162	[ICE_EEP2_GPIO_MASK2]  = 0x00,
   2163	[ICE_EEP2_GPIO_STATE]  = 0x00,
   2164	[ICE_EEP2_GPIO_STATE1] = 0x00,
   2165	[ICE_EEP2_GPIO_STATE2] = 0x00,
   2166};
   2167#define prodigy71_eeprom aureon71_eeprom
   2168
   2169static const unsigned char aureon71_universe_eeprom[] = {
   2170	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, spdif-in/ADC,
   2171					 * 4DACs
   2172					 */
   2173	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
   2174	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
   2175	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
   2176	[ICE_EEP2_GPIO_DIR]    = 0xff,
   2177	[ICE_EEP2_GPIO_DIR1]   = 0xff,
   2178	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
   2179	[ICE_EEP2_GPIO_MASK]   = 0x00,
   2180	[ICE_EEP2_GPIO_MASK1]  = 0x00,
   2181	[ICE_EEP2_GPIO_MASK2]  = 0x00,
   2182	[ICE_EEP2_GPIO_STATE]  = 0x00,
   2183	[ICE_EEP2_GPIO_STATE1] = 0x00,
   2184	[ICE_EEP2_GPIO_STATE2] = 0x00,
   2185};
   2186
   2187static const unsigned char prodigy71lt_eeprom[] = {
   2188	[ICE_EEP2_SYSCONF]     = 0x4b,	/* clock 384, spdif-in/ADC, 4DACs */
   2189	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
   2190	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
   2191	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
   2192	[ICE_EEP2_GPIO_DIR]    = 0xff,
   2193	[ICE_EEP2_GPIO_DIR1]   = 0xff,
   2194	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
   2195	[ICE_EEP2_GPIO_MASK]   = 0x00,
   2196	[ICE_EEP2_GPIO_MASK1]  = 0x00,
   2197	[ICE_EEP2_GPIO_MASK2]  = 0x00,
   2198	[ICE_EEP2_GPIO_STATE]  = 0x00,
   2199	[ICE_EEP2_GPIO_STATE1] = 0x00,
   2200	[ICE_EEP2_GPIO_STATE2] = 0x00,
   2201};
   2202#define prodigy71xt_eeprom prodigy71lt_eeprom
   2203
   2204/* entry point */
   2205struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
   2206	{
   2207		.subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
   2208		.name = "Terratec Aureon 5.1-Sky",
   2209		.model = "aureon51",
   2210		.chip_init = aureon_init,
   2211		.build_controls = aureon_add_controls,
   2212		.eeprom_size = sizeof(aureon51_eeprom),
   2213		.eeprom_data = aureon51_eeprom,
   2214		.driver = "Aureon51",
   2215	},
   2216	{
   2217		.subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
   2218		.name = "Terratec Aureon 7.1-Space",
   2219		.model = "aureon71",
   2220		.chip_init = aureon_init,
   2221		.build_controls = aureon_add_controls,
   2222		.eeprom_size = sizeof(aureon71_eeprom),
   2223		.eeprom_data = aureon71_eeprom,
   2224		.driver = "Aureon71",
   2225	},
   2226	{
   2227		.subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
   2228		.name = "Terratec Aureon 7.1-Universe",
   2229		.model = "universe",
   2230		.chip_init = aureon_init,
   2231		.build_controls = aureon_add_controls,
   2232		.eeprom_size = sizeof(aureon71_universe_eeprom),
   2233		.eeprom_data = aureon71_universe_eeprom,
   2234		.driver = "Aureon71Univ", /* keep in 15 letters */
   2235	},
   2236	{
   2237		.subvendor = VT1724_SUBDEVICE_PRODIGY71,
   2238		.name = "Audiotrak Prodigy 7.1",
   2239		.model = "prodigy71",
   2240		.chip_init = aureon_init,
   2241		.build_controls = aureon_add_controls,
   2242		.eeprom_size = sizeof(prodigy71_eeprom),
   2243		.eeprom_data = prodigy71_eeprom,
   2244		.driver = "Prodigy71", /* should be identical with Aureon71 */
   2245	},
   2246	{
   2247		.subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
   2248		.name = "Audiotrak Prodigy 7.1 LT",
   2249		.model = "prodigy71lt",
   2250		.chip_init = aureon_init,
   2251		.build_controls = aureon_add_controls,
   2252		.eeprom_size = sizeof(prodigy71lt_eeprom),
   2253		.eeprom_data = prodigy71lt_eeprom,
   2254		.driver = "Prodigy71LT",
   2255	},
   2256	{
   2257		.subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
   2258		.name = "Audiotrak Prodigy 7.1 XT",
   2259		.model = "prodigy71xt",
   2260		.chip_init = aureon_init,
   2261		.build_controls = aureon_add_controls,
   2262		.eeprom_size = sizeof(prodigy71xt_eeprom),
   2263		.eeprom_data = prodigy71xt_eeprom,
   2264		.driver = "Prodigy71LT",
   2265	},
   2266	{ } /* terminator */
   2267};