File Index
Files and directories
Sign in
FILE

aureon.c

File preview with syntax highlighting.

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