File Index
Files and directories
Sign in
FILE

prodigy_hifi.c

File preview with syntax highlighting.

linux-6.19.14/sound/pci/ice1712/prodigy_hifi.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
   4 *
   5 *   Lowlevel functions for Audiotrak Prodigy 7.1 Hifi
   6 *   based on pontis.c
   7 *
   8 *      Copyright (c) 2007 Julian Scheel <julian@jusst.de>
   9 *      Copyright (c) 2007 allank
  10 *      Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  11 */
  12
  13
  14#include <linux/delay.h>
  15#include <linux/interrupt.h>
  16#include <linux/init.h>
  17#include <linux/slab.h>
  18#include <linux/mutex.h>
  19
  20#include <sound/core.h>
  21#include <sound/info.h>
  22#include <sound/tlv.h>
  23
  24#include "ice1712.h"
  25#include "envy24ht.h"
  26#include "prodigy_hifi.h"
  27
  28struct prodigy_hifi_spec {
  29	unsigned short master[2];
  30	unsigned short vol[8];
  31};
  32
  33/* I2C addresses */
  34#define WM_DEV		0x34
  35
  36/* WM8776 registers */
  37#define WM_HP_ATTEN_L		0x00	/* headphone left attenuation */
  38#define WM_HP_ATTEN_R		0x01	/* headphone left attenuation */
  39#define WM_HP_MASTER		0x02	/* headphone master (both channels),
  40						override LLR */
  41#define WM_DAC_ATTEN_L		0x03	/* digital left attenuation */
  42#define WM_DAC_ATTEN_R		0x04
  43#define WM_DAC_MASTER		0x05
  44#define WM_PHASE_SWAP		0x06	/* DAC phase swap */
  45#define WM_DAC_CTRL1		0x07
  46#define WM_DAC_MUTE		0x08
  47#define WM_DAC_CTRL2		0x09
  48#define WM_DAC_INT		0x0a
  49#define WM_ADC_INT		0x0b
  50#define WM_MASTER_CTRL		0x0c
  51#define WM_POWERDOWN		0x0d
  52#define WM_ADC_ATTEN_L		0x0e
  53#define WM_ADC_ATTEN_R		0x0f
  54#define WM_ALC_CTRL1		0x10
  55#define WM_ALC_CTRL2		0x11
  56#define WM_ALC_CTRL3		0x12
  57#define WM_NOISE_GATE		0x13
  58#define WM_LIMITER		0x14
  59#define WM_ADC_MUX		0x15
  60#define WM_OUT_MUX		0x16
  61#define WM_RESET		0x17
  62
  63/* Analog Recording Source :- Mic, LineIn, CD/Video, */
  64
  65/* implement capture source select control for WM8776 */
  66
  67#define WM_AIN1 "AIN1"
  68#define WM_AIN2 "AIN2"
  69#define WM_AIN3 "AIN3"
  70#define WM_AIN4 "AIN4"
  71#define WM_AIN5 "AIN5"
  72
  73/* GPIO pins of envy24ht connected to wm8766 */
  74#define WM8766_SPI_CLK	 (1<<17) /* CLK, Pin97 on ICE1724 */
  75#define WM8766_SPI_MD	  (1<<16) /* DATA VT1724 -> WM8766, Pin96 */
  76#define WM8766_SPI_ML	  (1<<18) /* Latch, Pin98 */
  77
  78/* WM8766 registers */
  79#define WM8766_DAC_CTRL	 0x02   /* DAC Control */
  80#define WM8766_INT_CTRL	 0x03   /* Interface Control */
  81#define WM8766_DAC_CTRL2	0x09
  82#define WM8766_DAC_CTRL3	0x0a
  83#define WM8766_RESET	    0x1f
  84#define WM8766_LDA1	     0x00
  85#define WM8766_LDA2	     0x04
  86#define WM8766_LDA3	     0x06
  87#define WM8766_RDA1	     0x01
  88#define WM8766_RDA2	     0x05
  89#define WM8766_RDA3	     0x07
  90#define WM8766_MUTE1	    0x0C
  91#define WM8766_MUTE2	    0x0F
  92
  93
  94/*
  95 * Prodigy HD2
  96 */
  97#define AK4396_ADDR    0x00
  98#define AK4396_CSN    (1 << 8)    /* CSN->GPIO8, pin 75 */
  99#define AK4396_CCLK   (1 << 9)    /* CCLK->GPIO9, pin 76 */
 100#define AK4396_CDTI   (1 << 10)   /* CDTI->GPIO10, pin 77 */
 101
 102/* ak4396 registers */
 103#define AK4396_CTRL1	    0x00
 104#define AK4396_CTRL2	    0x01
 105#define AK4396_CTRL3	    0x02
 106#define AK4396_LCH_ATT	  0x03
 107#define AK4396_RCH_ATT	  0x04
 108
 109
 110/*
 111 * get the current register value of WM codec
 112 */
 113static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
 114{
 115	reg <<= 1;
 116	return ((unsigned short)ice->akm[0].images[reg] << 8) |
 117		ice->akm[0].images[reg + 1];
 118}
 119
 120/*
 121 * set the register value of WM codec and remember it
 122 */
 123static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
 124{
 125	unsigned short cval;
 126	cval = (reg << 9) | val;
 127	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
 128}
 129
 130static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
 131{
 132	wm_put_nocache(ice, reg, val);
 133	reg <<= 1;
 134	ice->akm[0].images[reg] = val >> 8;
 135	ice->akm[0].images[reg + 1] = val;
 136}
 137
 138/*
 139 * write data in the SPI mode
 140 */
 141
 142static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)
 143{
 144	unsigned int tmp = snd_ice1712_gpio_read(ice);
 145	if (val)
 146		tmp |= bit;
 147	else
 148		tmp &= ~bit;
 149	snd_ice1712_gpio_write(ice, tmp);
 150}
 151
 152/*
 153 * SPI implementation for WM8766 codec - only writing supported, no readback
 154 */
 155
 156static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data)
 157{
 158	int i;
 159	for (i = 0; i < 16; i++) {
 160		set_gpio_bit(ice, WM8766_SPI_CLK, 0);
 161		udelay(1);
 162		set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000);
 163		udelay(1);
 164		set_gpio_bit(ice, WM8766_SPI_CLK, 1);
 165		udelay(1);
 166		data <<= 1;
 167	}
 168}
 169
 170static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg,
 171			     unsigned int data)
 172{
 173	unsigned int block;
 174
 175	snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD|
 176					WM8766_SPI_CLK|WM8766_SPI_ML);
 177	snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD|
 178					WM8766_SPI_CLK|WM8766_SPI_ML));
 179	/* latch must be low when writing */
 180	set_gpio_bit(ice, WM8766_SPI_ML, 0);
 181	block = (reg << 9) | (data & 0x1ff);
 182	wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */
 183	/* release latch */
 184	set_gpio_bit(ice, WM8766_SPI_ML, 1);
 185	udelay(1);
 186	/* restore */
 187	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
 188	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
 189}
 190
 191
 192/*
 193 * serial interface for ak4396 - only writing supported, no readback
 194 */
 195
 196static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data)
 197{
 198	int i;
 199	for (i = 0; i < 16; i++) {
 200		set_gpio_bit(ice, AK4396_CCLK, 0);
 201		udelay(1);
 202		set_gpio_bit(ice, AK4396_CDTI, data & 0x8000);
 203		udelay(1);
 204		set_gpio_bit(ice, AK4396_CCLK, 1);
 205		udelay(1);
 206		data <<= 1;
 207	}
 208}
 209
 210static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg,
 211			 unsigned int data)
 212{
 213	unsigned int block;
 214
 215	snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI);
 216	snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI));
 217	/* latch must be low when writing */
 218	set_gpio_bit(ice, AK4396_CSN, 0); 
 219	block =  ((AK4396_ADDR & 0x03) << 14) | (1 << 13) |
 220			((reg & 0x1f) << 8) | (data & 0xff);
 221	ak4396_send_word(ice, block); /* REGISTER ADDRESS */
 222	/* release latch */
 223	set_gpio_bit(ice, AK4396_CSN, 1);
 224	udelay(1);
 225	/* restore */
 226	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
 227	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
 228}
 229
 230
 231/*
 232 * ak4396 mixers
 233 */
 234
 235
 236
 237/*
 238 * DAC volume attenuation mixer control (-64dB to 0dB)
 239 */
 240
 241static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol,
 242			       struct snd_ctl_elem_info *uinfo)
 243{
 244	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 245	uinfo->count = 2;
 246	uinfo->value.integer.min = 0;   /* mute */
 247	uinfo->value.integer.max = 0xFF; /* linear */
 248	return 0;
 249}
 250
 251static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol,
 252			      struct snd_ctl_elem_value *ucontrol)
 253{
 254	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 255	struct prodigy_hifi_spec *spec = ice->spec;
 256	int i;
 257	
 258	for (i = 0; i < 2; i++)
 259		ucontrol->value.integer.value[i] = spec->vol[i];
 260
 261	return 0;
 262}
 263
 264static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 265{
 266	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 267	struct prodigy_hifi_spec *spec = ice->spec;
 268	int i;
 269	int change = 0;
 270	
 271	guard(mutex)(&ice->gpio_mutex);
 272	for (i = 0; i < 2; i++) {
 273		if (ucontrol->value.integer.value[i] != spec->vol[i]) {
 274			spec->vol[i] = ucontrol->value.integer.value[i];
 275			ak4396_write(ice, AK4396_LCH_ATT + i,
 276				     spec->vol[i] & 0xff);
 277			change = 1;
 278		}
 279	}
 280	return change;
 281}
 282
 283static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 284static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 285
 286static const struct snd_kcontrol_new prodigy_hd2_controls[] = {
 287    {
 288	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 289	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 290		SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 291	.name = "Front Playback Volume",
 292	.info = ak4396_dac_vol_info,
 293	.get = ak4396_dac_vol_get,
 294	.put = ak4396_dac_vol_put,
 295	.tlv = { .p = ak4396_db_scale },
 296    },
 297};
 298
 299
 300/* --------------- */
 301
 302#define WM_VOL_MAX	255
 303#define WM_VOL_MUTE	0x8000
 304
 305
 306#define DAC_0dB	0xff
 307#define DAC_RES	128
 308#define DAC_MIN	(DAC_0dB - DAC_RES)
 309
 310
 311static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
 312		       unsigned short vol, unsigned short master)
 313{
 314	unsigned char nvol;
 315	
 316	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
 317		nvol = 0;
 318	else {
 319		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
 320				& WM_VOL_MAX;
 321		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
 322	}
 323	
 324	wm_put(ice, index, nvol);
 325	wm_put_nocache(ice, index, 0x100 | nvol);
 326}
 327
 328static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index,
 329			   unsigned short vol, unsigned short master)
 330{
 331	unsigned char nvol;
 332	
 333	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
 334		nvol = 0;
 335	else {
 336		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
 337				& WM_VOL_MAX;
 338		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
 339	}
 340
 341	wm8766_spi_write(ice, index, (0x0100 | nvol));
 342}
 343
 344
 345/*
 346 * DAC volume attenuation mixer control (-64dB to 0dB)
 347 */
 348
 349static int wm_dac_vol_info(struct snd_kcontrol *kcontrol,
 350			   struct snd_ctl_elem_info *uinfo)
 351{
 352	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 353	uinfo->count = 2;
 354	uinfo->value.integer.min = 0;	/* mute */
 355	uinfo->value.integer.max = DAC_RES;	/* 0dB, 0.5dB step */
 356	return 0;
 357}
 358
 359static int wm_dac_vol_get(struct snd_kcontrol *kcontrol,
 360			  struct snd_ctl_elem_value *ucontrol)
 361{
 362	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 363	struct prodigy_hifi_spec *spec = ice->spec;
 364	int i;
 365
 366	for (i = 0; i < 2; i++)
 367		ucontrol->value.integer.value[i] =
 368			spec->vol[2 + i] & ~WM_VOL_MUTE;
 369	return 0;
 370}
 371
 372static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 373{
 374	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 375	struct prodigy_hifi_spec *spec = ice->spec;
 376	int i, idx, change = 0;
 377
 378	guard(mutex)(&ice->gpio_mutex);
 379	for (i = 0; i < 2; i++) {
 380		if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) {
 381			idx = WM_DAC_ATTEN_L + i;
 382			spec->vol[2 + i] &= WM_VOL_MUTE;
 383			spec->vol[2 + i] |= ucontrol->value.integer.value[i];
 384			wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]);
 385			change = 1;
 386		}
 387	}
 388	return change;
 389}
 390
 391
 392/*
 393 * WM8766 DAC volume attenuation mixer control
 394 */
 395static int wm8766_vol_info(struct snd_kcontrol *kcontrol,
 396			   struct snd_ctl_elem_info *uinfo)
 397{
 398	int voices = kcontrol->private_value >> 8;
 399	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 400	uinfo->count = voices;
 401	uinfo->value.integer.min = 0;		/* mute */
 402	uinfo->value.integer.max = DAC_RES;	/* 0dB */
 403	return 0;
 404}
 405
 406static int wm8766_vol_get(struct snd_kcontrol *kcontrol,
 407			  struct snd_ctl_elem_value *ucontrol)
 408{
 409	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 410	struct prodigy_hifi_spec *spec = ice->spec;
 411	int i, ofs, voices;
 412
 413	voices = kcontrol->private_value >> 8;
 414	ofs = kcontrol->private_value & 0xff;
 415	for (i = 0; i < voices; i++)
 416		ucontrol->value.integer.value[i] = spec->vol[ofs + i];
 417	return 0;
 418}
 419
 420static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 421{
 422	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 423	struct prodigy_hifi_spec *spec = ice->spec;
 424	int i, idx, ofs, voices;
 425	int change = 0;
 426
 427	voices = kcontrol->private_value >> 8;
 428	ofs = kcontrol->private_value & 0xff;
 429	guard(mutex)(&ice->gpio_mutex);
 430	for (i = 0; i < voices; i++) {
 431		if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) {
 432			idx = WM8766_LDA1 + ofs + i;
 433			spec->vol[ofs + i] &= WM_VOL_MUTE;
 434			spec->vol[ofs + i] |= ucontrol->value.integer.value[i];
 435			wm8766_set_vol(ice, idx,
 436				       spec->vol[ofs + i], spec->master[i]);
 437			change = 1;
 438		}
 439	}
 440	return change;
 441}
 442
 443/*
 444 * Master volume attenuation mixer control / applied to WM8776+WM8766
 445 */
 446static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
 447			      struct snd_ctl_elem_info *uinfo)
 448{
 449	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 450	uinfo->count = 2;
 451	uinfo->value.integer.min = 0;
 452	uinfo->value.integer.max = DAC_RES;
 453	return 0;
 454}
 455
 456static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
 457			     struct snd_ctl_elem_value *ucontrol)
 458{
 459	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 460	struct prodigy_hifi_spec *spec = ice->spec;
 461	int i;
 462	for (i = 0; i < 2; i++)
 463		ucontrol->value.integer.value[i] = spec->master[i];
 464	return 0;
 465}
 466
 467static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
 468			     struct snd_ctl_elem_value *ucontrol)
 469{
 470	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 471	struct prodigy_hifi_spec *spec = ice->spec;
 472	int ch, change = 0;
 473
 474	guard(mutex)(&ice->gpio_mutex);
 475	for (ch = 0; ch < 2; ch++) {
 476		if (ucontrol->value.integer.value[ch] != spec->master[ch]) {
 477			spec->master[ch] = ucontrol->value.integer.value[ch];
 478
 479			/* Apply to front DAC */
 480			wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
 481				   spec->vol[2 + ch], spec->master[ch]);
 482
 483			wm8766_set_vol(ice, WM8766_LDA1 + ch,
 484				       spec->vol[0 + ch], spec->master[ch]);
 485
 486			wm8766_set_vol(ice, WM8766_LDA2 + ch,
 487				       spec->vol[4 + ch], spec->master[ch]);
 488
 489			wm8766_set_vol(ice, WM8766_LDA3 + ch,
 490				       spec->vol[6 + ch], spec->master[ch]);
 491			change = 1;
 492		}
 493	}
 494	return change;
 495}
 496
 497
 498/* KONSTI */
 499
 500static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol,
 501				struct snd_ctl_elem_info *uinfo)
 502{
 503	static const char * const texts[32] = {
 504		"NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2,
 505		WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3,
 506		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3,
 507		WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4,
 508		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4,
 509		WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4,
 510		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
 511		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
 512		WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5,
 513		WM_AIN1 "+" WM_AIN2 "+" WM_AIN5,
 514		WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5,
 515		WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
 516		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
 517		WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5,
 518		WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
 519		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
 520		WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
 521		WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
 522		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
 523		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5
 524	};
 525
 526	return snd_ctl_enum_info(uinfo, 1, 32, texts);
 527}
 528
 529static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol,
 530			       struct snd_ctl_elem_value *ucontrol)
 531{
 532	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 533
 534	guard(mutex)(&ice->gpio_mutex);
 535	ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f;
 536	return 0;
 537}
 538
 539static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol,
 540			       struct snd_ctl_elem_value *ucontrol)
 541{
 542	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 543	unsigned short oval, nval;
 544	int change = 0;
 545
 546	guard(mutex)(&ice->gpio_mutex);
 547	oval = wm_get(ice, WM_ADC_MUX);
 548	nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0];
 549	if (nval != oval) {
 550		wm_put(ice, WM_ADC_MUX, nval);
 551		change = 1;
 552	}
 553	return change;
 554}
 555
 556/* KONSTI */
 557
 558/*
 559 * ADC gain mixer control (-64dB to 0dB)
 560 */
 561
 562#define ADC_0dB	0xcf
 563#define ADC_RES	128
 564#define ADC_MIN	(ADC_0dB - ADC_RES)
 565
 566static int wm_adc_vol_info(struct snd_kcontrol *kcontrol,
 567			   struct snd_ctl_elem_info *uinfo)
 568{
 569	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 570	uinfo->count = 2;
 571	uinfo->value.integer.min = 0;	/* mute (-64dB) */
 572	uinfo->value.integer.max = ADC_RES;	/* 0dB, 0.5dB step */
 573	return 0;
 574}
 575
 576static int wm_adc_vol_get(struct snd_kcontrol *kcontrol,
 577			  struct snd_ctl_elem_value *ucontrol)
 578{
 579	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 580	unsigned short val;
 581	int i;
 582
 583	guard(mutex)(&ice->gpio_mutex);
 584	for (i = 0; i < 2; i++) {
 585		val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
 586		val = val > ADC_MIN ? (val - ADC_MIN) : 0;
 587		ucontrol->value.integer.value[i] = val;
 588	}
 589	return 0;
 590}
 591
 592static int wm_adc_vol_put(struct snd_kcontrol *kcontrol,
 593			  struct snd_ctl_elem_value *ucontrol)
 594{
 595	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 596	unsigned short ovol, nvol;
 597	int i, idx, change = 0;
 598
 599	guard(mutex)(&ice->gpio_mutex);
 600	for (i = 0; i < 2; i++) {
 601		nvol = ucontrol->value.integer.value[i];
 602		nvol = nvol ? (nvol + ADC_MIN) : 0;
 603		idx  = WM_ADC_ATTEN_L + i;
 604		ovol = wm_get(ice, idx) & 0xff;
 605		if (ovol != nvol) {
 606			wm_put(ice, idx, nvol);
 607			change = 1;
 608		}
 609	}
 610	return change;
 611}
 612
 613/*
 614 * ADC input mux mixer control
 615 */
 616#define wm_adc_mux_info		snd_ctl_boolean_mono_info
 617
 618static int wm_adc_mux_get(struct snd_kcontrol *kcontrol,
 619			  struct snd_ctl_elem_value *ucontrol)
 620{
 621	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 622	int bit = kcontrol->private_value;
 623
 624	guard(mutex)(&ice->gpio_mutex);
 625	ucontrol->value.integer.value[0] =
 626		(wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
 627	return 0;
 628}
 629
 630static int wm_adc_mux_put(struct snd_kcontrol *kcontrol,
 631			  struct snd_ctl_elem_value *ucontrol)
 632{
 633	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 634	int bit = kcontrol->private_value;
 635	unsigned short oval, nval;
 636	int change;
 637
 638	guard(mutex)(&ice->gpio_mutex);
 639	nval = oval = wm_get(ice, WM_ADC_MUX);
 640	if (ucontrol->value.integer.value[0])
 641		nval |= (1 << bit);
 642	else
 643		nval &= ~(1 << bit);
 644	change = nval != oval;
 645	if (change) {
 646		wm_put(ice, WM_ADC_MUX, nval);
 647	}
 648	return 0;
 649}
 650
 651/*
 652 * Analog bypass (In -> Out)
 653 */
 654#define wm_bypass_info		snd_ctl_boolean_mono_info
 655
 656static int wm_bypass_get(struct snd_kcontrol *kcontrol,
 657			 struct snd_ctl_elem_value *ucontrol)
 658{
 659	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 660
 661	guard(mutex)(&ice->gpio_mutex);
 662	ucontrol->value.integer.value[0] =
 663		(wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
 664	return 0;
 665}
 666
 667static int wm_bypass_put(struct snd_kcontrol *kcontrol,
 668			 struct snd_ctl_elem_value *ucontrol)
 669{
 670	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 671	unsigned short val, oval;
 672	int change = 0;
 673
 674	guard(mutex)(&ice->gpio_mutex);
 675	val = oval = wm_get(ice, WM_OUT_MUX);
 676	if (ucontrol->value.integer.value[0])
 677		val |= 0x04;
 678	else
 679		val &= ~0x04;
 680	if (val != oval) {
 681		wm_put(ice, WM_OUT_MUX, val);
 682		change = 1;
 683	}
 684	return change;
 685}
 686
 687/*
 688 * Left/Right swap
 689 */
 690#define wm_chswap_info		snd_ctl_boolean_mono_info
 691
 692static int wm_chswap_get(struct snd_kcontrol *kcontrol,
 693			 struct snd_ctl_elem_value *ucontrol)
 694{
 695	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 696
 697	guard(mutex)(&ice->gpio_mutex);
 698	ucontrol->value.integer.value[0] =
 699			(wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
 700	return 0;
 701}
 702
 703static int wm_chswap_put(struct snd_kcontrol *kcontrol,
 704			 struct snd_ctl_elem_value *ucontrol)
 705{
 706	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 707	unsigned short val, oval;
 708	int change = 0;
 709
 710	guard(mutex)(&ice->gpio_mutex);
 711	oval = wm_get(ice, WM_DAC_CTRL1);
 712	val = oval & 0x0f;
 713	if (ucontrol->value.integer.value[0])
 714		val |= 0x60;
 715	else
 716		val |= 0x90;
 717	if (val != oval) {
 718		wm_put(ice, WM_DAC_CTRL1, val);
 719		wm_put_nocache(ice, WM_DAC_CTRL1, val);
 720		change = 1;
 721	}
 722	return change;
 723}
 724
 725
 726/*
 727 * mixers
 728 */
 729
 730static const struct snd_kcontrol_new prodigy_hifi_controls[] = {
 731	{
 732		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 733		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 734			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 735		.name = "Master Playback Volume",
 736		.info = wm_master_vol_info,
 737		.get = wm_master_vol_get,
 738		.put = wm_master_vol_put,
 739		.tlv = { .p = db_scale_wm_dac }
 740	},
 741	{
 742		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 743		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 744			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 745		.name = "Front Playback Volume",
 746		.info = wm_dac_vol_info,
 747		.get = wm_dac_vol_get,
 748		.put = wm_dac_vol_put,
 749		.tlv = { .p = db_scale_wm_dac },
 750	},
 751	{
 752		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 753		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 754			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 755		.name = "Rear Playback Volume",
 756		.info = wm8766_vol_info,
 757		.get = wm8766_vol_get,
 758		.put = wm8766_vol_put,
 759		.private_value = (2 << 8) | 0,
 760		.tlv = { .p = db_scale_wm_dac },
 761	},
 762	{
 763		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 764		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 765			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 766		.name = "Center Playback Volume",
 767		.info = wm8766_vol_info,
 768		.get = wm8766_vol_get,
 769		.put = wm8766_vol_put,
 770		.private_value = (1 << 8) | 4,
 771		.tlv = { .p = db_scale_wm_dac }
 772	},
 773	{
 774		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 775		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 776			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 777		.name = "LFE Playback Volume",
 778		.info = wm8766_vol_info,
 779		.get = wm8766_vol_get,
 780		.put = wm8766_vol_put,
 781		.private_value = (1 << 8) | 5,
 782		.tlv = { .p = db_scale_wm_dac }
 783	},
 784	{
 785		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 786		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 787			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 788		.name = "Side Playback Volume",
 789		.info = wm8766_vol_info,
 790		.get = wm8766_vol_get,
 791		.put = wm8766_vol_put,
 792		.private_value = (2 << 8) | 6,
 793		.tlv = { .p = db_scale_wm_dac },
 794	},
 795	{
 796		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 797		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 798			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 799		.name = "Capture Volume",
 800		.info = wm_adc_vol_info,
 801		.get = wm_adc_vol_get,
 802		.put = wm_adc_vol_put,
 803		.tlv = { .p = db_scale_wm_dac },
 804	},
 805	{
 806		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 807		.name = "CD Capture Switch",
 808		.info = wm_adc_mux_info,
 809		.get = wm_adc_mux_get,
 810		.put = wm_adc_mux_put,
 811		.private_value = 0,
 812	},
 813	{
 814		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 815		.name = "Line Capture Switch",
 816		.info = wm_adc_mux_info,
 817		.get = wm_adc_mux_get,
 818		.put = wm_adc_mux_put,
 819		.private_value = 1,
 820	},
 821	{
 822		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 823		.name = "Analog Bypass Switch",
 824		.info = wm_bypass_info,
 825		.get = wm_bypass_get,
 826		.put = wm_bypass_put,
 827	},
 828	{
 829		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 830		.name = "Swap Output Channels",
 831		.info = wm_chswap_info,
 832		.get = wm_chswap_get,
 833		.put = wm_chswap_put,
 834	},
 835	{
 836		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 837		.name = "Analog Capture Source",
 838		.info = wm_adc_mux_enum_info,
 839		.get = wm_adc_mux_enum_get,
 840		.put = wm_adc_mux_enum_put,
 841	},
 842};
 843
 844/*
 845 * WM codec registers
 846 */
 847static void wm_proc_regs_write(struct snd_info_entry *entry,
 848			       struct snd_info_buffer *buffer)
 849{
 850	struct snd_ice1712 *ice = entry->private_data;
 851	char line[64];
 852	unsigned int reg, val;
 853
 854	guard(mutex)(&ice->gpio_mutex);
 855	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 856		if (sscanf(line, "%x %x", &reg, &val) != 2)
 857			continue;
 858		if (reg <= 0x17 && val <= 0xffff)
 859			wm_put(ice, reg, val);
 860	}
 861}
 862
 863static void wm_proc_regs_read(struct snd_info_entry *entry,
 864			      struct snd_info_buffer *buffer)
 865{
 866	struct snd_ice1712 *ice = entry->private_data;
 867	int reg, val;
 868
 869	guard(mutex)(&ice->gpio_mutex);
 870	for (reg = 0; reg <= 0x17; reg++) {
 871		val = wm_get(ice, reg);
 872		snd_iprintf(buffer, "%02x = %04x\n", reg, val);
 873	}
 874}
 875
 876static void wm_proc_init(struct snd_ice1712 *ice)
 877{
 878	snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,
 879			     wm_proc_regs_write);
 880}
 881
 882static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
 883{
 884	unsigned int i;
 885	int err;
 886
 887	for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) {
 888		err = snd_ctl_add(ice->card,
 889				  snd_ctl_new1(&prodigy_hifi_controls[i], ice));
 890		if (err < 0)
 891			return err;
 892	}
 893
 894	wm_proc_init(ice);
 895
 896	return 0;
 897}
 898
 899static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
 900{
 901	unsigned int i;
 902	int err;
 903
 904	for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) {
 905		err = snd_ctl_add(ice->card,
 906				  snd_ctl_new1(&prodigy_hd2_controls[i], ice));
 907		if (err < 0)
 908			return err;
 909	}
 910
 911	wm_proc_init(ice);
 912
 913	return 0;
 914}
 915
 916static void wm8766_init(struct snd_ice1712 *ice)
 917{
 918	static const unsigned short wm8766_inits[] = {
 919		WM8766_RESET,	   0x0000,
 920		WM8766_DAC_CTRL,	0x0120,
 921		WM8766_INT_CTRL,	0x0022, /* I2S Normal Mode, 24 bit */
 922		WM8766_DAC_CTRL2,       0x0001,
 923		WM8766_DAC_CTRL3,       0x0080,
 924		WM8766_LDA1,	    0x0100,
 925		WM8766_LDA2,	    0x0100,
 926		WM8766_LDA3,	    0x0100,
 927		WM8766_RDA1,	    0x0100,
 928		WM8766_RDA2,	    0x0100,
 929		WM8766_RDA3,	    0x0100,
 930		WM8766_MUTE1,	   0x0000,
 931		WM8766_MUTE2,	   0x0000,
 932	};
 933	unsigned int i;
 934
 935	for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)
 936		wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]);
 937}
 938
 939static void wm8776_init(struct snd_ice1712 *ice)
 940{
 941	static const unsigned short wm8776_inits[] = {
 942		/* These come first to reduce init pop noise */
 943		WM_ADC_MUX,	0x0003,	/* ADC mute */
 944		/* 0x00c0 replaced by 0x0003 */
 945		
 946		WM_DAC_MUTE,	0x0001,	/* DAC softmute */
 947		WM_DAC_CTRL1,	0x0000,	/* DAC mute */
 948
 949		WM_POWERDOWN,	0x0008,	/* All power-up except HP */
 950		WM_RESET,	0x0000,	/* reset */
 951	};
 952	unsigned int i;
 953
 954	for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2)
 955		wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]);
 956}
 957
 958#ifdef CONFIG_PM_SLEEP
 959static int prodigy_hifi_resume(struct snd_ice1712 *ice)
 960{
 961	static const unsigned short wm8776_reinit_registers[] = {
 962		WM_MASTER_CTRL,
 963		WM_DAC_INT,
 964		WM_ADC_INT,
 965		WM_OUT_MUX,
 966		WM_HP_ATTEN_L,
 967		WM_HP_ATTEN_R,
 968		WM_PHASE_SWAP,
 969		WM_DAC_CTRL2,
 970		WM_ADC_ATTEN_L,
 971		WM_ADC_ATTEN_R,
 972		WM_ALC_CTRL1,
 973		WM_ALC_CTRL2,
 974		WM_ALC_CTRL3,
 975		WM_NOISE_GATE,
 976		WM_ADC_MUX,
 977		/* no DAC attenuation here */
 978	};
 979	struct prodigy_hifi_spec *spec = ice->spec;
 980	int i, ch;
 981
 982	guard(mutex)(&ice->gpio_mutex);
 983
 984	/* reinitialize WM8776 and re-apply old register values */
 985	wm8776_init(ice);
 986	schedule_timeout_uninterruptible(1);
 987	for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++)
 988		wm_put(ice, wm8776_reinit_registers[i],
 989		       wm_get(ice, wm8776_reinit_registers[i]));
 990
 991	/* reinitialize WM8766 and re-apply volumes for all DACs */
 992	wm8766_init(ice);
 993	for (ch = 0; ch < 2; ch++) {
 994		wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
 995			   spec->vol[2 + ch], spec->master[ch]);
 996
 997		wm8766_set_vol(ice, WM8766_LDA1 + ch,
 998			       spec->vol[0 + ch], spec->master[ch]);
 999
