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.
51 #include <linux/delay.h>
52 #include <linux/interrupt.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/mutex.h>
57 #include <sound/core.h>
62 #include <sound/tlv.h>
64 /* AC97 register cache for Aureon */
66 unsigned short stac9744[64];
67 unsigned int cs8415_mux;
68 unsigned short master[2];
69 unsigned short vol[8];
70 unsigned char pca9554_out;
73 /* WM8770 registers */
74 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
75 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
76 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
77 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
78 #define WM_PHASE_SWAP 0x12 /* DAC phase */
79 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
80 #define WM_MUTE 0x14 /* mute controls */
81 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
82 #define WM_INT_CTRL 0x16 /* interface control */
83 #define WM_MASTER 0x17 /* master clock and mode */
84 #define WM_POWERDOWN 0x18 /* power-down controls */
85 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
86 #define WM_ADC_MUX 0x1b /* input MUX */
87 #define WM_OUT_MUX1 0x1c /* output MUX */
88 #define WM_OUT_MUX2 0x1e /* output MUX */
89 #define WM_RESET 0x1f /* software reset */
91 /* CS8415A registers */
92 #define CS8415_CTRL1 0x01
93 #define CS8415_CTRL2 0x02
94 #define CS8415_QSUB 0x14
95 #define CS8415_RATIO 0x1E
96 #define CS8415_C_BUFFER 0x20
97 #define CS8415_ID 0x7F
99 /* PCA9554 registers */
100 #define PCA9554_DEV 0x40 /* I2C device address */
101 #define PCA9554_IN 0x00 /* input port */
102 #define PCA9554_OUT 0x01 /* output port */
103 #define PCA9554_INVERT 0x02 /* input invert */
104 #define PCA9554_DIR 0x03 /* port directions */
107 * Aureon Universe additional controls using PCA9554
111 * Send data to pca9554
113 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
118 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
119 unsigned char val = 0;
121 tmp = snd_ice1712_gpio_read(ice);
123 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
124 AUREON_WM_RW|AUREON_WM_CS|
127 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
129 tmp &= ~AUREON_SPI_MOSI;
130 tmp &= ~AUREON_SPI_CLK;
131 snd_ice1712_gpio_write(ice, tmp);
135 * send i2c stop condition and start condition
136 * to obtain sane state
138 tmp |= AUREON_SPI_CLK;
139 snd_ice1712_gpio_write(ice, tmp);
141 tmp |= AUREON_SPI_MOSI;
142 snd_ice1712_gpio_write(ice, tmp);
144 tmp &= ~AUREON_SPI_MOSI;
145 snd_ice1712_gpio_write(ice, tmp);
147 tmp &= ~AUREON_SPI_CLK;
148 snd_ice1712_gpio_write(ice, tmp);
151 * send device address, command and value,
152 * skipping ack cycles inbetween
154 for (j = 0; j < 3; j++) {
156 case 0: val = dev; break;
157 case 1: val = reg; break;
158 case 2: val = data; break;
160 for (i = 7; i >= 0; i--) {
161 tmp &= ~AUREON_SPI_CLK;
162 snd_ice1712_gpio_write(ice, tmp);
165 tmp |= AUREON_SPI_MOSI;
167 tmp &= ~AUREON_SPI_MOSI;
168 snd_ice1712_gpio_write(ice, tmp);
170 tmp |= AUREON_SPI_CLK;
171 snd_ice1712_gpio_write(ice, tmp);
174 tmp &= ~AUREON_SPI_CLK;
175 snd_ice1712_gpio_write(ice, tmp);
177 tmp |= AUREON_SPI_CLK;
178 snd_ice1712_gpio_write(ice, tmp);
180 tmp &= ~AUREON_SPI_CLK;
181 snd_ice1712_gpio_write(ice, tmp);
184 tmp &= ~AUREON_SPI_CLK;
185 snd_ice1712_gpio_write(ice, tmp);
187 tmp &= ~AUREON_SPI_MOSI;
188 snd_ice1712_gpio_write(ice, tmp);
190 tmp |= AUREON_SPI_CLK;
191 snd_ice1712_gpio_write(ice, tmp);
193 tmp |= AUREON_SPI_MOSI;
194 snd_ice1712_gpio_write(ice, tmp);
198 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
199 struct snd_ctl_elem_info *uinfo)
201 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
203 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
205 uinfo->value.enumerated.items = 3;
206 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
207 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
208 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
212 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
215 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216 struct aureon_spec *spec = ice->spec;
217 ucontrol->value.enumerated.item[0] = spec->pca9554_out;
221 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
222 struct snd_ctl_elem_value *ucontrol)
224 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
225 struct aureon_spec *spec = ice->spec;
226 unsigned char oval, nval;
229 nval = ucontrol->value.enumerated.item[0];
232 snd_ice1712_save_gpio_status(ice);
233 oval = spec->pca9554_out;
234 if ((change = (oval != nval))) {
235 aureon_pca9554_write(ice, PCA9554_OUT, nval);
236 spec->pca9554_out = nval;
238 snd_ice1712_restore_gpio_status(ice);
244 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
247 struct aureon_spec *spec = ice->spec;
250 /* Send address to XILINX chip */
251 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
252 snd_ice1712_gpio_write(ice, tmp);
254 tmp |= AUREON_AC97_ADDR;
255 snd_ice1712_gpio_write(ice, tmp);
257 tmp &= ~AUREON_AC97_ADDR;
258 snd_ice1712_gpio_write(ice, tmp);
261 /* Send low-order byte to XILINX chip */
262 tmp &= ~AUREON_AC97_DATA_MASK;
263 tmp |= val & AUREON_AC97_DATA_MASK;
264 snd_ice1712_gpio_write(ice, tmp);
266 tmp |= AUREON_AC97_DATA_LOW;
267 snd_ice1712_gpio_write(ice, tmp);
269 tmp &= ~AUREON_AC97_DATA_LOW;
270 snd_ice1712_gpio_write(ice, tmp);
273 /* Send high-order byte to XILINX chip */
274 tmp &= ~AUREON_AC97_DATA_MASK;
275 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
277 snd_ice1712_gpio_write(ice, tmp);
279 tmp |= AUREON_AC97_DATA_HIGH;
280 snd_ice1712_gpio_write(ice, tmp);
282 tmp &= ~AUREON_AC97_DATA_HIGH;
283 snd_ice1712_gpio_write(ice, tmp);
286 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
287 tmp |= AUREON_AC97_COMMIT;
288 snd_ice1712_gpio_write(ice, tmp);
290 tmp &= ~AUREON_AC97_COMMIT;
291 snd_ice1712_gpio_write(ice, tmp);
294 /* Store the data in out private buffer */
295 spec->stac9744[(reg & 0x7F) >> 1] = val;
298 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
300 struct aureon_spec *spec = ice->spec;
301 return spec->stac9744[(reg & 0x7F) >> 1];
305 * Initialize STAC9744 chip
307 static int aureon_ac97_init (struct snd_ice1712 *ice)
309 struct aureon_spec *spec = ice->spec;
311 static const unsigned short ac97_defaults[] = {
335 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
336 snd_ice1712_gpio_write(ice, tmp);
339 tmp &= ~AUREON_AC97_RESET;
340 snd_ice1712_gpio_write(ice, tmp);
343 tmp |= AUREON_AC97_RESET;
344 snd_ice1712_gpio_write(ice, tmp);
347 memset(&spec->stac9744, 0, sizeof(spec->stac9744));
348 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
349 spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
351 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
356 #define AUREON_AC97_STEREO 0x80
359 * AC'97 volume controls
361 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
363 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
364 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
365 uinfo->value.integer.min = 0;
366 uinfo->value.integer.max = 31;
370 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
372 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
375 mutex_lock(&ice->gpio_mutex);
377 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
378 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
379 if (kcontrol->private_value & AUREON_AC97_STEREO)
380 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
382 mutex_unlock(&ice->gpio_mutex);
386 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
388 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
389 unsigned short ovol, nvol;
392 snd_ice1712_save_gpio_status(ice);
394 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
395 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
396 if (kcontrol->private_value & AUREON_AC97_STEREO)
397 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
398 nvol |= ovol & ~0x1F1F;
400 if ((change = (ovol != nvol)))
401 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
403 snd_ice1712_restore_gpio_status(ice);
409 * AC'97 mute controls
411 #define aureon_ac97_mute_info snd_ctl_boolean_mono_info
413 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
415 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
417 mutex_lock(&ice->gpio_mutex);
419 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
421 mutex_unlock(&ice->gpio_mutex);
425 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
427 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
428 unsigned short ovol, nvol;
431 snd_ice1712_save_gpio_status(ice);
433 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
434 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
436 if ((change = (ovol != nvol)))
437 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
439 snd_ice1712_restore_gpio_status(ice);
445 * AC'97 mute controls
447 #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
449 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
451 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
453 mutex_lock(&ice->gpio_mutex);
455 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
457 mutex_unlock(&ice->gpio_mutex);
461 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
463 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
464 unsigned short ovol, nvol;
467 snd_ice1712_save_gpio_status(ice);
469 ovol = aureon_ac97_read(ice, AC97_MIC);
470 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
472 if ((change = (ovol != nvol)))
473 aureon_ac97_write(ice, AC97_MIC, nvol);
475 snd_ice1712_restore_gpio_status(ice);
481 * write data in the SPI mode
483 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
487 unsigned int mosi, clk;
489 tmp = snd_ice1712_gpio_read(ice);
491 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
492 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
493 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
494 mosi = PRODIGY_SPI_MOSI;
495 clk = PRODIGY_SPI_CLK;
498 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
499 AUREON_WM_CS|AUREON_CS8415_CS));
500 mosi = AUREON_SPI_MOSI;
501 clk = AUREON_SPI_CLK;
507 snd_ice1712_gpio_write(ice, tmp);
510 for (i = bits - 1; i >= 0; i--) {
512 snd_ice1712_gpio_write(ice, tmp);
518 snd_ice1712_gpio_write(ice, tmp);
521 snd_ice1712_gpio_write(ice, tmp);
527 snd_ice1712_gpio_write(ice, tmp);
530 snd_ice1712_gpio_write(ice, tmp);
535 * Read data in SPI mode
537 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
541 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
542 snd_ice1712_gpio_write(ice, tmp);
544 snd_ice1712_gpio_write(ice, tmp);
547 for (i=bits-1; i>=0; i--) {
549 tmp |= AUREON_SPI_MOSI;
551 tmp &= ~AUREON_SPI_MOSI;
552 snd_ice1712_gpio_write(ice, tmp);
555 tmp |= AUREON_SPI_CLK;
556 snd_ice1712_gpio_write(ice, tmp);
559 tmp &= ~AUREON_SPI_CLK;
560 snd_ice1712_gpio_write(ice, tmp);
564 for (j=0; j<size; j++) {
565 unsigned char outdata = 0;
566 for (i=7; i>=0; i--) {
567 tmp = snd_ice1712_gpio_read(ice);
569 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
572 tmp |= AUREON_SPI_CLK;
573 snd_ice1712_gpio_write(ice, tmp);
576 tmp &= ~AUREON_SPI_CLK;
577 snd_ice1712_gpio_write(ice, tmp);
584 snd_ice1712_gpio_write(ice, tmp);
587 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
589 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
590 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
594 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
595 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
596 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
599 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
600 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
604 * get the current register value of WM codec
606 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
609 return ((unsigned short)ice->akm[0].images[reg] << 8) |
610 ice->akm[0].images[reg + 1];
614 * set the register value of WM codec
616 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
618 aureon_spi_write(ice,
619 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
620 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
621 PRODIGY_WM_CS : AUREON_WM_CS),
622 (reg << 9) | (val & 0x1ff), 16);
626 * set the register value of WM codec and remember it
628 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
630 wm_put_nocache(ice, reg, val);
632 ice->akm[0].images[reg] = val >> 8;
633 ice->akm[0].images[reg + 1] = val;
638 #define aureon_mono_bool_info snd_ctl_boolean_mono_info
641 * AC'97 master playback mute controls (Mute on WM8770 chip)
643 #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
645 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
647 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
649 mutex_lock(&ice->gpio_mutex);
651 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
653 mutex_unlock(&ice->gpio_mutex);
657 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
658 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
659 unsigned short ovol, nvol;
662 snd_ice1712_save_gpio_status(ice);
664 ovol = wm_get(ice, WM_OUT_MUX1);
665 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
666 if ((change = (ovol != nvol)))
667 wm_put(ice, WM_OUT_MUX1, nvol);
669 snd_ice1712_restore_gpio_status(ice);
674 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
675 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
676 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
677 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
678 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
681 * Logarithmic volume values for WM8770
682 * Computed as 20 * Log10(255 / x)
684 static const unsigned char wm_vol[256] = {
685 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
686 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
687 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
688 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
689 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
690 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,
691 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,
692 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,
693 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,
694 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,
695 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,
699 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
700 #define WM_VOL_MUTE 0x8000
702 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
706 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
709 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
711 wm_put(ice, index, nvol);
712 wm_put_nocache(ice, index, 0x180 | nvol);
718 #define wm_pcm_mute_info snd_ctl_boolean_mono_info
720 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
722 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
724 mutex_lock(&ice->gpio_mutex);
725 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
726 mutex_unlock(&ice->gpio_mutex);
730 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
732 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
733 unsigned short nval, oval;
736 snd_ice1712_save_gpio_status(ice);
737 oval = wm_get(ice, WM_MUTE);
738 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
739 if ((change = (nval != oval)))
740 wm_put(ice, WM_MUTE, nval);
741 snd_ice1712_restore_gpio_status(ice);
747 * Master volume attenuation mixer control
749 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
751 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
753 uinfo->value.integer.min = 0;
754 uinfo->value.integer.max = WM_VOL_MAX;
758 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
760 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
761 struct aureon_spec *spec = ice->spec;
764 ucontrol->value.integer.value[i] =
765 spec->master[i] & ~WM_VOL_MUTE;
769 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
771 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
772 struct aureon_spec *spec = ice->spec;
775 snd_ice1712_save_gpio_status(ice);
776 for (ch = 0; ch < 2; ch++) {
777 unsigned int vol = ucontrol->value.integer.value[ch];
778 if (vol > WM_VOL_MAX)
780 vol |= spec->master[ch] & WM_VOL_MUTE;
781 if (vol != spec->master[ch]) {
783 spec->master[ch] = vol;
784 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
785 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
791 snd_ice1712_restore_gpio_status(ice);
796 * DAC volume attenuation mixer control
798 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
800 int voices = kcontrol->private_value >> 8;
801 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
802 uinfo->count = voices;
803 uinfo->value.integer.min = 0; /* mute (-101dB) */
804 uinfo->value.integer.max = 0x7F; /* 0dB */
808 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
810 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
811 struct aureon_spec *spec = ice->spec;
814 voices = kcontrol->private_value >> 8;
815 ofs = kcontrol->private_value & 0xff;
816 for (i = 0; i < voices; i++)
817 ucontrol->value.integer.value[i] =
818 spec->vol[ofs+i] & ~WM_VOL_MUTE;
822 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
824 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
825 struct aureon_spec *spec = ice->spec;
826 int i, idx, ofs, voices;
829 voices = kcontrol->private_value >> 8;
830 ofs = kcontrol->private_value & 0xff;
831 snd_ice1712_save_gpio_status(ice);
832 for (i = 0; i < voices; i++) {
833 unsigned int vol = ucontrol->value.integer.value[i];
836 vol |= spec->vol[ofs+i];
837 if (vol != spec->vol[ofs+i]) {
838 spec->vol[ofs+i] = vol;
839 idx = WM_DAC_ATTEN + ofs + i;
840 wm_set_vol(ice, idx, spec->vol[ofs + i],
845 snd_ice1712_restore_gpio_status(ice);
850 * WM8770 mute control
852 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
853 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
854 uinfo->count = kcontrol->private_value >> 8;
855 uinfo->value.integer.min = 0;
856 uinfo->value.integer.max = 1;
860 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
862 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
863 struct aureon_spec *spec = ice->spec;
866 voices = kcontrol->private_value >> 8;
867 ofs = kcontrol->private_value & 0xFF;
869 for (i = 0; i < voices; i++)
870 ucontrol->value.integer.value[i] =
871 (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
875 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
877 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
878 struct aureon_spec *spec = ice->spec;
879 int change = 0, voices, ofs, i;
881 voices = kcontrol->private_value >> 8;
882 ofs = kcontrol->private_value & 0xFF;
884 snd_ice1712_save_gpio_status(ice);
885 for (i = 0; i < voices; i++) {
886 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
887 if (ucontrol->value.integer.value[i] != val) {
888 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
889 spec->vol[ofs + i] |=
890 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
891 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
896 snd_ice1712_restore_gpio_status(ice);
902 * WM8770 master mute control
904 #define wm_master_mute_info snd_ctl_boolean_stereo_info
906 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
908 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
909 struct aureon_spec *spec = ice->spec;
911 ucontrol->value.integer.value[0] =
912 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
913 ucontrol->value.integer.value[1] =
914 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
918 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
920 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
921 struct aureon_spec *spec = ice->spec;
924 snd_ice1712_save_gpio_status(ice);
925 for (i = 0; i < 2; i++) {
926 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
927 if (ucontrol->value.integer.value[i] != val) {
929 spec->master[i] &= ~WM_VOL_MUTE;
931 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
932 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
933 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
939 snd_ice1712_restore_gpio_status(ice);
944 /* digital master volume */
946 #define PCM_RES 128 /* -64dB */
947 #define PCM_MIN (PCM_0dB - PCM_RES)
948 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
950 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
952 uinfo->value.integer.min = 0; /* mute (-64dB) */
953 uinfo->value.integer.max = PCM_RES; /* 0dB */
957 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
959 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
962 mutex_lock(&ice->gpio_mutex);
963 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
964 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
965 ucontrol->value.integer.value[0] = val;
966 mutex_unlock(&ice->gpio_mutex);
970 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
972 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
973 unsigned short ovol, nvol;
976 nvol = ucontrol->value.integer.value[0];
979 snd_ice1712_save_gpio_status(ice);
980 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
981 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
983 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
984 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
987 snd_ice1712_restore_gpio_status(ice);
994 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
996 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
998 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1002 mutex_lock(&ice->gpio_mutex);
1003 for (i = 0; i < 2; i++) {
1004 val = wm_get(ice, WM_ADC_GAIN + i);
1005 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1007 mutex_unlock(&ice->gpio_mutex);
1011 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1013 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1014 unsigned short new, old;
1017 snd_ice1712_save_gpio_status(ice);
1018 for (i = 0; i < 2; i++) {
1019 old = wm_get(ice, WM_ADC_GAIN + i);
1020 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1022 wm_put(ice, WM_ADC_GAIN + i, new);
1026 snd_ice1712_restore_gpio_status(ice);
1032 * ADC gain mixer control
1034 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1036 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1038 uinfo->value.integer.min = 0; /* -12dB */
1039 uinfo->value.integer.max = 0x1f; /* 19dB */
1043 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1049 mutex_lock(&ice->gpio_mutex);
1050 for (i = 0; i < 2; i++) {
1051 idx = WM_ADC_GAIN + i;
1052 vol = wm_get(ice, idx) & 0x1f;
1053 ucontrol->value.integer.value[i] = vol;
1055 mutex_unlock(&ice->gpio_mutex);
1059 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1061 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1063 unsigned short ovol, nvol;
1066 snd_ice1712_save_gpio_status(ice);
1067 for (i = 0; i < 2; i++) {
1068 idx = WM_ADC_GAIN + i;
1069 nvol = ucontrol->value.integer.value[i] & 0x1f;
1070 ovol = wm_get(ice, idx);
1071 if ((ovol & 0x1f) != nvol) {
1072 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1076 snd_ice1712_restore_gpio_status(ice);
1081 * ADC input mux mixer control
1083 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1085 static const char * const texts[] = {
1092 static const char * const universe_texts[] = {
1102 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1104 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1106 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1107 uinfo->value.enumerated.items = 8;
1108 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1109 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1110 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1113 uinfo->value.enumerated.items = 5;
1114 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1115 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1116 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1121 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1123 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1126 mutex_lock(&ice->gpio_mutex);
1127 val = wm_get(ice, WM_ADC_MUX);
1128 ucontrol->value.enumerated.item[0] = val & 7;
1129 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1130 mutex_unlock(&ice->gpio_mutex);
1134 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1136 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1137 unsigned short oval, nval;
1140 snd_ice1712_save_gpio_status(ice);
1141 oval = wm_get(ice, WM_ADC_MUX);
1142 nval = oval & ~0x77;
1143 nval |= ucontrol->value.enumerated.item[0] & 7;
1144 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1145 change = (oval != nval);
1147 wm_put(ice, WM_ADC_MUX, nval);
1148 snd_ice1712_restore_gpio_status(ice);
1155 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1157 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1158 static const char * const aureon_texts[] = {
1162 static const char * const prodigy_texts[] = {
1166 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1168 uinfo->value.enumerated.items = 2;
1169 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1170 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1171 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1172 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1174 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1178 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1180 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1181 struct aureon_spec *spec = ice->spec;
1183 //snd_ice1712_save_gpio_status(ice);
1184 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1185 ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1186 //snd_ice1712_restore_gpio_status(ice);
1190 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1192 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1193 struct aureon_spec *spec = ice->spec;
1194 unsigned short oval, nval;
1197 snd_ice1712_save_gpio_status(ice);
1198 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1199 nval = oval & ~0x07;
1200 nval |= ucontrol->value.enumerated.item[0] & 7;
1201 change = (oval != nval);
1203 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1204 snd_ice1712_restore_gpio_status(ice);
1205 spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1209 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1211 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1213 uinfo->value.integer.min = 0;
1214 uinfo->value.integer.max = 192000;
1218 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1220 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1221 unsigned char ratio;
1222 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1223 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1230 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1232 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1234 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1235 snd_ice1712_save_gpio_status(ice);
1236 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1237 snd_ice1712_restore_gpio_status(ice);
1241 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1243 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1244 unsigned char oval, nval;
1246 snd_ice1712_save_gpio_status(ice);
1247 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1248 if (ucontrol->value.integer.value[0])
1249 nval = oval & ~0x20;
1252 if ((change = (oval != nval)))
1253 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1254 snd_ice1712_restore_gpio_status(ice);
1259 * CS8415A Q-Sub info
1261 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1262 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1267 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1268 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1270 snd_ice1712_save_gpio_status(ice);
1271 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1272 snd_ice1712_restore_gpio_status(ice);
1277 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1278 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1283 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1284 memset(ucontrol->value.iec958.status, 0xFF, 24);
1288 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1289 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1291 snd_ice1712_save_gpio_status(ice);
1292 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1293 snd_ice1712_restore_gpio_status(ice);
1298 * Headphone Amplifier
1300 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1302 unsigned int tmp, tmp2;
1304 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1306 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1307 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1308 tmp |= AUREON_HP_SEL;
1310 tmp |= PRODIGY_HP_SEL;
1312 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1313 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1314 tmp &= ~ AUREON_HP_SEL;
1316 tmp &= ~ PRODIGY_HP_SEL;
1318 snd_ice1712_gpio_write(ice, tmp);
1324 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1326 unsigned int tmp = snd_ice1712_gpio_read(ice);
1328 return ( tmp & AUREON_HP_SEL )!= 0;
1331 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1333 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1335 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1337 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1342 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1344 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1346 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1353 #define aureon_deemp_info snd_ctl_boolean_mono_info
1355 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1357 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1358 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1362 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1364 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1366 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1367 if (ucontrol->value.integer.value[0])
1371 if (temp != temp2) {
1372 wm_put(ice, WM_DAC_CTRL2, temp);
1381 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1383 static const char * const texts[2] = { "128x", "64x" };
1385 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1387 uinfo->value.enumerated.items = 2;
1389 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1390 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1391 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1396 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1398 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1399 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1403 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1406 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1408 temp2 = temp = wm_get(ice, WM_MASTER);
1410 if (ucontrol->value.enumerated.item[0])
1415 if (temp != temp2) {
1416 wm_put(ice, WM_MASTER, temp);
1426 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1428 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1429 .name = "Master Playback Switch",
1430 .info = wm_master_mute_info,
1431 .get = wm_master_mute_get,
1432 .put = wm_master_mute_put
1435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1436 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1437 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1438 .name = "Master Playback Volume",
1439 .info = wm_master_vol_info,
1440 .get = wm_master_vol_get,
1441 .put = wm_master_vol_put,
1442 .tlv = { .p = db_scale_wm_dac }
1445 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1446 .name = "Front Playback Switch",
1447 .info = wm_mute_info,
1450 .private_value = (2 << 8) | 0
1453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1455 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1456 .name = "Front Playback Volume",
1457 .info = wm_vol_info,
1460 .private_value = (2 << 8) | 0,
1461 .tlv = { .p = db_scale_wm_dac }
1464 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1465 .name = "Rear Playback Switch",
1466 .info = wm_mute_info,
1469 .private_value = (2 << 8) | 2
1472 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1473 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1474 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1475 .name = "Rear Playback Volume",
1476 .info = wm_vol_info,
1479 .private_value = (2 << 8) | 2,
1480 .tlv = { .p = db_scale_wm_dac }
1483 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1484 .name = "Center Playback Switch",
1485 .info = wm_mute_info,
1488 .private_value = (1 << 8) | 4
1491 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1492 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1493 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1494 .name = "Center Playback Volume",
1495 .info = wm_vol_info,
1498 .private_value = (1 << 8) | 4,
1499 .tlv = { .p = db_scale_wm_dac }
1502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1503 .name = "LFE Playback Switch",
1504 .info = wm_mute_info,
1507 .private_value = (1 << 8) | 5
1510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1511 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1512 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1513 .name = "LFE Playback Volume",
1514 .info = wm_vol_info,
1517 .private_value = (1 << 8) | 5,
1518 .tlv = { .p = db_scale_wm_dac }
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 .name = "Side Playback Switch",
1523 .info = wm_mute_info,
1526 .private_value = (2 << 8) | 6
1529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1530 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1531 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1532 .name = "Side Playback Volume",
1533 .info = wm_vol_info,
1536 .private_value = (2 << 8) | 6,
1537 .tlv = { .p = db_scale_wm_dac }
1541 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544 .name = "PCM Playback Switch",
1545 .info = wm_pcm_mute_info,
1546 .get = wm_pcm_mute_get,
1547 .put = wm_pcm_mute_put
1550 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1551 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1552 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1553 .name = "PCM Playback Volume",
1554 .info = wm_pcm_vol_info,
1555 .get = wm_pcm_vol_get,
1556 .put = wm_pcm_vol_put,
1557 .tlv = { .p = db_scale_wm_pcm }
1560 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1561 .name = "Capture Switch",
1562 .info = wm_adc_mute_info,
1563 .get = wm_adc_mute_get,
1564 .put = wm_adc_mute_put,
1567 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1568 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1569 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1570 .name = "Capture Volume",
1571 .info = wm_adc_vol_info,
1572 .get = wm_adc_vol_get,
1573 .put = wm_adc_vol_put,
1574 .tlv = { .p = db_scale_wm_adc }
1577 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1578 .name = "Capture Source",
1579 .info = wm_adc_mux_info,
1580 .get = wm_adc_mux_get,
1581 .put = wm_adc_mux_put,
1585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586 .name = "External Amplifier",
1587 .info = aureon_hpamp_info,
1588 .get = aureon_hpamp_get,
1589 .put = aureon_hpamp_put
1592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593 .name = "DAC Deemphasis Switch",
1594 .info = aureon_deemp_info,
1595 .get = aureon_deemp_get,
1596 .put = aureon_deemp_put
1599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1600 .name = "ADC Oversampling",
1601 .info = aureon_oversampling_info,
1602 .get = aureon_oversampling_get,
1603 .put = aureon_oversampling_put
1607 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1609 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1610 .name = "AC97 Playback Switch",
1611 .info = aureon_ac97_mmute_info,
1612 .get = aureon_ac97_mmute_get,
1613 .put = aureon_ac97_mmute_put,
1614 .private_value = AC97_MASTER
1617 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1619 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1620 .name = "AC97 Playback Volume",
1621 .info = aureon_ac97_vol_info,
1622 .get = aureon_ac97_vol_get,
1623 .put = aureon_ac97_vol_put,
1624 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1625 .tlv = { .p = db_scale_ac97_master }
1628 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1629 .name = "CD Playback Switch",
1630 .info = aureon_ac97_mute_info,
1631 .get = aureon_ac97_mute_get,
1632 .put = aureon_ac97_mute_put,
1633 .private_value = AC97_CD
1636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1637 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1638 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1639 .name = "CD Playback Volume",
1640 .info = aureon_ac97_vol_info,
1641 .get = aureon_ac97_vol_get,
1642 .put = aureon_ac97_vol_put,
1643 .private_value = AC97_CD|AUREON_AC97_STEREO,
1644 .tlv = { .p = db_scale_ac97_gain }
1647 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1648 .name = "Aux Playback Switch",
1649 .info = aureon_ac97_mute_info,
1650 .get = aureon_ac97_mute_get,
1651 .put = aureon_ac97_mute_put,
1652 .private_value = AC97_AUX,
1655 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1656 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1657 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1658 .name = "Aux Playback Volume",
1659 .info = aureon_ac97_vol_info,
1660 .get = aureon_ac97_vol_get,
1661 .put = aureon_ac97_vol_put,
1662 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1663 .tlv = { .p = db_scale_ac97_gain }
1666 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1667 .name = "Line Playback Switch",
1668 .info = aureon_ac97_mute_info,
1669 .get = aureon_ac97_mute_get,
1670 .put = aureon_ac97_mute_put,
1671 .private_value = AC97_LINE
1674 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1675 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1676 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1677 .name = "Line Playback Volume",
1678 .info = aureon_ac97_vol_info,
1679 .get = aureon_ac97_vol_get,
1680 .put = aureon_ac97_vol_put,
1681 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1682 .tlv = { .p = db_scale_ac97_gain }
1685 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1686 .name = "Mic Playback Switch",
1687 .info = aureon_ac97_mute_info,
1688 .get = aureon_ac97_mute_get,
1689 .put = aureon_ac97_mute_put,
1690 .private_value = AC97_MIC
1693 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1694 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1695 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1696 .name = "Mic Playback Volume",
1697 .info = aureon_ac97_vol_info,
1698 .get = aureon_ac97_vol_get,
1699 .put = aureon_ac97_vol_put,
1700 .private_value = AC97_MIC,
1701 .tlv = { .p = db_scale_ac97_gain }
1704 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1705 .name = "Mic Boost (+20dB)",
1706 .info = aureon_ac97_micboost_info,
1707 .get = aureon_ac97_micboost_get,
1708 .put = aureon_ac97_micboost_put
1712 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1714 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1715 .name = "AC97 Playback Switch",
1716 .info = aureon_ac97_mmute_info,
1717 .get = aureon_ac97_mmute_get,
1718 .put = aureon_ac97_mmute_put,
1719 .private_value = AC97_MASTER
1722 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1723 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1724 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1725 .name = "AC97 Playback Volume",
1726 .info = aureon_ac97_vol_info,
1727 .get = aureon_ac97_vol_get,
1728 .put = aureon_ac97_vol_put,
1729 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1730 .tlv = { .p = db_scale_ac97_master }
1733 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1734 .name = "CD Playback Switch",
1735 .info = aureon_ac97_mute_info,
1736 .get = aureon_ac97_mute_get,
1737 .put = aureon_ac97_mute_put,
1738 .private_value = AC97_AUX
1741 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1742 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1743 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1744 .name = "CD Playback Volume",
1745 .info = aureon_ac97_vol_info,
1746 .get = aureon_ac97_vol_get,
1747 .put = aureon_ac97_vol_put,
1748 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1749 .tlv = { .p = db_scale_ac97_gain }
1752 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1753 .name = "Phono Playback Switch",
1754 .info = aureon_ac97_mute_info,
1755 .get = aureon_ac97_mute_get,
1756 .put = aureon_ac97_mute_put,
1757 .private_value = AC97_CD
1760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1761 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1762 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1763 .name = "Phono Playback Volume",
1764 .info = aureon_ac97_vol_info,
1765 .get = aureon_ac97_vol_get,
1766 .put = aureon_ac97_vol_put,
1767 .private_value = AC97_CD|AUREON_AC97_STEREO,
1768 .tlv = { .p = db_scale_ac97_gain }
1771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1772 .name = "Line Playback Switch",
1773 .info = aureon_ac97_mute_info,
1774 .get = aureon_ac97_mute_get,
1775 .put = aureon_ac97_mute_put,
1776 .private_value = AC97_LINE
1779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1781 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1782 .name = "Line Playback Volume",
1783 .info = aureon_ac97_vol_info,
1784 .get = aureon_ac97_vol_get,
1785 .put = aureon_ac97_vol_put,
1786 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1787 .tlv = { .p = db_scale_ac97_gain }
1790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791 .name = "Mic Playback Switch",
1792 .info = aureon_ac97_mute_info,
1793 .get = aureon_ac97_mute_get,
1794 .put = aureon_ac97_mute_put,
1795 .private_value = AC97_MIC
1798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1799 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1800 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1801 .name = "Mic Playback Volume",
1802 .info = aureon_ac97_vol_info,
1803 .get = aureon_ac97_vol_get,
1804 .put = aureon_ac97_vol_put,
1805 .private_value = AC97_MIC,
1806 .tlv = { .p = db_scale_ac97_gain }
1809 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1810 .name = "Mic Boost (+20dB)",
1811 .info = aureon_ac97_micboost_info,
1812 .get = aureon_ac97_micboost_get,
1813 .put = aureon_ac97_micboost_put
1816 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1817 .name = "Aux Playback Switch",
1818 .info = aureon_ac97_mute_info,
1819 .get = aureon_ac97_mute_get,
1820 .put = aureon_ac97_mute_put,
1821 .private_value = AC97_VIDEO,
1824 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1825 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1826 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1827 .name = "Aux Playback Volume",
1828 .info = aureon_ac97_vol_info,
1829 .get = aureon_ac97_vol_get,
1830 .put = aureon_ac97_vol_put,
1831 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1832 .tlv = { .p = db_scale_ac97_gain }
1835 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1836 .name = "Aux Source",
1837 .info = aureon_universe_inmux_info,
1838 .get = aureon_universe_inmux_get,
1839 .put = aureon_universe_inmux_put
1844 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1846 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1847 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1848 .info = aureon_cs8415_mute_info,
1849 .get = aureon_cs8415_mute_get,
1850 .put = aureon_cs8415_mute_put
1853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1854 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1855 .info = aureon_cs8415_mux_info,
1856 .get = aureon_cs8415_mux_get,
1857 .put = aureon_cs8415_mux_put,
1860 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1861 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1862 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1863 .info = aureon_cs8415_qsub_info,
1864 .get = aureon_cs8415_qsub_get,
1867 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1868 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1869 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1870 .info = aureon_cs8415_spdif_info,
1871 .get = aureon_cs8415_mask_get
1874 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1875 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1876 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1877 .info = aureon_cs8415_spdif_info,
1878 .get = aureon_cs8415_spdif_get
1881 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1882 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1883 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1884 .info = aureon_cs8415_rate_info,
1885 .get = aureon_cs8415_rate_get
1889 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1891 unsigned int i, counts;
1894 counts = ARRAY_SIZE(aureon_dac_controls);
1895 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1896 counts -= 2; /* no side */
1897 for (i = 0; i < counts; i++) {
1898 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1903 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1904 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1909 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1910 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1911 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1916 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1917 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1918 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1919 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1925 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1926 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1928 snd_ice1712_save_gpio_status(ice);
1929 id = aureon_cs8415_get(ice, CS8415_ID);
1931 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1932 else if ((id & 0x0F) != 0x01)
1933 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1935 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1936 struct snd_kcontrol *kctl;
1937 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1941 kctl->id.device = ice->pcm->device;
1944 snd_ice1712_restore_gpio_status(ice);
1952 * initialize the chip
1954 static int __devinit aureon_init(struct snd_ice1712 *ice)
1956 static const unsigned short wm_inits_aureon[] = {
1957 /* These come first to reduce init pop noise */
1958 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1959 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1960 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1962 0x18, 0x000, /* All power-up */
1964 0x16, 0x122, /* I2S, normal polarity, 24bit */
1965 0x17, 0x022, /* 256fs, slave mode */
1966 0x00, 0, /* DAC1 analog mute */
1967 0x01, 0, /* DAC2 analog mute */
1968 0x02, 0, /* DAC3 analog mute */
1969 0x03, 0, /* DAC4 analog mute */
1970 0x04, 0, /* DAC5 analog mute */
1971 0x05, 0, /* DAC6 analog mute */
1972 0x06, 0, /* DAC7 analog mute */
1973 0x07, 0, /* DAC8 analog mute */
1974 0x08, 0x100, /* master analog mute */
1975 0x09, 0xff, /* DAC1 digital full */
1976 0x0a, 0xff, /* DAC2 digital full */
1977 0x0b, 0xff, /* DAC3 digital full */
1978 0x0c, 0xff, /* DAC4 digital full */
1979 0x0d, 0xff, /* DAC5 digital full */
1980 0x0e, 0xff, /* DAC6 digital full */
1981 0x0f, 0xff, /* DAC7 digital full */
1982 0x10, 0xff, /* DAC8 digital full */
1983 0x11, 0x1ff, /* master digital full */
1984 0x12, 0x000, /* phase normal */
1985 0x13, 0x090, /* unmute DAC L/R */
1986 0x14, 0x000, /* all unmute */
1987 0x15, 0x000, /* no deemphasis, no ZFLG */
1988 0x19, 0x000, /* -12dB ADC/L */
1989 0x1a, 0x000, /* -12dB ADC/R */
1992 static const unsigned short wm_inits_prodigy[] = {
1994 /* These come first to reduce init pop noise */
1995 0x1b, 0x000, /* ADC Mux */
1996 0x1c, 0x009, /* Out Mux1 */
1997 0x1d, 0x009, /* Out Mux2 */
1999 0x18, 0x000, /* All power-up */
2001 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
2002 0x17, 0x006, /* 128fs, slave mode */
2004 0x00, 0, /* DAC1 analog mute */
2005 0x01, 0, /* DAC2 analog mute */
2006 0x02, 0, /* DAC3 analog mute */
2007 0x03, 0, /* DAC4 analog mute */
2008 0x04, 0, /* DAC5 analog mute */
2009 0x05, 0, /* DAC6 analog mute */
2010 0x06, 0, /* DAC7 analog mute */
2011 0x07, 0, /* DAC8 analog mute */
2012 0x08, 0x100, /* master analog mute */
2014 0x09, 0x7f, /* DAC1 digital full */
2015 0x0a, 0x7f, /* DAC2 digital full */
2016 0x0b, 0x7f, /* DAC3 digital full */
2017 0x0c, 0x7f, /* DAC4 digital full */
2018 0x0d, 0x7f, /* DAC5 digital full */
2019 0x0e, 0x7f, /* DAC6 digital full */
2020 0x0f, 0x7f, /* DAC7 digital full */
2021 0x10, 0x7f, /* DAC8 digital full */
2022 0x11, 0x1FF, /* master digital full */
2024 0x12, 0x000, /* phase normal */
2025 0x13, 0x090, /* unmute DAC L/R */
2026 0x14, 0x000, /* all unmute */
2027 0x15, 0x000, /* no deemphasis, no ZFLG */
2029 0x19, 0x000, /* -12dB ADC/L */
2030 0x1a, 0x000, /* -12dB ADC/R */
2034 static const unsigned short cs_inits[] = {
2036 0x0180, /* no mute, OMCK output on RMCK pin */
2037 0x0201, /* S/PDIF source on RXP1 */
2038 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2041 struct aureon_spec *spec;
2043 const unsigned short *p;
2046 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2051 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2052 ice->num_total_dacs = 6;
2053 ice->num_total_adcs = 2;
2055 /* aureon 7.1 and prodigy 7.1 */
2056 ice->num_total_dacs = 8;
2057 ice->num_total_adcs = 2;
2060 /* to remeber the register values of CS8415 */
2061 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2064 ice->akm_codecs = 1;
2066 if ((err = aureon_ac97_init(ice)) != 0)
2069 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2071 /* reset the wm codec as the SPI mode */
2072 snd_ice1712_save_gpio_status(ice);
2073 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2075 tmp = snd_ice1712_gpio_read(ice);
2076 tmp &= ~AUREON_WM_RESET;
2077 snd_ice1712_gpio_write(ice, tmp);
2079 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2080 snd_ice1712_gpio_write(ice, tmp);
2082 tmp |= AUREON_WM_RESET;
2083 snd_ice1712_gpio_write(ice, tmp);
2086 /* initialize WM8770 codec */
2087 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2088 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2089 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2090 p = wm_inits_prodigy;
2092 p = wm_inits_aureon;
2093 for (; *p != (unsigned short)-1; p += 2)
2094 wm_put(ice, p[0], p[1]);
2096 /* initialize CS8415A codec */
2097 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2098 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2099 for (p = cs_inits; *p != (unsigned short)-1; p++)
2100 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2101 spec->cs8415_mux = 1;
2103 aureon_set_headphone_amp(ice, 1);
2106 snd_ice1712_restore_gpio_status(ice);
2108 /* initialize PCA9554 pin directions & set default input*/
2109 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2110 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2112 spec->master[0] = WM_VOL_MUTE;
2113 spec->master[1] = WM_VOL_MUTE;
2114 for (i = 0; i < ice->num_total_dacs; i++) {
2115 spec->vol[i] = WM_VOL_MUTE;
2116 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2124 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2125 * hence the driver needs to sets up it properly.
2128 static unsigned char aureon51_eeprom[] __devinitdata = {
2129 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2130 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2131 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2132 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2133 [ICE_EEP2_GPIO_DIR] = 0xff,
2134 [ICE_EEP2_GPIO_DIR1] = 0xff,
2135 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2136 [ICE_EEP2_GPIO_MASK] = 0x00,
2137 [ICE_EEP2_GPIO_MASK1] = 0x00,
2138 [ICE_EEP2_GPIO_MASK2] = 0x00,
2139 [ICE_EEP2_GPIO_STATE] = 0x00,
2140 [ICE_EEP2_GPIO_STATE1] = 0x00,
2141 [ICE_EEP2_GPIO_STATE2] = 0x00,
2144 static unsigned char aureon71_eeprom[] __devinitdata = {
2145 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2146 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2147 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2148 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2149 [ICE_EEP2_GPIO_DIR] = 0xff,
2150 [ICE_EEP2_GPIO_DIR1] = 0xff,
2151 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2152 [ICE_EEP2_GPIO_MASK] = 0x00,
2153 [ICE_EEP2_GPIO_MASK1] = 0x00,
2154 [ICE_EEP2_GPIO_MASK2] = 0x00,
2155 [ICE_EEP2_GPIO_STATE] = 0x00,
2156 [ICE_EEP2_GPIO_STATE1] = 0x00,
2157 [ICE_EEP2_GPIO_STATE2] = 0x00,
2159 #define prodigy71_eeprom aureon71_eeprom
2161 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2162 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2163 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2164 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2165 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2166 [ICE_EEP2_GPIO_DIR] = 0xff,
2167 [ICE_EEP2_GPIO_DIR1] = 0xff,
2168 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2169 [ICE_EEP2_GPIO_MASK] = 0x00,
2170 [ICE_EEP2_GPIO_MASK1] = 0x00,
2171 [ICE_EEP2_GPIO_MASK2] = 0x00,
2172 [ICE_EEP2_GPIO_STATE] = 0x00,
2173 [ICE_EEP2_GPIO_STATE1] = 0x00,
2174 [ICE_EEP2_GPIO_STATE2] = 0x00,
2176 #define prodigy71xt_eeprom prodigy71lt_eeprom
2179 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2181 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2182 .name = "Terratec Aureon 5.1-Sky",
2183 .model = "aureon51",
2184 .chip_init = aureon_init,
2185 .build_controls = aureon_add_controls,
2186 .eeprom_size = sizeof(aureon51_eeprom),
2187 .eeprom_data = aureon51_eeprom,
2188 .driver = "Aureon51",
2191 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2192 .name = "Terratec Aureon 7.1-Space",
2193 .model = "aureon71",
2194 .chip_init = aureon_init,
2195 .build_controls = aureon_add_controls,
2196 .eeprom_size = sizeof(aureon71_eeprom),
2197 .eeprom_data = aureon71_eeprom,
2198 .driver = "Aureon71",
2201 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2202 .name = "Terratec Aureon 7.1-Universe",
2203 .model = "universe",
2204 .chip_init = aureon_init,
2205 .build_controls = aureon_add_controls,
2206 .eeprom_size = sizeof(aureon71_eeprom),
2207 .eeprom_data = aureon71_eeprom,
2208 .driver = "Aureon71Univ", /* keep in 15 letters */
2211 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2212 .name = "Audiotrak Prodigy 7.1",
2213 .model = "prodigy71",
2214 .chip_init = aureon_init,
2215 .build_controls = aureon_add_controls,
2216 .eeprom_size = sizeof(prodigy71_eeprom),
2217 .eeprom_data = prodigy71_eeprom,
2218 .driver = "Prodigy71", /* should be identical with Aureon71 */
2221 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2222 .name = "Audiotrak Prodigy 7.1 LT",
2223 .model = "prodigy71lt",
2224 .chip_init = aureon_init,
2225 .build_controls = aureon_add_controls,
2226 .eeprom_size = sizeof(prodigy71lt_eeprom),
2227 .eeprom_data = prodigy71lt_eeprom,
2228 .driver = "Prodigy71LT",
2231 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2232 .name = "Audiotrak Prodigy 7.1 XT",
2233 .model = "prodigy71xt",
2234 .chip_init = aureon_init,
2235 .build_controls = aureon_add_controls,
2236 .eeprom_size = sizeof(prodigy71xt_eeprom),
2237 .eeprom_data = prodigy71xt_eeprom,
2238 .driver = "Prodigy71LT",
2240 { } /* terminator */