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 <linux/delay.h>
51 #include <linux/interrupt.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/mutex.h>
56 #include <sound/core.h>
61 #include <sound/tlv.h>
63 /* AC97 register cache for Aureon */
65 unsigned short stac9744[64];
66 unsigned int cs8415_mux;
67 unsigned short master[2];
68 unsigned short vol[8];
69 unsigned char pca9554_out;
72 /* WM8770 registers */
73 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
74 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
75 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
76 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
77 #define WM_PHASE_SWAP 0x12 /* DAC phase */
78 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
79 #define WM_MUTE 0x14 /* mute controls */
80 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
81 #define WM_INT_CTRL 0x16 /* interface control */
82 #define WM_MASTER 0x17 /* master clock and mode */
83 #define WM_POWERDOWN 0x18 /* power-down controls */
84 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
85 #define WM_ADC_MUX 0x1b /* input MUX */
86 #define WM_OUT_MUX1 0x1c /* output MUX */
87 #define WM_OUT_MUX2 0x1e /* output MUX */
88 #define WM_RESET 0x1f /* software reset */
90 /* CS8415A registers */
91 #define CS8415_CTRL1 0x01
92 #define CS8415_CTRL2 0x02
93 #define CS8415_QSUB 0x14
94 #define CS8415_RATIO 0x1E
95 #define CS8415_C_BUFFER 0x20
96 #define CS8415_ID 0x7F
98 /* PCA9554 registers */
99 #define PCA9554_DEV 0x40 /* I2C device address */
100 #define PCA9554_IN 0x00 /* input port */
101 #define PCA9554_OUT 0x01 /* output port */
102 #define PCA9554_INVERT 0x02 /* input invert */
103 #define PCA9554_DIR 0x03 /* port directions */
106 * Aureon Universe additional controls using PCA9554
110 * Send data to pca9554
112 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
117 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
118 unsigned char val = 0;
120 tmp = snd_ice1712_gpio_read(ice);
122 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
123 AUREON_WM_RW|AUREON_WM_CS|
126 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
128 tmp &= ~AUREON_SPI_MOSI;
129 tmp &= ~AUREON_SPI_CLK;
130 snd_ice1712_gpio_write(ice, tmp);
134 * send i2c stop condition and start condition
135 * to obtain sane state
137 tmp |= AUREON_SPI_CLK;
138 snd_ice1712_gpio_write(ice, tmp);
140 tmp |= AUREON_SPI_MOSI;
141 snd_ice1712_gpio_write(ice, tmp);
143 tmp &= ~AUREON_SPI_MOSI;
144 snd_ice1712_gpio_write(ice, tmp);
146 tmp &= ~AUREON_SPI_CLK;
147 snd_ice1712_gpio_write(ice, tmp);
150 * send device address, command and value,
151 * skipping ack cycles inbetween
153 for (j = 0; j < 3; j++) {
165 for (i = 7; i >= 0; i--) {
166 tmp &= ~AUREON_SPI_CLK;
167 snd_ice1712_gpio_write(ice, tmp);
170 tmp |= AUREON_SPI_MOSI;
172 tmp &= ~AUREON_SPI_MOSI;
173 snd_ice1712_gpio_write(ice, tmp);
175 tmp |= AUREON_SPI_CLK;
176 snd_ice1712_gpio_write(ice, tmp);
179 tmp &= ~AUREON_SPI_CLK;
180 snd_ice1712_gpio_write(ice, tmp);
182 tmp |= AUREON_SPI_CLK;
183 snd_ice1712_gpio_write(ice, tmp);
185 tmp &= ~AUREON_SPI_CLK;
186 snd_ice1712_gpio_write(ice, tmp);
189 tmp &= ~AUREON_SPI_CLK;
190 snd_ice1712_gpio_write(ice, tmp);
192 tmp &= ~AUREON_SPI_MOSI;
193 snd_ice1712_gpio_write(ice, tmp);
195 tmp |= AUREON_SPI_CLK;
196 snd_ice1712_gpio_write(ice, tmp);
198 tmp |= AUREON_SPI_MOSI;
199 snd_ice1712_gpio_write(ice, tmp);
203 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_info *uinfo)
206 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
208 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
210 uinfo->value.enumerated.items = 3;
211 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
212 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
213 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
217 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
218 struct snd_ctl_elem_value *ucontrol)
220 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
221 struct aureon_spec *spec = ice->spec;
222 ucontrol->value.enumerated.item[0] = spec->pca9554_out;
226 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
227 struct snd_ctl_elem_value *ucontrol)
229 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
230 struct aureon_spec *spec = ice->spec;
231 unsigned char oval, nval;
234 nval = ucontrol->value.enumerated.item[0];
237 snd_ice1712_save_gpio_status(ice);
238 oval = spec->pca9554_out;
239 change = (oval != nval);
241 aureon_pca9554_write(ice, PCA9554_OUT, nval);
242 spec->pca9554_out = nval;
244 snd_ice1712_restore_gpio_status(ice);
249 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
252 struct aureon_spec *spec = ice->spec;
255 /* Send address to XILINX chip */
256 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
257 snd_ice1712_gpio_write(ice, tmp);
259 tmp |= AUREON_AC97_ADDR;
260 snd_ice1712_gpio_write(ice, tmp);
262 tmp &= ~AUREON_AC97_ADDR;
263 snd_ice1712_gpio_write(ice, tmp);
266 /* Send low-order byte to XILINX chip */
267 tmp &= ~AUREON_AC97_DATA_MASK;
268 tmp |= val & AUREON_AC97_DATA_MASK;
269 snd_ice1712_gpio_write(ice, tmp);
271 tmp |= AUREON_AC97_DATA_LOW;
272 snd_ice1712_gpio_write(ice, tmp);
274 tmp &= ~AUREON_AC97_DATA_LOW;
275 snd_ice1712_gpio_write(ice, tmp);
278 /* Send high-order byte to XILINX chip */
279 tmp &= ~AUREON_AC97_DATA_MASK;
280 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
282 snd_ice1712_gpio_write(ice, tmp);
284 tmp |= AUREON_AC97_DATA_HIGH;
285 snd_ice1712_gpio_write(ice, tmp);
287 tmp &= ~AUREON_AC97_DATA_HIGH;
288 snd_ice1712_gpio_write(ice, tmp);
291 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
292 tmp |= AUREON_AC97_COMMIT;
293 snd_ice1712_gpio_write(ice, tmp);
295 tmp &= ~AUREON_AC97_COMMIT;
296 snd_ice1712_gpio_write(ice, tmp);
299 /* Store the data in out private buffer */
300 spec->stac9744[(reg & 0x7F) >> 1] = val;
303 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
305 struct aureon_spec *spec = ice->spec;
306 return spec->stac9744[(reg & 0x7F) >> 1];
310 * Initialize STAC9744 chip
312 static int aureon_ac97_init(struct snd_ice1712 *ice)
314 struct aureon_spec *spec = ice->spec;
316 static const unsigned short ac97_defaults[] = {
340 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
341 snd_ice1712_gpio_write(ice, tmp);
344 tmp &= ~AUREON_AC97_RESET;
345 snd_ice1712_gpio_write(ice, tmp);
348 tmp |= AUREON_AC97_RESET;
349 snd_ice1712_gpio_write(ice, tmp);
352 memset(&spec->stac9744, 0, sizeof(spec->stac9744));
353 for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2)
354 spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
356 /* Unmute AC'97 master volume permanently - muting is done by WM8770 */
357 aureon_ac97_write(ice, AC97_MASTER, 0x0000);
362 #define AUREON_AC97_STEREO 0x80
365 * AC'97 volume controls
367 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
369 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
370 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
371 uinfo->value.integer.min = 0;
372 uinfo->value.integer.max = 31;
376 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
378 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
381 mutex_lock(&ice->gpio_mutex);
383 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
384 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
385 if (kcontrol->private_value & AUREON_AC97_STEREO)
386 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
388 mutex_unlock(&ice->gpio_mutex);
392 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
394 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
395 unsigned short ovol, nvol;
398 snd_ice1712_save_gpio_status(ice);
400 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
401 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
402 if (kcontrol->private_value & AUREON_AC97_STEREO)
403 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
404 nvol |= ovol & ~0x1F1F;
406 change = (ovol != nvol);
408 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
410 snd_ice1712_restore_gpio_status(ice);
416 * AC'97 mute controls
418 #define aureon_ac97_mute_info snd_ctl_boolean_mono_info
420 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
422 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
424 mutex_lock(&ice->gpio_mutex);
426 ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
427 kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
429 mutex_unlock(&ice->gpio_mutex);
433 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
435 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
436 unsigned short ovol, nvol;
439 snd_ice1712_save_gpio_status(ice);
441 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
442 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
444 change = (ovol != nvol);
446 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
448 snd_ice1712_restore_gpio_status(ice);
454 * AC'97 mute controls
456 #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
458 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
460 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
462 mutex_lock(&ice->gpio_mutex);
464 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
466 mutex_unlock(&ice->gpio_mutex);
470 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
472 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
473 unsigned short ovol, nvol;
476 snd_ice1712_save_gpio_status(ice);
478 ovol = aureon_ac97_read(ice, AC97_MIC);
479 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
481 change = (ovol != nvol);
483 aureon_ac97_write(ice, AC97_MIC, nvol);
485 snd_ice1712_restore_gpio_status(ice);
491 * write data in the SPI mode
493 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
497 unsigned int mosi, clk;
499 tmp = snd_ice1712_gpio_read(ice);
501 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
502 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
503 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
504 mosi = PRODIGY_SPI_MOSI;
505 clk = PRODIGY_SPI_CLK;
507 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
508 AUREON_WM_CS|AUREON_CS8415_CS));
509 mosi = AUREON_SPI_MOSI;
510 clk = AUREON_SPI_CLK;
516 snd_ice1712_gpio_write(ice, tmp);
519 for (i = bits - 1; i >= 0; i--) {
521 snd_ice1712_gpio_write(ice, tmp);
527 snd_ice1712_gpio_write(ice, tmp);
530 snd_ice1712_gpio_write(ice, tmp);
536 snd_ice1712_gpio_write(ice, tmp);
539 snd_ice1712_gpio_write(ice, tmp);
544 * Read data in SPI mode
546 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
547 unsigned int data, int bits, unsigned char *buffer, int size)
552 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
553 snd_ice1712_gpio_write(ice, tmp);
555 snd_ice1712_gpio_write(ice, tmp);
558 for (i = bits-1; i >= 0; i--) {
560 tmp |= AUREON_SPI_MOSI;
562 tmp &= ~AUREON_SPI_MOSI;
563 snd_ice1712_gpio_write(ice, tmp);
566 tmp |= AUREON_SPI_CLK;
567 snd_ice1712_gpio_write(ice, tmp);
570 tmp &= ~AUREON_SPI_CLK;
571 snd_ice1712_gpio_write(ice, tmp);
575 for (j = 0; j < size; j++) {
576 unsigned char outdata = 0;
577 for (i = 7; i >= 0; i--) {
578 tmp = snd_ice1712_gpio_read(ice);
580 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
583 tmp |= AUREON_SPI_CLK;
584 snd_ice1712_gpio_write(ice, tmp);
587 tmp &= ~AUREON_SPI_CLK;
588 snd_ice1712_gpio_write(ice, tmp);
595 snd_ice1712_gpio_write(ice, tmp);
598 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
601 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
602 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
606 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
607 unsigned char *buffer, int size)
609 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
610 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
613 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
616 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
620 * get the current register value of WM codec
622 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
625 return ((unsigned short)ice->akm[0].images[reg] << 8) |
626 ice->akm[0].images[reg + 1];
630 * set the register value of WM codec
632 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
634 aureon_spi_write(ice,
635 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
636 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
637 PRODIGY_WM_CS : AUREON_WM_CS),
638 (reg << 9) | (val & 0x1ff), 16);
642 * set the register value of WM codec and remember it
644 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
646 wm_put_nocache(ice, reg, val);
648 ice->akm[0].images[reg] = val >> 8;
649 ice->akm[0].images[reg + 1] = val;
654 #define aureon_mono_bool_info snd_ctl_boolean_mono_info
657 * AC'97 master playback mute controls (Mute on WM8770 chip)
659 #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
661 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
663 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
665 mutex_lock(&ice->gpio_mutex);
667 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
669 mutex_unlock(&ice->gpio_mutex);
673 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
675 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
676 unsigned short ovol, nvol;
679 snd_ice1712_save_gpio_status(ice);
681 ovol = wm_get(ice, WM_OUT_MUX1);
682 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
683 change = (ovol != nvol);
685 wm_put(ice, WM_OUT_MUX1, nvol);
687 snd_ice1712_restore_gpio_status(ice);
692 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
693 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
694 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
695 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
696 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
699 * Logarithmic volume values for WM8770
700 * Computed as 20 * Log10(255 / x)
702 static const unsigned char wm_vol[256] = {
703 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
704 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
705 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
706 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
707 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
708 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,
709 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,
710 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,
711 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,
712 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,
713 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,
717 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
718 #define WM_VOL_MUTE 0x8000
720 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
724 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
727 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
729 wm_put(ice, index, nvol);
730 wm_put_nocache(ice, index, 0x180 | nvol);
736 #define wm_pcm_mute_info snd_ctl_boolean_mono_info
738 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
740 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
742 mutex_lock(&ice->gpio_mutex);
743 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
744 mutex_unlock(&ice->gpio_mutex);
748 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
750 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
751 unsigned short nval, oval;
754 snd_ice1712_save_gpio_status(ice);
755 oval = wm_get(ice, WM_MUTE);
756 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
757 change = (oval != nval);
759 wm_put(ice, WM_MUTE, nval);
760 snd_ice1712_restore_gpio_status(ice);
766 * Master volume attenuation mixer control
768 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
770 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
772 uinfo->value.integer.min = 0;
773 uinfo->value.integer.max = WM_VOL_MAX;
777 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
779 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
780 struct aureon_spec *spec = ice->spec;
782 for (i = 0; i < 2; i++)
783 ucontrol->value.integer.value[i] =
784 spec->master[i] & ~WM_VOL_MUTE;
788 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
790 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
791 struct aureon_spec *spec = ice->spec;
794 snd_ice1712_save_gpio_status(ice);
795 for (ch = 0; ch < 2; ch++) {
796 unsigned int vol = ucontrol->value.integer.value[ch];
797 if (vol > WM_VOL_MAX)
799 vol |= spec->master[ch] & WM_VOL_MUTE;
800 if (vol != spec->master[ch]) {
802 spec->master[ch] = vol;
803 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
804 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
810 snd_ice1712_restore_gpio_status(ice);
815 * DAC volume attenuation mixer control
817 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
819 int voices = kcontrol->private_value >> 8;
820 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
821 uinfo->count = voices;
822 uinfo->value.integer.min = 0; /* mute (-101dB) */
823 uinfo->value.integer.max = 0x7F; /* 0dB */
827 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
829 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
830 struct aureon_spec *spec = ice->spec;
833 voices = kcontrol->private_value >> 8;
834 ofs = kcontrol->private_value & 0xff;
835 for (i = 0; i < voices; i++)
836 ucontrol->value.integer.value[i] =
837 spec->vol[ofs+i] & ~WM_VOL_MUTE;
841 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
843 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
844 struct aureon_spec *spec = ice->spec;
845 int i, idx, ofs, voices;
848 voices = kcontrol->private_value >> 8;
849 ofs = kcontrol->private_value & 0xff;
850 snd_ice1712_save_gpio_status(ice);
851 for (i = 0; i < voices; i++) {
852 unsigned int vol = ucontrol->value.integer.value[i];
855 vol |= spec->vol[ofs+i];
856 if (vol != spec->vol[ofs+i]) {
857 spec->vol[ofs+i] = vol;
858 idx = WM_DAC_ATTEN + ofs + i;
859 wm_set_vol(ice, idx, spec->vol[ofs + i],
864 snd_ice1712_restore_gpio_status(ice);
869 * WM8770 mute control
871 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
873 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
874 uinfo->count = kcontrol->private_value >> 8;
875 uinfo->value.integer.min = 0;
876 uinfo->value.integer.max = 1;
880 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
882 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
883 struct aureon_spec *spec = ice->spec;
886 voices = kcontrol->private_value >> 8;
887 ofs = kcontrol->private_value & 0xFF;
889 for (i = 0; i < voices; i++)
890 ucontrol->value.integer.value[i] =
891 (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
895 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
897 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
898 struct aureon_spec *spec = ice->spec;
899 int change = 0, voices, ofs, i;
901 voices = kcontrol->private_value >> 8;
902 ofs = kcontrol->private_value & 0xFF;
904 snd_ice1712_save_gpio_status(ice);
905 for (i = 0; i < voices; i++) {
906 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
907 if (ucontrol->value.integer.value[i] != val) {
908 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
909 spec->vol[ofs + i] |=
910 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
911 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
916 snd_ice1712_restore_gpio_status(ice);
922 * WM8770 master mute control
924 #define wm_master_mute_info snd_ctl_boolean_stereo_info
926 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
928 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
929 struct aureon_spec *spec = ice->spec;
931 ucontrol->value.integer.value[0] =
932 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
933 ucontrol->value.integer.value[1] =
934 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
938 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
940 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
941 struct aureon_spec *spec = ice->spec;
944 snd_ice1712_save_gpio_status(ice);
945 for (i = 0; i < 2; i++) {
946 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
947 if (ucontrol->value.integer.value[i] != val) {
949 spec->master[i] &= ~WM_VOL_MUTE;
951 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
952 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
953 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
959 snd_ice1712_restore_gpio_status(ice);
964 /* digital master volume */
966 #define PCM_RES 128 /* -64dB */
967 #define PCM_MIN (PCM_0dB - PCM_RES)
968 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
970 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
972 uinfo->value.integer.min = 0; /* mute (-64dB) */
973 uinfo->value.integer.max = PCM_RES; /* 0dB */
977 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
979 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
982 mutex_lock(&ice->gpio_mutex);
983 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
984 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
985 ucontrol->value.integer.value[0] = val;
986 mutex_unlock(&ice->gpio_mutex);
990 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
992 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
993 unsigned short ovol, nvol;
996 nvol = ucontrol->value.integer.value[0];
999 snd_ice1712_save_gpio_status(ice);
1000 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
1001 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
1003 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
1004 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
1007 snd_ice1712_restore_gpio_status(ice);
1014 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
1016 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1018 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1022 mutex_lock(&ice->gpio_mutex);
1023 for (i = 0; i < 2; i++) {
1024 val = wm_get(ice, WM_ADC_GAIN + i);
1025 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1027 mutex_unlock(&ice->gpio_mutex);
1031 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1033 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1034 unsigned short new, old;
1037 snd_ice1712_save_gpio_status(ice);
1038 for (i = 0; i < 2; i++) {
1039 old = wm_get(ice, WM_ADC_GAIN + i);
1040 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1042 wm_put(ice, WM_ADC_GAIN + i, new);
1046 snd_ice1712_restore_gpio_status(ice);
1052 * ADC gain mixer control
1054 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1056 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1058 uinfo->value.integer.min = 0; /* -12dB */
1059 uinfo->value.integer.max = 0x1f; /* 19dB */
1063 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1065 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1069 mutex_lock(&ice->gpio_mutex);
1070 for (i = 0; i < 2; i++) {
1071 idx = WM_ADC_GAIN + i;
1072 vol = wm_get(ice, idx) & 0x1f;
1073 ucontrol->value.integer.value[i] = vol;
1075 mutex_unlock(&ice->gpio_mutex);
1079 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1081 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1083 unsigned short ovol, nvol;
1086 snd_ice1712_save_gpio_status(ice);
1087 for (i = 0; i < 2; i++) {
1088 idx = WM_ADC_GAIN + i;
1089 nvol = ucontrol->value.integer.value[i] & 0x1f;
1090 ovol = wm_get(ice, idx);
1091 if ((ovol & 0x1f) != nvol) {
1092 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1096 snd_ice1712_restore_gpio_status(ice);
1101 * ADC input mux mixer control
1103 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1105 static const char * const texts[] = {
1112 static const char * const universe_texts[] = {
1122 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1124 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1126 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1127 uinfo->value.enumerated.items = 8;
1128 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1129 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1130 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1132 uinfo->value.enumerated.items = 5;
1133 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1134 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1135 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1140 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1142 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1145 mutex_lock(&ice->gpio_mutex);
1146 val = wm_get(ice, WM_ADC_MUX);
1147 ucontrol->value.enumerated.item[0] = val & 7;
1148 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1149 mutex_unlock(&ice->gpio_mutex);
1153 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1155 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1156 unsigned short oval, nval;
1159 snd_ice1712_save_gpio_status(ice);
1160 oval = wm_get(ice, WM_ADC_MUX);
1161 nval = oval & ~0x77;
1162 nval |= ucontrol->value.enumerated.item[0] & 7;
1163 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1164 change = (oval != nval);
1166 wm_put(ice, WM_ADC_MUX, nval);
1167 snd_ice1712_restore_gpio_status(ice);
1174 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1176 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1177 static const char * const aureon_texts[] = {
1179 "Optical" /* RXP1 */
1181 static const char * const prodigy_texts[] = {
1185 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1187 uinfo->value.enumerated.items = 2;
1188 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1189 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1190 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1191 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1193 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1197 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1199 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1200 struct aureon_spec *spec = ice->spec;
1202 /* snd_ice1712_save_gpio_status(ice); */
1203 /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
1204 ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1205 /* snd_ice1712_restore_gpio_status(ice); */
1209 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1211 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212 struct aureon_spec *spec = ice->spec;
1213 unsigned short oval, nval;
1216 snd_ice1712_save_gpio_status(ice);
1217 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1218 nval = oval & ~0x07;
1219 nval |= ucontrol->value.enumerated.item[0] & 7;
1220 change = (oval != nval);
1222 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1223 snd_ice1712_restore_gpio_status(ice);
1224 spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1228 static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1230 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1232 uinfo->value.integer.min = 0;
1233 uinfo->value.integer.max = 192000;
1237 static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1239 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240 unsigned char ratio;
1241 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1242 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1249 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1251 static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1253 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1254 snd_ice1712_save_gpio_status(ice);
1255 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1256 snd_ice1712_restore_gpio_status(ice);
1260 static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1262 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1263 unsigned char oval, nval;
1265 snd_ice1712_save_gpio_status(ice);
1266 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1267 if (ucontrol->value.integer.value[0])
1268 nval = oval & ~0x20;
1271 change = (oval != nval);
1273 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1274 snd_ice1712_restore_gpio_status(ice);
1279 * CS8415A Q-Sub info
1281 static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1283 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1288 static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1290 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1292 snd_ice1712_save_gpio_status(ice);
1293 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1294 snd_ice1712_restore_gpio_status(ice);
1299 static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1301 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1306 static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1308 memset(ucontrol->value.iec958.status, 0xFF, 24);
1312 static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1314 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1316 snd_ice1712_save_gpio_status(ice);
1317 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1318 snd_ice1712_restore_gpio_status(ice);
1323 * Headphone Amplifier
1325 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1327 unsigned int tmp, tmp2;
1329 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1331 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1332 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1333 tmp |= AUREON_HP_SEL;
1335 tmp |= PRODIGY_HP_SEL;
1337 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1338 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1339 tmp &= ~AUREON_HP_SEL;
1341 tmp &= ~PRODIGY_HP_SEL;
1343 snd_ice1712_gpio_write(ice, tmp);
1349 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1351 unsigned int tmp = snd_ice1712_gpio_read(ice);
1353 return (tmp & AUREON_HP_SEL) != 0;
1356 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1358 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1360 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1362 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1367 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1369 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1371 return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1378 #define aureon_deemp_info snd_ctl_boolean_mono_info
1380 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1382 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1383 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1387 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1389 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1391 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1392 if (ucontrol->value.integer.value[0])
1396 if (temp != temp2) {
1397 wm_put(ice, WM_DAC_CTRL2, temp);
1406 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1408 static const char * const texts[2] = { "128x", "64x" };
1410 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1412 uinfo->value.enumerated.items = 2;
1414 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1415 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1416 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1421 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1423 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1424 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1428 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1431 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1433 temp2 = temp = wm_get(ice, WM_MASTER);
1435 if (ucontrol->value.enumerated.item[0])
1440 if (temp != temp2) {
1441 wm_put(ice, WM_MASTER, temp);
1451 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454 .name = "Master Playback Switch",
1455 .info = wm_master_mute_info,
1456 .get = wm_master_mute_get,
1457 .put = wm_master_mute_put
1460 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1461 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1462 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1463 .name = "Master Playback Volume",
1464 .info = wm_master_vol_info,
1465 .get = wm_master_vol_get,
1466 .put = wm_master_vol_put,
1467 .tlv = { .p = db_scale_wm_dac }
1470 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1471 .name = "Front Playback Switch",
1472 .info = wm_mute_info,
1475 .private_value = (2 << 8) | 0
1478 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1479 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1480 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1481 .name = "Front Playback Volume",
1482 .info = wm_vol_info,
1485 .private_value = (2 << 8) | 0,
1486 .tlv = { .p = db_scale_wm_dac }
1489 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1490 .name = "Rear Playback Switch",
1491 .info = wm_mute_info,
1494 .private_value = (2 << 8) | 2
1497 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1498 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1499 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1500 .name = "Rear Playback Volume",
1501 .info = wm_vol_info,
1504 .private_value = (2 << 8) | 2,
1505 .tlv = { .p = db_scale_wm_dac }
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "Center Playback Switch",
1510 .info = wm_mute_info,
1513 .private_value = (1 << 8) | 4
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1519 .name = "Center Playback Volume",
1520 .info = wm_vol_info,
1523 .private_value = (1 << 8) | 4,
1524 .tlv = { .p = db_scale_wm_dac }
1527 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1528 .name = "LFE Playback Switch",
1529 .info = wm_mute_info,
1532 .private_value = (1 << 8) | 5
1535 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1536 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1537 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1538 .name = "LFE Playback Volume",
1539 .info = wm_vol_info,
1542 .private_value = (1 << 8) | 5,
1543 .tlv = { .p = db_scale_wm_dac }
1546 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1547 .name = "Side Playback Switch",
1548 .info = wm_mute_info,
1551 .private_value = (2 << 8) | 6
1554 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1555 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1556 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1557 .name = "Side Playback Volume",
1558 .info = wm_vol_info,
1561 .private_value = (2 << 8) | 6,
1562 .tlv = { .p = db_scale_wm_dac }
1566 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1568 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1569 .name = "PCM Playback Switch",
1570 .info = wm_pcm_mute_info,
1571 .get = wm_pcm_mute_get,
1572 .put = wm_pcm_mute_put
1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1577 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1578 .name = "PCM Playback Volume",
1579 .info = wm_pcm_vol_info,
1580 .get = wm_pcm_vol_get,
1581 .put = wm_pcm_vol_put,
1582 .tlv = { .p = db_scale_wm_pcm }
1585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586 .name = "Capture Switch",
1587 .info = wm_adc_mute_info,
1588 .get = wm_adc_mute_get,
1589 .put = wm_adc_mute_put,
1592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1594 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1595 .name = "Capture Volume",
1596 .info = wm_adc_vol_info,
1597 .get = wm_adc_vol_get,
1598 .put = wm_adc_vol_put,
1599 .tlv = { .p = db_scale_wm_adc }
1602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603 .name = "Capture Source",
1604 .info = wm_adc_mux_info,
1605 .get = wm_adc_mux_get,
1606 .put = wm_adc_mux_put,
1610 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1611 .name = "External Amplifier",
1612 .info = aureon_hpamp_info,
1613 .get = aureon_hpamp_get,
1614 .put = aureon_hpamp_put
1617 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618 .name = "DAC Deemphasis Switch",
1619 .info = aureon_deemp_info,
1620 .get = aureon_deemp_get,
1621 .put = aureon_deemp_put
1624 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1625 .name = "ADC Oversampling",
1626 .info = aureon_oversampling_info,
1627 .get = aureon_oversampling_get,
1628 .put = aureon_oversampling_put
1632 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1635 .name = "AC97 Playback Switch",
1636 .info = aureon_ac97_mmute_info,
1637 .get = aureon_ac97_mmute_get,
1638 .put = aureon_ac97_mmute_put,
1639 .private_value = AC97_MASTER
1642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1643 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1644 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1645 .name = "AC97 Playback Volume",
1646 .info = aureon_ac97_vol_info,
1647 .get = aureon_ac97_vol_get,
1648 .put = aureon_ac97_vol_put,
1649 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1650 .tlv = { .p = db_scale_ac97_master }
1653 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1654 .name = "CD Playback Switch",
1655 .info = aureon_ac97_mute_info,
1656 .get = aureon_ac97_mute_get,
1657 .put = aureon_ac97_mute_put,
1658 .private_value = AC97_CD
1661 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1662 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1663 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1664 .name = "CD Playback Volume",
1665 .info = aureon_ac97_vol_info,
1666 .get = aureon_ac97_vol_get,
1667 .put = aureon_ac97_vol_put,
1668 .private_value = AC97_CD|AUREON_AC97_STEREO,
1669 .tlv = { .p = db_scale_ac97_gain }
1672 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1673 .name = "Aux Playback Switch",
1674 .info = aureon_ac97_mute_info,
1675 .get = aureon_ac97_mute_get,
1676 .put = aureon_ac97_mute_put,
1677 .private_value = AC97_AUX,
1680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1682 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1683 .name = "Aux Playback Volume",
1684 .info = aureon_ac97_vol_info,
1685 .get = aureon_ac97_vol_get,
1686 .put = aureon_ac97_vol_put,
1687 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1688 .tlv = { .p = db_scale_ac97_gain }
1691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1692 .name = "Line Playback Switch",
1693 .info = aureon_ac97_mute_info,
1694 .get = aureon_ac97_mute_get,
1695 .put = aureon_ac97_mute_put,
1696 .private_value = AC97_LINE
1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1701 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1702 .name = "Line Playback Volume",
1703 .info = aureon_ac97_vol_info,
1704 .get = aureon_ac97_vol_get,
1705 .put = aureon_ac97_vol_put,
1706 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1707 .tlv = { .p = db_scale_ac97_gain }
1710 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1711 .name = "Mic Playback Switch",
1712 .info = aureon_ac97_mute_info,
1713 .get = aureon_ac97_mute_get,
1714 .put = aureon_ac97_mute_put,
1715 .private_value = AC97_MIC
1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1720 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1721 .name = "Mic Playback Volume",
1722 .info = aureon_ac97_vol_info,
1723 .get = aureon_ac97_vol_get,
1724 .put = aureon_ac97_vol_put,
1725 .private_value = AC97_MIC,
1726 .tlv = { .p = db_scale_ac97_gain }
1729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730 .name = "Mic Boost (+20dB)",
1731 .info = aureon_ac97_micboost_info,
1732 .get = aureon_ac97_micboost_get,
1733 .put = aureon_ac97_micboost_put
1737 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1739 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1740 .name = "AC97 Playback Switch",
1741 .info = aureon_ac97_mmute_info,
1742 .get = aureon_ac97_mmute_get,
1743 .put = aureon_ac97_mmute_put,
1744 .private_value = AC97_MASTER
1747 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1748 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1749 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1750 .name = "AC97 Playback Volume",
1751 .info = aureon_ac97_vol_info,
1752 .get = aureon_ac97_vol_get,
1753 .put = aureon_ac97_vol_put,
1754 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1755 .tlv = { .p = db_scale_ac97_master }
1758 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1759 .name = "CD Playback Switch",
1760 .info = aureon_ac97_mute_info,
1761 .get = aureon_ac97_mute_get,
1762 .put = aureon_ac97_mute_put,
1763 .private_value = AC97_AUX
1766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1767 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1768 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1769 .name = "CD Playback Volume",
1770 .info = aureon_ac97_vol_info,
1771 .get = aureon_ac97_vol_get,
1772 .put = aureon_ac97_vol_put,
1773 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1774 .tlv = { .p = db_scale_ac97_gain }
1777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1778 .name = "Phono Playback Switch",
1779 .info = aureon_ac97_mute_info,
1780 .get = aureon_ac97_mute_get,
1781 .put = aureon_ac97_mute_put,
1782 .private_value = AC97_CD
1785 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1786 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1787 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1788 .name = "Phono Playback Volume",
1789 .info = aureon_ac97_vol_info,
1790 .get = aureon_ac97_vol_get,
1791 .put = aureon_ac97_vol_put,
1792 .private_value = AC97_CD|AUREON_AC97_STEREO,
1793 .tlv = { .p = db_scale_ac97_gain }
1796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1797 .name = "Line Playback Switch",
1798 .info = aureon_ac97_mute_info,
1799 .get = aureon_ac97_mute_get,
1800 .put = aureon_ac97_mute_put,
1801 .private_value = AC97_LINE
1804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1805 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1806 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1807 .name = "Line Playback Volume",
1808 .info = aureon_ac97_vol_info,
1809 .get = aureon_ac97_vol_get,
1810 .put = aureon_ac97_vol_put,
1811 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1812 .tlv = { .p = db_scale_ac97_gain }
1815 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1816 .name = "Mic Playback Switch",
1817 .info = aureon_ac97_mute_info,
1818 .get = aureon_ac97_mute_get,
1819 .put = aureon_ac97_mute_put,
1820 .private_value = AC97_MIC
1823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1824 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1825 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1826 .name = "Mic Playback Volume",
1827 .info = aureon_ac97_vol_info,
1828 .get = aureon_ac97_vol_get,
1829 .put = aureon_ac97_vol_put,
1830 .private_value = AC97_MIC,
1831 .tlv = { .p = db_scale_ac97_gain }
1834 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1835 .name = "Mic Boost (+20dB)",
1836 .info = aureon_ac97_micboost_info,
1837 .get = aureon_ac97_micboost_get,
1838 .put = aureon_ac97_micboost_put
1841 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1842 .name = "Aux Playback Switch",
1843 .info = aureon_ac97_mute_info,
1844 .get = aureon_ac97_mute_get,
1845 .put = aureon_ac97_mute_put,
1846 .private_value = AC97_VIDEO,
1849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1850 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1851 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1852 .name = "Aux Playback Volume",
1853 .info = aureon_ac97_vol_info,
1854 .get = aureon_ac97_vol_get,
1855 .put = aureon_ac97_vol_put,
1856 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1857 .tlv = { .p = db_scale_ac97_gain }
1860 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1861 .name = "Aux Source",
1862 .info = aureon_universe_inmux_info,
1863 .get = aureon_universe_inmux_get,
1864 .put = aureon_universe_inmux_put
1869 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1871 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1872 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1873 .info = aureon_cs8415_mute_info,
1874 .get = aureon_cs8415_mute_get,
1875 .put = aureon_cs8415_mute_put
1878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1879 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1880 .info = aureon_cs8415_mux_info,
1881 .get = aureon_cs8415_mux_get,
1882 .put = aureon_cs8415_mux_put,
1885 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1886 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1887 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1888 .info = aureon_cs8415_qsub_info,
1889 .get = aureon_cs8415_qsub_get,
1892 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1893 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1894 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1895 .info = aureon_cs8415_spdif_info,
1896 .get = aureon_cs8415_mask_get
1899 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1900 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1901 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1902 .info = aureon_cs8415_spdif_info,
1903 .get = aureon_cs8415_spdif_get
1906 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1907 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1908 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1909 .info = aureon_cs8415_rate_info,
1910 .get = aureon_cs8415_rate_get
1914 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1916 unsigned int i, counts;
1919 counts = ARRAY_SIZE(aureon_dac_controls);
1920 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1921 counts -= 2; /* no side */
1922 for (i = 0; i < counts; i++) {
1923 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1928 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1929 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1934 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1935 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1936 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1940 } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1941 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1942 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1943 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1949 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1950 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1952 snd_ice1712_save_gpio_status(ice);
1953 id = aureon_cs8415_get(ice, CS8415_ID);
1955 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1956 else if ((id & 0x0F) != 0x01)
1957 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1959 for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1960 struct snd_kcontrol *kctl;
1961 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1965 kctl->id.device = ice->pcm->device;
1968 snd_ice1712_restore_gpio_status(ice);
1976 * initialize the chip
1978 static int __devinit aureon_init(struct snd_ice1712 *ice)
1980 static const unsigned short wm_inits_aureon[] = {
1981 /* These come first to reduce init pop noise */
1982 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1983 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1984 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1986 0x18, 0x000, /* All power-up */
1988 0x16, 0x122, /* I2S, normal polarity, 24bit */
1989 0x17, 0x022, /* 256fs, slave mode */
1990 0x00, 0, /* DAC1 analog mute */
1991 0x01, 0, /* DAC2 analog mute */
1992 0x02, 0, /* DAC3 analog mute */
1993 0x03, 0, /* DAC4 analog mute */
1994 0x04, 0, /* DAC5 analog mute */
1995 0x05, 0, /* DAC6 analog mute */
1996 0x06, 0, /* DAC7 analog mute */
1997 0x07, 0, /* DAC8 analog mute */
1998 0x08, 0x100, /* master analog mute */
1999 0x09, 0xff, /* DAC1 digital full */
2000 0x0a, 0xff, /* DAC2 digital full */
2001 0x0b, 0xff, /* DAC3 digital full */
2002 0x0c, 0xff, /* DAC4 digital full */
2003 0x0d, 0xff, /* DAC5 digital full */
2004 0x0e, 0xff, /* DAC6 digital full */
2005 0x0f, 0xff, /* DAC7 digital full */
2006 0x10, 0xff, /* DAC8 digital full */
2007 0x11, 0x1ff, /* master digital full */
2008 0x12, 0x000, /* phase normal */
2009 0x13, 0x090, /* unmute DAC L/R */
2010 0x14, 0x000, /* all unmute */
2011 0x15, 0x000, /* no deemphasis, no ZFLG */
2012 0x19, 0x000, /* -12dB ADC/L */
2013 0x1a, 0x000, /* -12dB ADC/R */
2016 static const unsigned short wm_inits_prodigy[] = {
2018 /* These come first to reduce init pop noise */
2019 0x1b, 0x000, /* ADC Mux */
2020 0x1c, 0x009, /* Out Mux1 */
2021 0x1d, 0x009, /* Out Mux2 */
2023 0x18, 0x000, /* All power-up */
2025 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
2026 0x17, 0x006, /* 128fs, slave mode */
2028 0x00, 0, /* DAC1 analog mute */
2029 0x01, 0, /* DAC2 analog mute */
2030 0x02, 0, /* DAC3 analog mute */
2031 0x03, 0, /* DAC4 analog mute */
2032 0x04, 0, /* DAC5 analog mute */
2033 0x05, 0, /* DAC6 analog mute */
2034 0x06, 0, /* DAC7 analog mute */
2035 0x07, 0, /* DAC8 analog mute */
2036 0x08, 0x100, /* master analog mute */
2038 0x09, 0x7f, /* DAC1 digital full */
2039 0x0a, 0x7f, /* DAC2 digital full */
2040 0x0b, 0x7f, /* DAC3 digital full */
2041 0x0c, 0x7f, /* DAC4 digital full */
2042 0x0d, 0x7f, /* DAC5 digital full */
2043 0x0e, 0x7f, /* DAC6 digital full */
2044 0x0f, 0x7f, /* DAC7 digital full */
2045 0x10, 0x7f, /* DAC8 digital full */
2046 0x11, 0x1FF, /* master digital full */
2048 0x12, 0x000, /* phase normal */
2049 0x13, 0x090, /* unmute DAC L/R */
2050 0x14, 0x000, /* all unmute */
2051 0x15, 0x000, /* no deemphasis, no ZFLG */
2053 0x19, 0x000, /* -12dB ADC/L */
2054 0x1a, 0x000, /* -12dB ADC/R */
2058 static const unsigned short cs_inits[] = {
2060 0x0180, /* no mute, OMCK output on RMCK pin */
2061 0x0201, /* S/PDIF source on RXP1 */
2062 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2065 struct aureon_spec *spec;
2067 const unsigned short *p;
2070 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2075 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2076 ice->num_total_dacs = 6;
2077 ice->num_total_adcs = 2;
2079 /* aureon 7.1 and prodigy 7.1 */
2080 ice->num_total_dacs = 8;
2081 ice->num_total_adcs = 2;
2084 /* to remeber the register values of CS8415 */
2085 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2088 ice->akm_codecs = 1;
2090 err = aureon_ac97_init(ice);
2094 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2096 /* reset the wm codec as the SPI mode */
2097 snd_ice1712_save_gpio_status(ice);
2098 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2100 tmp = snd_ice1712_gpio_read(ice);
2101 tmp &= ~AUREON_WM_RESET;
2102 snd_ice1712_gpio_write(ice, tmp);
2104 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2105 snd_ice1712_gpio_write(ice, tmp);
2107 tmp |= AUREON_WM_RESET;
2108 snd_ice1712_gpio_write(ice, tmp);
2111 /* initialize WM8770 codec */
2112 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2113 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2114 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2115 p = wm_inits_prodigy;
2117 p = wm_inits_aureon;
2118 for (; *p != (unsigned short)-1; p += 2)
2119 wm_put(ice, p[0], p[1]);
2121 /* initialize CS8415A codec */
2122 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2123 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2124 for (p = cs_inits; *p != (unsigned short)-1; p++)
2125 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2126 spec->cs8415_mux = 1;
2128 aureon_set_headphone_amp(ice, 1);
2131 snd_ice1712_restore_gpio_status(ice);
2133 /* initialize PCA9554 pin directions & set default input */
2134 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2135 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2137 spec->master[0] = WM_VOL_MUTE;
2138 spec->master[1] = WM_VOL_MUTE;
2139 for (i = 0; i < ice->num_total_dacs; i++) {
2140 spec->vol[i] = WM_VOL_MUTE;
2141 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2149 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2150 * hence the driver needs to sets up it properly.
2153 static unsigned char aureon51_eeprom[] __devinitdata = {
2154 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2155 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2156 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2157 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2158 [ICE_EEP2_GPIO_DIR] = 0xff,
2159 [ICE_EEP2_GPIO_DIR1] = 0xff,
2160 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2161 [ICE_EEP2_GPIO_MASK] = 0x00,
2162 [ICE_EEP2_GPIO_MASK1] = 0x00,
2163 [ICE_EEP2_GPIO_MASK2] = 0x00,
2164 [ICE_EEP2_GPIO_STATE] = 0x00,
2165 [ICE_EEP2_GPIO_STATE1] = 0x00,
2166 [ICE_EEP2_GPIO_STATE2] = 0x00,
2169 static unsigned char aureon71_eeprom[] __devinitdata = {
2170 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2171 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2172 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2173 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2174 [ICE_EEP2_GPIO_DIR] = 0xff,
2175 [ICE_EEP2_GPIO_DIR1] = 0xff,
2176 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2177 [ICE_EEP2_GPIO_MASK] = 0x00,
2178 [ICE_EEP2_GPIO_MASK1] = 0x00,
2179 [ICE_EEP2_GPIO_MASK2] = 0x00,
2180 [ICE_EEP2_GPIO_STATE] = 0x00,
2181 [ICE_EEP2_GPIO_STATE1] = 0x00,
2182 [ICE_EEP2_GPIO_STATE2] = 0x00,
2184 #define prodigy71_eeprom aureon71_eeprom
2186 static unsigned char aureon71_universe_eeprom[] __devinitdata = {
2187 [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC,
2190 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2191 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2192 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2193 [ICE_EEP2_GPIO_DIR] = 0xff,
2194 [ICE_EEP2_GPIO_DIR1] = 0xff,
2195 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2196 [ICE_EEP2_GPIO_MASK] = 0x00,
2197 [ICE_EEP2_GPIO_MASK1] = 0x00,
2198 [ICE_EEP2_GPIO_MASK2] = 0x00,
2199 [ICE_EEP2_GPIO_STATE] = 0x00,
2200 [ICE_EEP2_GPIO_STATE1] = 0x00,
2201 [ICE_EEP2_GPIO_STATE2] = 0x00,
2204 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2205 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2206 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2207 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2208 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2209 [ICE_EEP2_GPIO_DIR] = 0xff,
2210 [ICE_EEP2_GPIO_DIR1] = 0xff,
2211 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2212 [ICE_EEP2_GPIO_MASK] = 0x00,
2213 [ICE_EEP2_GPIO_MASK1] = 0x00,
2214 [ICE_EEP2_GPIO_MASK2] = 0x00,
2215 [ICE_EEP2_GPIO_STATE] = 0x00,
2216 [ICE_EEP2_GPIO_STATE1] = 0x00,
2217 [ICE_EEP2_GPIO_STATE2] = 0x00,
2219 #define prodigy71xt_eeprom prodigy71lt_eeprom
2222 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2224 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2225 .name = "Terratec Aureon 5.1-Sky",
2226 .model = "aureon51",
2227 .chip_init = aureon_init,
2228 .build_controls = aureon_add_controls,
2229 .eeprom_size = sizeof(aureon51_eeprom),
2230 .eeprom_data = aureon51_eeprom,
2231 .driver = "Aureon51",
2234 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2235 .name = "Terratec Aureon 7.1-Space",
2236 .model = "aureon71",
2237 .chip_init = aureon_init,
2238 .build_controls = aureon_add_controls,
2239 .eeprom_size = sizeof(aureon71_eeprom),
2240 .eeprom_data = aureon71_eeprom,
2241 .driver = "Aureon71",
2244 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2245 .name = "Terratec Aureon 7.1-Universe",
2246 .model = "universe",
2247 .chip_init = aureon_init,
2248 .build_controls = aureon_add_controls,
2249 .eeprom_size = sizeof(aureon71_universe_eeprom),
2250 .eeprom_data = aureon71_universe_eeprom,
2251 .driver = "Aureon71Univ", /* keep in 15 letters */
2254 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2255 .name = "Audiotrak Prodigy 7.1",
2256 .model = "prodigy71",
2257 .chip_init = aureon_init,
2258 .build_controls = aureon_add_controls,
2259 .eeprom_size = sizeof(prodigy71_eeprom),
2260 .eeprom_data = prodigy71_eeprom,
2261 .driver = "Prodigy71", /* should be identical with Aureon71 */
2264 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2265 .name = "Audiotrak Prodigy 7.1 LT",
2266 .model = "prodigy71lt",
2267 .chip_init = aureon_init,
2268 .build_controls = aureon_add_controls,
2269 .eeprom_size = sizeof(prodigy71lt_eeprom),
2270 .eeprom_data = prodigy71lt_eeprom,
2271 .driver = "Prodigy71LT",
2274 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2275 .name = "Audiotrak Prodigy 7.1 XT",
2276 .model = "prodigy71xt",
2277 .chip_init = aureon_init,
2278 .build_controls = aureon_add_controls,
2279 .eeprom_size = sizeof(prodigy71xt_eeprom),
2280 .eeprom_data = prodigy71xt_eeprom,
2281 .driver = "Prodigy71LT",
2283 { } /* terminator */