2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Terratec Aureon cards
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
26 * both wm and akm codecs are pretty similar, so we can integrate
27 * both controls in the future, once if wm codecs are reused in
30 * - DAC digital volumes are not implemented in the mixer.
31 * if they show better response than DAC analog volumes, we can use them
34 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
37 * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
38 * added 64x/128x oversampling switch (should be 64x only for 96khz)
39 * fixed some recording labels (still need to check the rest)
40 * recording is working probably thanks to correct wm8770 initialization
42 * version 0.5: Initial release:
43 * working: analog output, mixer, headphone amplifier switch
44 * not working: prety much everything else, at least i could verify that
45 * we have no digital output, no capture, pretty bad clicks and poops
46 * on mixer switch and other coll stuff.
50 #include <sound/driver.h>
52 #include <linux/delay.h>
53 #include <linux/interrupt.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <linux/mutex.h>
58 #include <sound/core.h>
63 #include <sound/tlv.h>
65 /* WM8770 registers */
66 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
67 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
68 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
69 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
70 #define WM_PHASE_SWAP 0x12 /* DAC phase */
71 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
72 #define WM_MUTE 0x14 /* mute controls */
73 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
74 #define WM_INT_CTRL 0x16 /* interface control */
75 #define WM_MASTER 0x17 /* master clock and mode */
76 #define WM_POWERDOWN 0x18 /* power-down controls */
77 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
78 #define WM_ADC_MUX 0x1b /* input MUX */
79 #define WM_OUT_MUX1 0x1c /* output MUX */
80 #define WM_OUT_MUX2 0x1e /* output MUX */
81 #define WM_RESET 0x1f /* software reset */
83 /* CS8415A registers */
84 #define CS8415_CTRL1 0x01
85 #define CS8415_CTRL2 0x02
86 #define CS8415_QSUB 0x14
87 #define CS8415_RATIO 0x1E
88 #define CS8415_C_BUFFER 0x20
89 #define CS8415_ID 0x7F
91 /* PCA9554 registers */
92 #define PCA9554_DEV 0x40 /* I2C device address */
93 #define PCA9554_IN 0x00 /* input port */
94 #define PCA9554_OUT 0x01 /* output port */
95 #define PCA9554_INVERT 0x02 /* input invert */
96 #define PCA9554_DIR 0x03 /* port directions */
99 * Aureon Universe additional controls using PCA9554
103 * Send data to pca9554
105 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
110 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
111 unsigned char val = 0;
113 tmp = snd_ice1712_gpio_read(ice);
115 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
116 AUREON_WM_RW|AUREON_WM_CS|
119 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
121 tmp &= ~AUREON_SPI_MOSI;
122 tmp &= ~AUREON_SPI_CLK;
123 snd_ice1712_gpio_write(ice, tmp);
127 * send i2c stop condition and start condition
128 * to obtain sane state
130 tmp |= AUREON_SPI_CLK;
131 snd_ice1712_gpio_write(ice, tmp);
133 tmp |= AUREON_SPI_MOSI;
134 snd_ice1712_gpio_write(ice, tmp);
136 tmp &= ~AUREON_SPI_MOSI;
137 snd_ice1712_gpio_write(ice, tmp);
139 tmp &= ~AUREON_SPI_CLK;
140 snd_ice1712_gpio_write(ice, tmp);
143 * send device address, command and value,
144 * skipping ack cycles inbetween
146 for (j = 0; j < 3; j++) {
148 case 0: val = dev; break;
149 case 1: val = reg; break;
150 case 2: val = data; break;
152 for (i = 7; i >= 0; i--) {
153 tmp &= ~AUREON_SPI_CLK;
154 snd_ice1712_gpio_write(ice, tmp);
157 tmp |= AUREON_SPI_MOSI;
159 tmp &= ~AUREON_SPI_MOSI;
160 snd_ice1712_gpio_write(ice, tmp);
162 tmp |= AUREON_SPI_CLK;
163 snd_ice1712_gpio_write(ice, tmp);
166 tmp &= ~AUREON_SPI_CLK;
167 snd_ice1712_gpio_write(ice, tmp);
169 tmp |= AUREON_SPI_CLK;
170 snd_ice1712_gpio_write(ice, tmp);
172 tmp &= ~AUREON_SPI_CLK;
173 snd_ice1712_gpio_write(ice, tmp);
176 tmp &= ~AUREON_SPI_CLK;
177 snd_ice1712_gpio_write(ice, tmp);
179 tmp &= ~AUREON_SPI_MOSI;
180 snd_ice1712_gpio_write(ice, tmp);
182 tmp |= AUREON_SPI_CLK;
183 snd_ice1712_gpio_write(ice, tmp);
185 tmp |= AUREON_SPI_MOSI;
186 snd_ice1712_gpio_write(ice, tmp);
190 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_info *uinfo)
193 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
195 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
197 uinfo->value.enumerated.items = 3;
198 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
199 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
204 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
205 struct snd_ctl_elem_value *ucontrol)
207 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
208 ucontrol->value.enumerated.item[0] = ice->spec.aureon.pca9554_out;
212 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
215 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216 unsigned char oval, nval;
219 nval = ucontrol->value.enumerated.item[0];
222 snd_ice1712_save_gpio_status(ice);
223 oval = ice->spec.aureon.pca9554_out;
224 if ((change = (oval != nval))) {
225 aureon_pca9554_write(ice, PCA9554_OUT, nval);
226 ice->spec.aureon.pca9554_out = nval;
228 snd_ice1712_restore_gpio_status(ice);
234 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
239 /* Send address to XILINX chip */
240 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
241 snd_ice1712_gpio_write(ice, tmp);
243 tmp |= AUREON_AC97_ADDR;
244 snd_ice1712_gpio_write(ice, tmp);
246 tmp &= ~AUREON_AC97_ADDR;
247 snd_ice1712_gpio_write(ice, tmp);
250 /* Send low-order byte to XILINX chip */
251 tmp &= ~AUREON_AC97_DATA_MASK;
252 tmp |= val & AUREON_AC97_DATA_MASK;
253 snd_ice1712_gpio_write(ice, tmp);
255 tmp |= AUREON_AC97_DATA_LOW;
256 snd_ice1712_gpio_write(ice, tmp);
258 tmp &= ~AUREON_AC97_DATA_LOW;
259 snd_ice1712_gpio_write(ice, tmp);
262 /* Send high-order byte to XILINX chip */
263 tmp &= ~AUREON_AC97_DATA_MASK;
264 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
266 snd_ice1712_gpio_write(ice, tmp);
268 tmp |= AUREON_AC97_DATA_HIGH;
269 snd_ice1712_gpio_write(ice, tmp);
271 tmp &= ~AUREON_AC97_DATA_HIGH;
272 snd_ice1712_gpio_write(ice, tmp);
275 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
276 tmp |= AUREON_AC97_COMMIT;
277 snd_ice1712_gpio_write(ice, tmp);
279 tmp &= ~AUREON_AC97_COMMIT;
280 snd_ice1712_gpio_write(ice, tmp);
283 /* Store the data in out private buffer */
284 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
287 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
289 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
293 * Initialize STAC9744 chip
295 static int aureon_ac97_init (struct snd_ice1712 *ice)
298 static const unsigned short ac97_defaults[] = {
322 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
323 snd_ice1712_gpio_write(ice, tmp);
326 tmp &= ~AUREON_AC97_RESET;
327 snd_ice1712_gpio_write(ice, tmp);
330 tmp |= AUREON_AC97_RESET;
331 snd_ice1712_gpio_write(ice, tmp);
334 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
335 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
336 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
338 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
343 #define AUREON_AC97_STEREO 0x80
346 * AC'97 volume controls
348 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
350 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
351 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
352 uinfo->value.integer.min = 0;
353 uinfo->value.integer.max = 31;
357 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
359 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
362 mutex_lock(&ice->gpio_mutex);
364 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
365 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
366 if (kcontrol->private_value & AUREON_AC97_STEREO)
367 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
369 mutex_unlock(&ice->gpio_mutex);
373 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
375 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
376 unsigned short ovol, nvol;
379 snd_ice1712_save_gpio_status(ice);
381 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
382 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
383 if (kcontrol->private_value & AUREON_AC97_STEREO)
384 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
385 nvol |= ovol & ~0x1F1F;
387 if ((change = (ovol != nvol)))
388 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
390 snd_ice1712_restore_gpio_status(ice);
396 * AC'97 mute controls
398 #define aureon_ac97_mute_info snd_ctl_boolean_mono_info
400 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
402 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
404 mutex_lock(&ice->gpio_mutex);
406 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
408 mutex_unlock(&ice->gpio_mutex);
412 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
414 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
415 unsigned short ovol, nvol;
418 snd_ice1712_save_gpio_status(ice);
420 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
421 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
423 if ((change = (ovol != nvol)))
424 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
426 snd_ice1712_restore_gpio_status(ice);
432 * AC'97 mute controls
434 #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
436 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
438 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
440 mutex_lock(&ice->gpio_mutex);
442 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
444 mutex_unlock(&ice->gpio_mutex);
448 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
450 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
451 unsigned short ovol, nvol;
454 snd_ice1712_save_gpio_status(ice);
456 ovol = aureon_ac97_read(ice, AC97_MIC);
457 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
459 if ((change = (ovol != nvol)))
460 aureon_ac97_write(ice, AC97_MIC, nvol);
462 snd_ice1712_restore_gpio_status(ice);
468 * write data in the SPI mode
470 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
474 unsigned int mosi, clk;
476 tmp = snd_ice1712_gpio_read(ice);
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;
485 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
486 AUREON_WM_CS|AUREON_CS8415_CS));
487 mosi = AUREON_SPI_MOSI;
488 clk = AUREON_SPI_CLK;
494 snd_ice1712_gpio_write(ice, tmp);
497 for (i = bits - 1; i >= 0; i--) {
499 snd_ice1712_gpio_write(ice, tmp);
505 snd_ice1712_gpio_write(ice, tmp);
508 snd_ice1712_gpio_write(ice, tmp);
514 snd_ice1712_gpio_write(ice, tmp);
517 snd_ice1712_gpio_write(ice, tmp);
522 * Read data in SPI mode
524 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
528 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
529 snd_ice1712_gpio_write(ice, tmp);
531 snd_ice1712_gpio_write(ice, tmp);
534 for (i=bits-1; i>=0; i--) {
536 tmp |= AUREON_SPI_MOSI;
538 tmp &= ~AUREON_SPI_MOSI;
539 snd_ice1712_gpio_write(ice, tmp);
542 tmp |= AUREON_SPI_CLK;
543 snd_ice1712_gpio_write(ice, tmp);
546 tmp &= ~AUREON_SPI_CLK;
547 snd_ice1712_gpio_write(ice, tmp);
551 for (j=0; j<size; j++) {
552 unsigned char outdata = 0;
553 for (i=7; i>=0; i--) {
554 tmp = snd_ice1712_gpio_read(ice);
556 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
559 tmp |= AUREON_SPI_CLK;
560 snd_ice1712_gpio_write(ice, tmp);
563 tmp &= ~AUREON_SPI_CLK;
564 snd_ice1712_gpio_write(ice, tmp);
571 snd_ice1712_gpio_write(ice, tmp);
574 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
576 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
577 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
581 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
582 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
583 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
586 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
587 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
591 * get the current register value of WM codec
593 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
596 return ((unsigned short)ice->akm[0].images[reg] << 8) |
597 ice->akm[0].images[reg + 1];
601 * set the register value of WM codec
603 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
605 aureon_spi_write(ice,
606 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
607 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
608 PRODIGY_WM_CS : AUREON_WM_CS),
609 (reg << 9) | (val & 0x1ff), 16);
613 * set the register value of WM codec and remember it
615 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
617 wm_put_nocache(ice, reg, val);
619 ice->akm[0].images[reg] = val >> 8;
620 ice->akm[0].images[reg + 1] = val;
625 #define aureon_mono_bool_info snd_ctl_boolean_mono_info
628 * AC'97 master playback mute controls (Mute on WM8770 chip)
630 #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
632 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
634 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
636 mutex_lock(&ice->gpio_mutex);
638 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
640 mutex_unlock(&ice->gpio_mutex);
644 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
645 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
646 unsigned short ovol, nvol;
649 snd_ice1712_save_gpio_status(ice);
651 ovol = wm_get(ice, WM_OUT_MUX1);
652 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
653 if ((change = (ovol != nvol)))
654 wm_put(ice, WM_OUT_MUX1, nvol);
656 snd_ice1712_restore_gpio_status(ice);
661 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
662 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
663 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
664 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
665 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
668 * Logarithmic volume values for WM8770
669 * Computed as 20 * Log10(255 / x)
671 static const unsigned char wm_vol[256] = {
672 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
673 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
674 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
675 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
676 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
677 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
678 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
679 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
680 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
681 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
682 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
686 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
687 #define WM_VOL_MUTE 0x8000
689 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
693 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
696 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
698 wm_put(ice, index, nvol);
699 wm_put_nocache(ice, index, 0x180 | nvol);
705 #define wm_pcm_mute_info snd_ctl_boolean_mono_info
707 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
709 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
711 mutex_lock(&ice->gpio_mutex);
712 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
713 mutex_unlock(&ice->gpio_mutex);
717 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
719 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
720 unsigned short nval, oval;
723 snd_ice1712_save_gpio_status(ice);
724 oval = wm_get(ice, WM_MUTE);
725 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
726 if ((change = (nval != oval)))
727 wm_put(ice, WM_MUTE, nval);
728 snd_ice1712_restore_gpio_status(ice);
734 * Master volume attenuation mixer control
736 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
738 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
740 uinfo->value.integer.min = 0;
741 uinfo->value.integer.max = WM_VOL_MAX;
745 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
747 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
750 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
754 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
756 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
759 snd_ice1712_save_gpio_status(ice);
760 for (ch = 0; ch < 2; ch++) {
761 unsigned int vol = ucontrol->value.integer.value[ch];
762 if (vol > WM_VOL_MAX)
764 vol |= ice->spec.aureon.master[ch] & WM_VOL_MUTE;
765 if (vol != ice->spec.aureon.master[ch]) {
767 ice->spec.aureon.master[ch] = vol;
768 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
769 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
770 ice->spec.aureon.vol[dac + ch],
771 ice->spec.aureon.master[ch]);
775 snd_ice1712_restore_gpio_status(ice);
780 * DAC volume attenuation mixer control
782 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
784 int voices = kcontrol->private_value >> 8;
785 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
786 uinfo->count = voices;
787 uinfo->value.integer.min = 0; /* mute (-101dB) */
788 uinfo->value.integer.max = 0x7F; /* 0dB */
792 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
794 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
797 voices = kcontrol->private_value >> 8;
798 ofs = kcontrol->private_value & 0xff;
799 for (i = 0; i < voices; i++)
800 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
804 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
806 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
807 int i, idx, ofs, voices;
810 voices = kcontrol->private_value >> 8;
811 ofs = kcontrol->private_value & 0xff;
812 snd_ice1712_save_gpio_status(ice);
813 for (i = 0; i < voices; i++) {
814 unsigned int vol = ucontrol->value.integer.value[i];
817 vol |= ice->spec.aureon.vol[ofs+i];
818 if (vol != ice->spec.aureon.vol[ofs+i]) {
819 ice->spec.aureon.vol[ofs+i] = vol;
820 idx = WM_DAC_ATTEN + ofs + i;
821 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
822 ice->spec.aureon.master[i]);
826 snd_ice1712_restore_gpio_status(ice);
831 * WM8770 mute control
833 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
834 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
835 uinfo->count = kcontrol->private_value >> 8;
836 uinfo->value.integer.min = 0;
837 uinfo->value.integer.max = 1;
841 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
843 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
846 voices = kcontrol->private_value >> 8;
847 ofs = kcontrol->private_value & 0xFF;
849 for (i = 0; i < voices; i++)
850 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
854 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
856 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
857 int change = 0, voices, ofs, i;
859 voices = kcontrol->private_value >> 8;
860 ofs = kcontrol->private_value & 0xFF;
862 snd_ice1712_save_gpio_status(ice);
863 for (i = 0; i < voices; i++) {
864 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
865 if (ucontrol->value.integer.value[i] != val) {
866 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
867 ice->spec.aureon.vol[ofs + i] |=
868 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
869 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
870 ice->spec.aureon.master[i]);
874 snd_ice1712_restore_gpio_status(ice);
880 * WM8770 master mute control
882 #define wm_master_mute_info snd_ctl_boolean_stereo_info
884 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
886 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
888 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
889 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
893 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
895 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
898 snd_ice1712_save_gpio_status(ice);
899 for (i = 0; i < 2; i++) {
900 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
901 if (ucontrol->value.integer.value[i] != val) {
903 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
904 ice->spec.aureon.master[i] |=
905 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
906 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
907 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
908 ice->spec.aureon.vol[dac + i],
909 ice->spec.aureon.master[i]);
913 snd_ice1712_restore_gpio_status(ice);
918 /* digital master volume */
920 #define PCM_RES 128 /* -64dB */
921 #define PCM_MIN (PCM_0dB - PCM_RES)
922 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
924 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
926 uinfo->value.integer.min = 0; /* mute (-64dB) */
927 uinfo->value.integer.max = PCM_RES; /* 0dB */
931 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
933 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
936 mutex_lock(&ice->gpio_mutex);
937 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
938 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
939 ucontrol->value.integer.value[0] = val;
940 mutex_unlock(&ice->gpio_mutex);
944 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
946 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
947 unsigned short ovol, nvol;
950 nvol = ucontrol->value.integer.value[0];
953 snd_ice1712_save_gpio_status(ice);
954 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
955 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
957 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
958 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
961 snd_ice1712_restore_gpio_status(ice);
968 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
970 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
972 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
976 mutex_lock(&ice->gpio_mutex);
977 for (i = 0; i < 2; i++) {
978 val = wm_get(ice, WM_ADC_GAIN + i);
979 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
981 mutex_unlock(&ice->gpio_mutex);
985 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
987 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
988 unsigned short new, old;
991 snd_ice1712_save_gpio_status(ice);
992 for (i = 0; i < 2; i++) {
993 old = wm_get(ice, WM_ADC_GAIN + i);
994 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
996 wm_put(ice, WM_ADC_GAIN + i, new);
1000 snd_ice1712_restore_gpio_status(ice);
1006 * ADC gain mixer control
1008 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1010 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1012 uinfo->value.integer.min = 0; /* -12dB */
1013 uinfo->value.integer.max = 0x1f; /* 19dB */
1017 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1019 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1023 mutex_lock(&ice->gpio_mutex);
1024 for (i = 0; i < 2; i++) {
1025 idx = WM_ADC_GAIN + i;
1026 vol = wm_get(ice, idx) & 0x1f;
1027 ucontrol->value.integer.value[i] = vol;
1029 mutex_unlock(&ice->gpio_mutex);
1033 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1035 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1037 unsigned short ovol, nvol;
1040 snd_ice1712_save_gpio_status(ice);
1041 for (i = 0; i < 2; i++) {
1042 idx = WM_ADC_GAIN + i;
1043 nvol = ucontrol->value.integer.value[i] & 0x1f;
1044 ovol = wm_get(ice, idx);
1045 if ((ovol & 0x1f) != nvol) {
1046 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1050 snd_ice1712_restore_gpio_status(ice);
1055 * ADC input mux mixer control
1057 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1059 static const char * const texts[] = {
1066 static const char * const universe_texts[] = {
1076 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1078 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1080 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1081 uinfo->value.enumerated.items = 8;
1082 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1083 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1084 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1087 uinfo->value.enumerated.items = 5;
1088 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1089 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1090 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1095 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1097 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1100 mutex_lock(&ice->gpio_mutex);
1101 val = wm_get(ice, WM_ADC_MUX);
1102 ucontrol->value.enumerated.item[0] = val & 7;
1103 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1104 mutex_unlock(&ice->gpio_mutex);
1108 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1110 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1111 unsigned short oval, nval;
1114 snd_ice1712_save_gpio_status(ice);
1115 oval = wm_get(ice, WM_ADC_MUX);
1116 nval = oval & ~0x77;
1117 nval |= ucontrol->value.enumerated.item[0] & 7;
1118 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1119 change = (oval != nval);
1121 wm_put(ice, WM_ADC_MUX, nval);
1122 snd_ice1712_restore_gpio_status(ice);
1129 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1131 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1132 static const char * const aureon_texts[] = {
1136 static const char * const prodigy_texts[] = {
1140 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1142 uinfo->value.enumerated.items = 2;
1143 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1144 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1145 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1146 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1148 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1152 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1154 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1156 //snd_ice1712_save_gpio_status(ice);
1157 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1158 ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1159 //snd_ice1712_restore_gpio_status(ice);
1163 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1165 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1166 unsigned short oval, nval;
1169 snd_ice1712_save_gpio_status(ice);
1170 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1171 nval = oval & ~0x07;
1172 nval |= ucontrol->value.enumerated.item[0] & 7;
1173 change = (oval != nval);
1175 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1176 snd_ice1712_restore_gpio_status(ice);
1177 ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1181 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1183 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1185 uinfo->value.integer.min = 0;
1186 uinfo->value.integer.max = 192000;
1190 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1192 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1193 unsigned char ratio;
1194 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1195 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1202 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1204 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1206 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1207 snd_ice1712_save_gpio_status(ice);
1208 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1209 snd_ice1712_restore_gpio_status(ice);
1213 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1215 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1216 unsigned char oval, nval;
1218 snd_ice1712_save_gpio_status(ice);
1219 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1220 if (ucontrol->value.integer.value[0])
1221 nval = oval & ~0x20;
1224 if ((change = (oval != nval)))
1225 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1226 snd_ice1712_restore_gpio_status(ice);
1231 * CS8415A Q-Sub info
1233 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1234 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1239 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1240 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1242 snd_ice1712_save_gpio_status(ice);
1243 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1244 snd_ice1712_restore_gpio_status(ice);
1249 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1250 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1255 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1256 memset(ucontrol->value.iec958.status, 0xFF, 24);
1260 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1261 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1263 snd_ice1712_save_gpio_status(ice);
1264 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1265 snd_ice1712_restore_gpio_status(ice);
1270 * Headphone Amplifier
1272 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1274 unsigned int tmp, tmp2;
1276 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1278 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1279 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1280 tmp |= AUREON_HP_SEL;
1282 tmp |= PRODIGY_HP_SEL;
1284 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1285 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1286 tmp &= ~ AUREON_HP_SEL;
1288 tmp &= ~ PRODIGY_HP_SEL;
1290 snd_ice1712_gpio_write(ice, tmp);
1296 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1298 unsigned int tmp = snd_ice1712_gpio_read(ice);
1300 return ( tmp & AUREON_HP_SEL )!= 0;
1303 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1305 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1307 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1309 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1314 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1316 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1318 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1325 #define aureon_deemp_info snd_ctl_boolean_mono_info
1327 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1329 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1330 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1334 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1336 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1338 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1339 if (ucontrol->value.integer.value[0])
1343 if (temp != temp2) {
1344 wm_put(ice, WM_DAC_CTRL2, temp);
1353 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1355 static const char * const texts[2] = { "128x", "64x" };
1357 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1359 uinfo->value.enumerated.items = 2;
1361 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1362 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1363 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1368 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1370 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1371 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1375 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1378 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1380 temp2 = temp = wm_get(ice, WM_MASTER);
1382 if (ucontrol->value.enumerated.item[0])
1387 if (temp != temp2) {
1388 wm_put(ice, WM_MASTER, temp);
1398 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1401 .name = "Master Playback Switch",
1402 .info = wm_master_mute_info,
1403 .get = wm_master_mute_get,
1404 .put = wm_master_mute_put
1407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1408 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1409 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1410 .name = "Master Playback Volume",
1411 .info = wm_master_vol_info,
1412 .get = wm_master_vol_get,
1413 .put = wm_master_vol_put,
1414 .tlv = { .p = db_scale_wm_dac }
1417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1418 .name = "Front Playback Switch",
1419 .info = wm_mute_info,
1422 .private_value = (2 << 8) | 0
1425 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1426 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1427 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1428 .name = "Front Playback Volume",
1429 .info = wm_vol_info,
1432 .private_value = (2 << 8) | 0,
1433 .tlv = { .p = db_scale_wm_dac }
1436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1437 .name = "Rear Playback Switch",
1438 .info = wm_mute_info,
1441 .private_value = (2 << 8) | 2
1444 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1445 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1446 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1447 .name = "Rear Playback Volume",
1448 .info = wm_vol_info,
1451 .private_value = (2 << 8) | 2,
1452 .tlv = { .p = db_scale_wm_dac }
1455 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1456 .name = "Center Playback Switch",
1457 .info = wm_mute_info,
1460 .private_value = (1 << 8) | 4
1463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1464 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1465 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1466 .name = "Center Playback Volume",
1467 .info = wm_vol_info,
1470 .private_value = (1 << 8) | 4,
1471 .tlv = { .p = db_scale_wm_dac }
1474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475 .name = "LFE Playback Switch",
1476 .info = wm_mute_info,
1479 .private_value = (1 << 8) | 5
1482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1483 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1484 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1485 .name = "LFE Playback Volume",
1486 .info = wm_vol_info,
1489 .private_value = (1 << 8) | 5,
1490 .tlv = { .p = db_scale_wm_dac }
1493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1494 .name = "Side Playback Switch",
1495 .info = wm_mute_info,
1498 .private_value = (2 << 8) | 6
1501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1502 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1503 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1504 .name = "Side Playback Volume",
1505 .info = wm_vol_info,
1508 .private_value = (2 << 8) | 6,
1509 .tlv = { .p = db_scale_wm_dac }
1513 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1516 .name = "PCM Playback Switch",
1517 .info = wm_pcm_mute_info,
1518 .get = wm_pcm_mute_get,
1519 .put = wm_pcm_mute_put
1522 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1523 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1524 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1525 .name = "PCM Playback Volume",
1526 .info = wm_pcm_vol_info,
1527 .get = wm_pcm_vol_get,
1528 .put = wm_pcm_vol_put,
1529 .tlv = { .p = db_scale_wm_pcm }
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533 .name = "Capture Switch",
1534 .info = wm_adc_mute_info,
1535 .get = wm_adc_mute_get,
1536 .put = wm_adc_mute_put,
1539 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1540 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1541 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1542 .name = "Capture Volume",
1543 .info = wm_adc_vol_info,
1544 .get = wm_adc_vol_get,
1545 .put = wm_adc_vol_put,
1546 .tlv = { .p = db_scale_wm_adc }
1549 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1550 .name = "Capture Source",
1551 .info = wm_adc_mux_info,
1552 .get = wm_adc_mux_get,
1553 .put = wm_adc_mux_put,
1557 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1558 .name = "External Amplifier",
1559 .info = aureon_hpamp_info,
1560 .get = aureon_hpamp_get,
1561 .put = aureon_hpamp_put
1564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1565 .name = "DAC Deemphasis Switch",
1566 .info = aureon_deemp_info,
1567 .get = aureon_deemp_get,
1568 .put = aureon_deemp_put
1571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572 .name = "ADC Oversampling",
1573 .info = aureon_oversampling_info,
1574 .get = aureon_oversampling_get,
1575 .put = aureon_oversampling_put
1579 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1581 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1582 .name = "AC97 Playback Switch",
1583 .info = aureon_ac97_mmute_info,
1584 .get = aureon_ac97_mmute_get,
1585 .put = aureon_ac97_mmute_put,
1586 .private_value = AC97_MASTER
1589 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1590 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1591 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1592 .name = "AC97 Playback Volume",
1593 .info = aureon_ac97_vol_info,
1594 .get = aureon_ac97_vol_get,
1595 .put = aureon_ac97_vol_put,
1596 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1597 .tlv = { .p = db_scale_ac97_master }
1600 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1601 .name = "CD Playback Switch",
1602 .info = aureon_ac97_mute_info,
1603 .get = aureon_ac97_mute_get,
1604 .put = aureon_ac97_mute_put,
1605 .private_value = AC97_CD
1608 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1609 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1610 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1611 .name = "CD Playback Volume",
1612 .info = aureon_ac97_vol_info,
1613 .get = aureon_ac97_vol_get,
1614 .put = aureon_ac97_vol_put,
1615 .private_value = AC97_CD|AUREON_AC97_STEREO,
1616 .tlv = { .p = db_scale_ac97_gain }
1619 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1620 .name = "Aux Playback Switch",
1621 .info = aureon_ac97_mute_info,
1622 .get = aureon_ac97_mute_get,
1623 .put = aureon_ac97_mute_put,
1624 .private_value = AC97_AUX,
1627 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1628 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1629 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1630 .name = "Aux Playback Volume",
1631 .info = aureon_ac97_vol_info,
1632 .get = aureon_ac97_vol_get,
1633 .put = aureon_ac97_vol_put,
1634 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1635 .tlv = { .p = db_scale_ac97_gain }
1638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1639 .name = "Line Playback Switch",
1640 .info = aureon_ac97_mute_info,
1641 .get = aureon_ac97_mute_get,
1642 .put = aureon_ac97_mute_put,
1643 .private_value = AC97_LINE
1646 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1647 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1648 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1649 .name = "Line Playback Volume",
1650 .info = aureon_ac97_vol_info,
1651 .get = aureon_ac97_vol_get,
1652 .put = aureon_ac97_vol_put,
1653 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1654 .tlv = { .p = db_scale_ac97_gain }
1657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1658 .name = "Mic Playback Switch",
1659 .info = aureon_ac97_mute_info,
1660 .get = aureon_ac97_mute_get,
1661 .put = aureon_ac97_mute_put,
1662 .private_value = AC97_MIC
1665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1666 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1667 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1668 .name = "Mic Playback Volume",
1669 .info = aureon_ac97_vol_info,
1670 .get = aureon_ac97_vol_get,
1671 .put = aureon_ac97_vol_put,
1672 .private_value = AC97_MIC,
1673 .tlv = { .p = db_scale_ac97_gain }
1676 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1677 .name = "Mic Boost (+20dB)",
1678 .info = aureon_ac97_micboost_info,
1679 .get = aureon_ac97_micboost_get,
1680 .put = aureon_ac97_micboost_put
1684 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1686 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1687 .name = "AC97 Playback Switch",
1688 .info = aureon_ac97_mmute_info,
1689 .get = aureon_ac97_mmute_get,
1690 .put = aureon_ac97_mmute_put,
1691 .private_value = AC97_MASTER
1694 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1695 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1696 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1697 .name = "AC97 Playback Volume",
1698 .info = aureon_ac97_vol_info,
1699 .get = aureon_ac97_vol_get,
1700 .put = aureon_ac97_vol_put,
1701 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1702 .tlv = { .p = db_scale_ac97_master }
1705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1706 .name = "CD Playback Switch",
1707 .info = aureon_ac97_mute_info,
1708 .get = aureon_ac97_mute_get,
1709 .put = aureon_ac97_mute_put,
1710 .private_value = AC97_AUX
1713 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1714 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1715 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1716 .name = "CD Playback Volume",
1717 .info = aureon_ac97_vol_info,
1718 .get = aureon_ac97_vol_get,
1719 .put = aureon_ac97_vol_put,
1720 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1721 .tlv = { .p = db_scale_ac97_gain }
1724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1725 .name = "Phono Playback Switch",
1726 .info = aureon_ac97_mute_info,
1727 .get = aureon_ac97_mute_get,
1728 .put = aureon_ac97_mute_put,
1729 .private_value = AC97_CD
1732 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1733 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1734 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1735 .name = "Phono Playback Volume",
1736 .info = aureon_ac97_vol_info,
1737 .get = aureon_ac97_vol_get,
1738 .put = aureon_ac97_vol_put,
1739 .private_value = AC97_CD|AUREON_AC97_STEREO,
1740 .tlv = { .p = db_scale_ac97_gain }
1743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1744 .name = "Line Playback Switch",
1745 .info = aureon_ac97_mute_info,
1746 .get = aureon_ac97_mute_get,
1747 .put = aureon_ac97_mute_put,
1748 .private_value = AC97_LINE
1751 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1752 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1753 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1754 .name = "Line Playback Volume",
1755 .info = aureon_ac97_vol_info,
1756 .get = aureon_ac97_vol_get,
1757 .put = aureon_ac97_vol_put,
1758 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1759 .tlv = { .p = db_scale_ac97_gain }
1762 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1763 .name = "Mic Playback Switch",
1764 .info = aureon_ac97_mute_info,
1765 .get = aureon_ac97_mute_get,
1766 .put = aureon_ac97_mute_put,
1767 .private_value = AC97_MIC
1770 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1771 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1772 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1773 .name = "Mic Playback Volume",
1774 .info = aureon_ac97_vol_info,
1775 .get = aureon_ac97_vol_get,
1776 .put = aureon_ac97_vol_put,
1777 .private_value = AC97_MIC,
1778 .tlv = { .p = db_scale_ac97_gain }
1781 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1782 .name = "Mic Boost (+20dB)",
1783 .info = aureon_ac97_micboost_info,
1784 .get = aureon_ac97_micboost_get,
1785 .put = aureon_ac97_micboost_put
1788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1789 .name = "Aux Playback Switch",
1790 .info = aureon_ac97_mute_info,
1791 .get = aureon_ac97_mute_get,
1792 .put = aureon_ac97_mute_put,
1793 .private_value = AC97_VIDEO,
1796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1797 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1798 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1799 .name = "Aux Playback Volume",
1800 .info = aureon_ac97_vol_info,
1801 .get = aureon_ac97_vol_get,
1802 .put = aureon_ac97_vol_put,
1803 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1804 .tlv = { .p = db_scale_ac97_gain }
1807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1808 .name = "Aux Source",
1809 .info = aureon_universe_inmux_info,
1810 .get = aureon_universe_inmux_get,
1811 .put = aureon_universe_inmux_put
1816 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1818 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1819 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1820 .info = aureon_cs8415_mute_info,
1821 .get = aureon_cs8415_mute_get,
1822 .put = aureon_cs8415_mute_put
1825 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1826 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1827 .info = aureon_cs8415_mux_info,
1828 .get = aureon_cs8415_mux_get,
1829 .put = aureon_cs8415_mux_put,
1832 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1833 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1834 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1835 .info = aureon_cs8415_qsub_info,
1836 .get = aureon_cs8415_qsub_get,
1839 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1840 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1841 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1842 .info = aureon_cs8415_spdif_info,
1843 .get = aureon_cs8415_mask_get
1846 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1847 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1848 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1849 .info = aureon_cs8415_spdif_info,
1850 .get = aureon_cs8415_spdif_get
1853 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1854 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1855 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1856 .info = aureon_cs8415_rate_info,
1857 .get = aureon_cs8415_rate_get
1861 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1863 unsigned int i, counts;
1866 counts = ARRAY_SIZE(aureon_dac_controls);
1867 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1868 counts -= 2; /* no side */
1869 for (i = 0; i < counts; i++) {
1870 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1875 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1876 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1881 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1882 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1883 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1888 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1889 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1890 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1891 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1897 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1898 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1900 snd_ice1712_save_gpio_status(ice);
1901 id = aureon_cs8415_get(ice, CS8415_ID);
1903 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1904 else if ((id & 0x0F) != 0x01)
1905 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1907 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1908 struct snd_kcontrol *kctl;
1909 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1913 kctl->id.device = ice->pcm->device;
1916 snd_ice1712_restore_gpio_status(ice);
1924 * initialize the chip
1926 static int __devinit aureon_init(struct snd_ice1712 *ice)
1928 static const unsigned short wm_inits_aureon[] = {
1929 /* These come first to reduce init pop noise */
1930 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1931 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1932 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1934 0x18, 0x000, /* All power-up */
1936 0x16, 0x122, /* I2S, normal polarity, 24bit */
1937 0x17, 0x022, /* 256fs, slave mode */
1938 0x00, 0, /* DAC1 analog mute */
1939 0x01, 0, /* DAC2 analog mute */
1940 0x02, 0, /* DAC3 analog mute */
1941 0x03, 0, /* DAC4 analog mute */
1942 0x04, 0, /* DAC5 analog mute */
1943 0x05, 0, /* DAC6 analog mute */
1944 0x06, 0, /* DAC7 analog mute */
1945 0x07, 0, /* DAC8 analog mute */
1946 0x08, 0x100, /* master analog mute */
1947 0x09, 0xff, /* DAC1 digital full */
1948 0x0a, 0xff, /* DAC2 digital full */
1949 0x0b, 0xff, /* DAC3 digital full */
1950 0x0c, 0xff, /* DAC4 digital full */
1951 0x0d, 0xff, /* DAC5 digital full */
1952 0x0e, 0xff, /* DAC6 digital full */
1953 0x0f, 0xff, /* DAC7 digital full */
1954 0x10, 0xff, /* DAC8 digital full */
1955 0x11, 0x1ff, /* master digital full */
1956 0x12, 0x000, /* phase normal */
1957 0x13, 0x090, /* unmute DAC L/R */
1958 0x14, 0x000, /* all unmute */
1959 0x15, 0x000, /* no deemphasis, no ZFLG */
1960 0x19, 0x000, /* -12dB ADC/L */
1961 0x1a, 0x000, /* -12dB ADC/R */
1964 static const unsigned short wm_inits_prodigy[] = {
1966 /* These come first to reduce init pop noise */
1967 0x1b, 0x000, /* ADC Mux */
1968 0x1c, 0x009, /* Out Mux1 */
1969 0x1d, 0x009, /* Out Mux2 */
1971 0x18, 0x000, /* All power-up */
1973 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1974 0x17, 0x006, /* 128fs, slave mode */
1976 0x00, 0, /* DAC1 analog mute */
1977 0x01, 0, /* DAC2 analog mute */
1978 0x02, 0, /* DAC3 analog mute */
1979 0x03, 0, /* DAC4 analog mute */
1980 0x04, 0, /* DAC5 analog mute */
1981 0x05, 0, /* DAC6 analog mute */
1982 0x06, 0, /* DAC7 analog mute */
1983 0x07, 0, /* DAC8 analog mute */
1984 0x08, 0x100, /* master analog mute */
1986 0x09, 0x7f, /* DAC1 digital full */
1987 0x0a, 0x7f, /* DAC2 digital full */
1988 0x0b, 0x7f, /* DAC3 digital full */
1989 0x0c, 0x7f, /* DAC4 digital full */
1990 0x0d, 0x7f, /* DAC5 digital full */
1991 0x0e, 0x7f, /* DAC6 digital full */
1992 0x0f, 0x7f, /* DAC7 digital full */
1993 0x10, 0x7f, /* DAC8 digital full */
1994 0x11, 0x1FF, /* master digital full */
1996 0x12, 0x000, /* phase normal */
1997 0x13, 0x090, /* unmute DAC L/R */
1998 0x14, 0x000, /* all unmute */
1999 0x15, 0x000, /* no deemphasis, no ZFLG */
2001 0x19, 0x000, /* -12dB ADC/L */
2002 0x1a, 0x000, /* -12dB ADC/R */
2006 static const unsigned short cs_inits[] = {
2008 0x0180, /* no mute, OMCK output on RMCK pin */
2009 0x0201, /* S/PDIF source on RXP1 */
2010 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2014 const unsigned short *p;
2017 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2018 ice->num_total_dacs = 6;
2019 ice->num_total_adcs = 2;
2021 /* aureon 7.1 and prodigy 7.1 */
2022 ice->num_total_dacs = 8;
2023 ice->num_total_adcs = 2;
2026 /* to remeber the register values of CS8415 */
2027 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2030 ice->akm_codecs = 1;
2032 if ((err = aureon_ac97_init(ice)) != 0)
2035 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2037 /* reset the wm codec as the SPI mode */
2038 snd_ice1712_save_gpio_status(ice);
2039 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2041 tmp = snd_ice1712_gpio_read(ice);
2042 tmp &= ~AUREON_WM_RESET;
2043 snd_ice1712_gpio_write(ice, tmp);
2045 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2046 snd_ice1712_gpio_write(ice, tmp);
2048 tmp |= AUREON_WM_RESET;
2049 snd_ice1712_gpio_write(ice, tmp);
2052 /* initialize WM8770 codec */
2053 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2054 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2055 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2056 p = wm_inits_prodigy;
2058 p = wm_inits_aureon;
2059 for (; *p != (unsigned short)-1; p += 2)
2060 wm_put(ice, p[0], p[1]);
2062 /* initialize CS8415A codec */
2063 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2064 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2065 for (p = cs_inits; *p != (unsigned short)-1; p++)
2066 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2067 ice->spec.aureon.cs8415_mux = 1;
2069 aureon_set_headphone_amp(ice, 1);
2072 snd_ice1712_restore_gpio_status(ice);
2074 /* initialize PCA9554 pin directions & set default input*/
2075 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2076 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2078 ice->spec.aureon.master[0] = WM_VOL_MUTE;
2079 ice->spec.aureon.master[1] = WM_VOL_MUTE;
2080 for (i = 0; i < ice->num_total_dacs; i++) {
2081 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2082 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2090 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2091 * hence the driver needs to sets up it properly.
2094 static unsigned char aureon51_eeprom[] __devinitdata = {
2095 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2096 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2097 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2098 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2099 [ICE_EEP2_GPIO_DIR] = 0xff,
2100 [ICE_EEP2_GPIO_DIR1] = 0xff,
2101 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2102 [ICE_EEP2_GPIO_MASK] = 0x00,
2103 [ICE_EEP2_GPIO_MASK1] = 0x00,
2104 [ICE_EEP2_GPIO_MASK2] = 0x00,
2105 [ICE_EEP2_GPIO_STATE] = 0x00,
2106 [ICE_EEP2_GPIO_STATE1] = 0x00,
2107 [ICE_EEP2_GPIO_STATE2] = 0x00,
2110 static unsigned char aureon71_eeprom[] __devinitdata = {
2111 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2112 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2113 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2114 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2115 [ICE_EEP2_GPIO_DIR] = 0xff,
2116 [ICE_EEP2_GPIO_DIR1] = 0xff,
2117 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2118 [ICE_EEP2_GPIO_MASK] = 0x00,
2119 [ICE_EEP2_GPIO_MASK1] = 0x00,
2120 [ICE_EEP2_GPIO_MASK2] = 0x00,
2121 [ICE_EEP2_GPIO_STATE] = 0x00,
2122 [ICE_EEP2_GPIO_STATE1] = 0x00,
2123 [ICE_EEP2_GPIO_STATE2] = 0x00,
2125 #define prodigy71_eeprom aureon71_eeprom
2127 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2128 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2129 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2130 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2131 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2132 [ICE_EEP2_GPIO_DIR] = 0xff,
2133 [ICE_EEP2_GPIO_DIR1] = 0xff,
2134 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2135 [ICE_EEP2_GPIO_MASK] = 0x00,
2136 [ICE_EEP2_GPIO_MASK1] = 0x00,
2137 [ICE_EEP2_GPIO_MASK2] = 0x00,
2138 [ICE_EEP2_GPIO_STATE] = 0x00,
2139 [ICE_EEP2_GPIO_STATE1] = 0x00,
2140 [ICE_EEP2_GPIO_STATE2] = 0x00,
2142 #define prodigy71xt_eeprom prodigy71lt_eeprom
2145 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2147 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2148 .name = "Terratec Aureon 5.1-Sky",
2149 .model = "aureon51",
2150 .chip_init = aureon_init,
2151 .build_controls = aureon_add_controls,
2152 .eeprom_size = sizeof(aureon51_eeprom),
2153 .eeprom_data = aureon51_eeprom,
2154 .driver = "Aureon51",
2157 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2158 .name = "Terratec Aureon 7.1-Space",
2159 .model = "aureon71",
2160 .chip_init = aureon_init,
2161 .build_controls = aureon_add_controls,
2162 .eeprom_size = sizeof(aureon71_eeprom),
2163 .eeprom_data = aureon71_eeprom,
2164 .driver = "Aureon71",
2167 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2168 .name = "Terratec Aureon 7.1-Universe",
2169 .model = "universe",
2170 .chip_init = aureon_init,
2171 .build_controls = aureon_add_controls,
2172 .eeprom_size = sizeof(aureon71_eeprom),
2173 .eeprom_data = aureon71_eeprom,
2174 .driver = "Aureon71Univ", /* keep in 15 letters */
2177 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2178 .name = "Audiotrak Prodigy 7.1",
2179 .model = "prodigy71",
2180 .chip_init = aureon_init,
2181 .build_controls = aureon_add_controls,
2182 .eeprom_size = sizeof(prodigy71_eeprom),
2183 .eeprom_data = prodigy71_eeprom,
2184 .driver = "Prodigy71", /* should be identical with Aureon71 */
2187 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2188 .name = "Audiotrak Prodigy 7.1 LT",
2189 .model = "prodigy71lt",
2190 .chip_init = aureon_init,
2191 .build_controls = aureon_add_controls,
2192 .eeprom_size = sizeof(prodigy71lt_eeprom),
2193 .eeprom_data = prodigy71lt_eeprom,
2194 .driver = "Prodigy71LT",
2197 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2198 .name = "Audiotrak Prodigy 7.1 XT",
2199 .model = "prodigy71xt",
2200 .chip_init = aureon_init,
2201 .build_controls = aureon_add_controls,
2202 .eeprom_size = sizeof(prodigy71xt_eeprom),
2203 .eeprom_data = prodigy71xt_eeprom,
2204 .driver = "Prodigy71LT",
2206 { } /* terminator */