1000		wm8766_set_vol(ice, WM8766_LDA2 + ch,
1001			       spec->vol[4 + ch], spec->master[ch]);
1002
1003		wm8766_set_vol(ice, WM8766_LDA3 + ch,
1004			       spec->vol[6 + ch], spec->master[ch]);
1005	}
1006
1007	/* unmute WM8776 DAC */
1008	wm_put(ice, WM_DAC_MUTE, 0x00);
1009	wm_put(ice, WM_DAC_CTRL1, 0x90);
1010
1011	return 0;
1012}
1013#endif
1014
1015/*
1016 * initialize the chip
1017 */
1018static int prodigy_hifi_init(struct snd_ice1712 *ice)
1019{
1020	static const unsigned short wm8776_defaults[] = {
1021		WM_MASTER_CTRL,  0x0022, /* 256fs, slave mode */
1022		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
1023		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
1024		WM_DAC_CTRL1,	0x0090,	/* DAC L/R */
1025		WM_OUT_MUX,	0x0001,	/* OUT DAC */
1026		WM_HP_ATTEN_L,	0x0179,	/* HP 0dB */
1027		WM_HP_ATTEN_R,	0x0179,	/* HP 0dB */
1028		WM_DAC_ATTEN_L,	0x0000,	/* DAC 0dB */
1029		WM_DAC_ATTEN_L,	0x0100,	/* DAC 0dB */
1030		WM_DAC_ATTEN_R,	0x0000,	/* DAC 0dB */
1031		WM_DAC_ATTEN_R,	0x0100,	/* DAC 0dB */
1032		WM_PHASE_SWAP,	0x0000,	/* phase normal */
1033#if 0
1034		WM_DAC_MASTER,	0x0100,	/* DAC master muted */
1035#endif
1036		WM_DAC_CTRL2,	0x0000,	/* no deemphasis, no ZFLG */
1037		WM_ADC_ATTEN_L,	0x0000,	/* ADC muted */
1038		WM_ADC_ATTEN_R,	0x0000,	/* ADC muted */
1039#if 1
1040		WM_ALC_CTRL1,	0x007b,	/* */
1041		WM_ALC_CTRL2,	0x0000,	/* */
1042		WM_ALC_CTRL3,	0x0000,	/* */
1043		WM_NOISE_GATE,	0x0000,	/* */
1044#endif
1045		WM_DAC_MUTE,	0x0000,	/* DAC unmute */
1046		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */
1047	};
1048	struct prodigy_hifi_spec *spec;
1049	unsigned int i;
1050
1051	ice->vt1720 = 0;
1052	ice->vt1724 = 1;
1053
1054	ice->num_total_dacs = 8;
1055	ice->num_total_adcs = 1;
1056
1057	/* HACK - use this as the SPDIF source.
1058	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
1059	*/
1060	ice->gpio.saved[0] = 0;
1061	/* to remember the register values */
1062
1063	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1064	if (! ice->akm)
1065		return -ENOMEM;
1066	ice->akm_codecs = 1;
1067
1068	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1069	if (!spec)
1070		return -ENOMEM;
1071	ice->spec = spec;
1072
1073	/* initialize WM8776 codec */
1074	wm8776_init(ice);
1075	schedule_timeout_uninterruptible(1);
1076	for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2)
1077		wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]);
1078
1079	wm8766_init(ice);
1080
1081#ifdef CONFIG_PM_SLEEP
1082	ice->pm_resume = &prodigy_hifi_resume;
1083	ice->pm_suspend_enabled = 1;
1084#endif
1085
1086	return 0;
1087}
1088
1089
1090/*
1091 * initialize the chip
1092 */
1093static void ak4396_init(struct snd_ice1712 *ice)
1094{
1095	static const unsigned short ak4396_inits[] = {
1096		AK4396_CTRL1,	   0x87,   /* I2S Normal Mode, 24 bit */
1097		AK4396_CTRL2,	   0x02,
1098		AK4396_CTRL3,	   0x00, 
1099		AK4396_LCH_ATT,	 0x00,
1100		AK4396_RCH_ATT,	 0x00,
1101	};
1102
1103	unsigned int i;
1104
1105	/* initialize ak4396 codec */
1106	/* reset codec */
1107	ak4396_write(ice, AK4396_CTRL1, 0x86);
1108	msleep(100);
1109	ak4396_write(ice, AK4396_CTRL1, 0x87);
1110
1111	for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)
1112		ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);
1113}
1114
1115#ifdef CONFIG_PM_SLEEP
1116static int prodigy_hd2_resume(struct snd_ice1712 *ice)
1117{
1118	/* initialize ak4396 codec and restore previous mixer volumes */
1119	struct prodigy_hifi_spec *spec = ice->spec;
1120	int i;
1121
1122	guard(mutex)(&ice->gpio_mutex);
1123	ak4396_init(ice);
1124	for (i = 0; i < 2; i++)
1125		ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);
1126	return 0;
1127}
1128#endif
1129
1130static int prodigy_hd2_init(struct snd_ice1712 *ice)
1131{
1132	struct prodigy_hifi_spec *spec;
1133
1134	ice->vt1720 = 0;
1135	ice->vt1724 = 1;
1136
1137	ice->num_total_dacs = 1;
1138	ice->num_total_adcs = 1;
1139
1140	/* HACK - use this as the SPDIF source.
1141	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
1142	*/
1143	ice->gpio.saved[0] = 0;
1144	/* to remember the register values */
1145
1146	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1147	if (! ice->akm)
1148		return -ENOMEM;
1149	ice->akm_codecs = 1;
1150
1151	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1152	if (!spec)
1153		return -ENOMEM;
1154	ice->spec = spec;
1155
1156#ifdef CONFIG_PM_SLEEP
1157	ice->pm_resume = &prodigy_hd2_resume;
1158	ice->pm_suspend_enabled = 1;
1159#endif
1160
1161	ak4396_init(ice);
1162
1163	return 0;
1164}
1165
1166
1167static const unsigned char prodigy71hifi_eeprom[] = {
1168	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1169	0x80,   /* ACLINK: I2S */
1170	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1171	0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1172	0xff,   /* GPIO_DIR */
1173	0xff,   /* GPIO_DIR1 */
1174	0x5f,   /* GPIO_DIR2 */
1175	0x00,   /* GPIO_MASK */
1176	0x00,   /* GPIO_MASK1 */
1177	0x00,   /* GPIO_MASK2 */
1178	0x00,   /* GPIO_STATE */
1179	0x00,   /* GPIO_STATE1 */
1180	0x00,   /* GPIO_STATE2 */
1181};
1182
1183static const unsigned char prodigyhd2_eeprom[] = {
1184	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1185	0x80,   /* ACLINK: I2S */
1186	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1187	0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1188	0xff,   /* GPIO_DIR */
1189	0xff,   /* GPIO_DIR1 */
1190	0x5f,   /* GPIO_DIR2 */
1191	0x00,   /* GPIO_MASK */
1192	0x00,   /* GPIO_MASK1 */
1193	0x00,   /* GPIO_MASK2 */
1194	0x00,   /* GPIO_STATE */
1195	0x00,   /* GPIO_STATE1 */
1196	0x00,   /* GPIO_STATE2 */
1197};
1198
1199static const unsigned char fortissimo4_eeprom[] = {
1200	0x43,   /* SYSCONF: clock 512, ADC, 4DACs */	
1201	0x80,   /* ACLINK: I2S */
1202	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1203	0xc1,   /* SPDIF: out-en, out-int */
1204	0xff,   /* GPIO_DIR */
1205	0xff,   /* GPIO_DIR1 */
1206	0x5f,   /* GPIO_DIR2 */
1207	0x00,   /* GPIO_MASK */
1208	0x00,   /* GPIO_MASK1 */
1209	0x00,   /* GPIO_MASK2 */
1210	0x00,   /* GPIO_STATE */
1211	0x00,   /* GPIO_STATE1 */
1212	0x00,   /* GPIO_STATE2 */
1213};
1214
1215/* entry point */
1216struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
1217	{
1218		.subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
1219		.name = "Audiotrak Prodigy 7.1 HiFi",
1220		.model = "prodigy71hifi",
1221		.chip_init = prodigy_hifi_init,
1222		.build_controls = prodigy_hifi_add_controls,
1223		.eeprom_size = sizeof(prodigy71hifi_eeprom),
1224		.eeprom_data = prodigy71hifi_eeprom,
1225		.driver = "Prodigy71HIFI",
1226	},
1227	{
1228	.subvendor = VT1724_SUBDEVICE_PRODIGY_HD2,
1229	.name = "Audiotrak Prodigy HD2",
1230	.model = "prodigyhd2",
1231	.chip_init = prodigy_hd2_init,
1232	.build_controls = prodigy_hd2_add_controls,
1233	.eeprom_size = sizeof(prodigyhd2_eeprom),
1234	.eeprom_data = prodigyhd2_eeprom,
1235	.driver = "Prodigy71HD2",
1236	},
1237	{
1238		.subvendor = VT1724_SUBDEVICE_FORTISSIMO4,
1239		.name = "Hercules Fortissimo IV",
1240		.model = "fortissimo4",
1241		.chip_init = prodigy_hifi_init,
1242		.build_controls = prodigy_hifi_add_controls,
1243		.eeprom_size = sizeof(fortissimo4_eeprom),
1244		.eeprom_data = fortissimo4_eeprom,
1245		.driver = "Fortissimo4",
1246	},
1247	{ } /* terminator */
1248};
1249
~/ Read-only file preview.