2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Terratec Aureon cards
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
26 * both wm and akm codecs are pretty similar, so we can integrate
27 * both controls in the future, once if wm codecs are reused in
30 * - DAC digital volumes are not implemented in the mixer.
31 * if they show better response than DAC analog volumes, we can use them
34 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
37 * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
38 * added 64x/128x oversampling switch (should be 64x only for 96khz)
39 * fixed some recording labels (still need to check the rest)
40 * recording is working probably thanks to correct wm8770 initialization
42 * version 0.5: Initial release:
43 * working: analog output, mixer, headphone amplifier switch
44 * not working: prety much everything else, at least i could verify that
45 * we have no digital output, no capture, pretty bad clicks and poops
46 * on mixer switch and other coll stuff.
50 #include <sound/driver.h>
52 #include <linux/delay.h>
53 #include <linux/interrupt.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <linux/mutex.h>
58 #include <sound/core.h>
63 #include <sound/tlv.h>
65 /* WM8770 registers */
66 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
67 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
68 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
69 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
70 #define WM_PHASE_SWAP 0x12 /* DAC phase */
71 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
72 #define WM_MUTE 0x14 /* mute controls */
73 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
74 #define WM_INT_CTRL 0x16 /* interface control */
75 #define WM_MASTER 0x17 /* master clock and mode */
76 #define WM_POWERDOWN 0x18 /* power-down controls */
77 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
78 #define WM_ADC_MUX 0x1b /* input MUX */
79 #define WM_OUT_MUX1 0x1c /* output MUX */
80 #define WM_OUT_MUX2 0x1e /* output MUX */
81 #define WM_RESET 0x1f /* software reset */
83 /* CS8415A registers */
84 #define CS8415_CTRL1 0x01
85 #define CS8415_CTRL2 0x02
86 #define CS8415_QSUB 0x14
87 #define CS8415_RATIO 0x1E
88 #define CS8415_C_BUFFER 0x20
89 #define CS8415_ID 0x7F
91 /* PCA9554 registers */
92 #define PCA9554_DEV 0x40 /* I2C device address */
93 #define PCA9554_IN 0x00 /* input port */
94 #define PCA9554_OUT 0x01 /* output port */
95 #define PCA9554_INVERT 0x02 /* input invert */
96 #define PCA9554_DIR 0x03 /* port directions */
99 * Aureon Universe additional controls using PCA9554
103 * Send data to pca9554
105 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
110 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
111 unsigned char val = 0;
113 tmp = snd_ice1712_gpio_read(ice);
115 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
116 AUREON_WM_RW|AUREON_WM_CS|
119 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
121 tmp &= ~AUREON_SPI_MOSI;
122 tmp &= ~AUREON_SPI_CLK;
123 snd_ice1712_gpio_write(ice, tmp);
127 * send i2c stop condition and start condition
128 * to obtain sane state
130 tmp |= AUREON_SPI_CLK;
131 snd_ice1712_gpio_write(ice, tmp);
133 tmp |= AUREON_SPI_MOSI;
134 snd_ice1712_gpio_write(ice, tmp);
136 tmp &= ~AUREON_SPI_MOSI;
137 snd_ice1712_gpio_write(ice, tmp);
139 tmp &= ~AUREON_SPI_CLK;
140 snd_ice1712_gpio_write(ice, tmp);
143 * send device address, command and value,
144 * skipping ack cycles inbetween
146 for (j = 0; j < 3; j++) {
148 case 0: val = dev; break;
149 case 1: val = reg; break;
150 case 2: val = data; break;
152 for (i = 7; i >= 0; i--) {
153 tmp &= ~AUREON_SPI_CLK;
154 snd_ice1712_gpio_write(ice, tmp);
157 tmp |= AUREON_SPI_MOSI;
159 tmp &= ~AUREON_SPI_MOSI;
160 snd_ice1712_gpio_write(ice, tmp);
162 tmp |= AUREON_SPI_CLK;
163 snd_ice1712_gpio_write(ice, tmp);
166 tmp &= ~AUREON_SPI_CLK;
167 snd_ice1712_gpio_write(ice, tmp);
169 tmp |= AUREON_SPI_CLK;
170 snd_ice1712_gpio_write(ice, tmp);
172 tmp &= ~AUREON_SPI_CLK;
173 snd_ice1712_gpio_write(ice, tmp);
176 tmp &= ~AUREON_SPI_CLK;
177 snd_ice1712_gpio_write(ice, tmp);
179 tmp &= ~AUREON_SPI_MOSI;
180 snd_ice1712_gpio_write(ice, tmp);
182 tmp |= AUREON_SPI_CLK;
183 snd_ice1712_gpio_write(ice, tmp);
185 tmp |= AUREON_SPI_MOSI;
186 snd_ice1712_gpio_write(ice, tmp);
190 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_info *uinfo)
193 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
195 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
197 uinfo->value.enumerated.items = 3;
198 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
199 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
204 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
205 struct snd_ctl_elem_value *ucontrol)
207 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
208 ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
212 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
215 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216 unsigned char oval, nval;
219 snd_ice1712_save_gpio_status(ice);
221 oval = ice->spec.aureon.pca9554_out;
222 nval = ucontrol->value.integer.value[0];
223 if ((change = (oval != nval))) {
224 aureon_pca9554_write(ice, PCA9554_OUT, nval);
225 ice->spec.aureon.pca9554_out = nval;
227 snd_ice1712_restore_gpio_status(ice);
233 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
238 /* Send address to XILINX chip */
239 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
240 snd_ice1712_gpio_write(ice, tmp);
242 tmp |= AUREON_AC97_ADDR;
243 snd_ice1712_gpio_write(ice, tmp);
245 tmp &= ~AUREON_AC97_ADDR;
246 snd_ice1712_gpio_write(ice, tmp);
249 /* Send low-order byte to XILINX chip */
250 tmp &= ~AUREON_AC97_DATA_MASK;
251 tmp |= val & AUREON_AC97_DATA_MASK;
252 snd_ice1712_gpio_write(ice, tmp);
254 tmp |= AUREON_AC97_DATA_LOW;
255 snd_ice1712_gpio_write(ice, tmp);
257 tmp &= ~AUREON_AC97_DATA_LOW;
258 snd_ice1712_gpio_write(ice, tmp);
261 /* Send high-order byte to XILINX chip */
262 tmp &= ~AUREON_AC97_DATA_MASK;
263 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
265 snd_ice1712_gpio_write(ice, tmp);
267 tmp |= AUREON_AC97_DATA_HIGH;
268 snd_ice1712_gpio_write(ice, tmp);
270 tmp &= ~AUREON_AC97_DATA_HIGH;
271 snd_ice1712_gpio_write(ice, tmp);
274 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
275 tmp |= AUREON_AC97_COMMIT;
276 snd_ice1712_gpio_write(ice, tmp);
278 tmp &= ~AUREON_AC97_COMMIT;
279 snd_ice1712_gpio_write(ice, tmp);
282 /* Store the data in out private buffer */
283 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
286 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
288 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
292 * Initialize STAC9744 chip
294 static int aureon_ac97_init (struct snd_ice1712 *ice)
297 static unsigned short ac97_defaults[] = {
321 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
322 snd_ice1712_gpio_write(ice, tmp);
325 tmp &= ~AUREON_AC97_RESET;
326 snd_ice1712_gpio_write(ice, tmp);
329 tmp |= AUREON_AC97_RESET;
330 snd_ice1712_gpio_write(ice, tmp);
333 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
334 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
335 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
337 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
342 #define AUREON_AC97_STEREO 0x80
345 * AC'97 volume controls
347 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
349 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
350 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
351 uinfo->value.integer.min = 0;
352 uinfo->value.integer.max = 31;
356 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
358 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
361 mutex_lock(&ice->gpio_mutex);
363 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
364 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
365 if (kcontrol->private_value & AUREON_AC97_STEREO)
366 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
368 mutex_unlock(&ice->gpio_mutex);
372 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
374 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
375 unsigned short ovol, nvol;
378 snd_ice1712_save_gpio_status(ice);
380 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
381 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
382 if (kcontrol->private_value & AUREON_AC97_STEREO)
383 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
384 nvol |= ovol & ~0x1F1F;
386 if ((change = (ovol != nvol)))
387 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
389 snd_ice1712_restore_gpio_status(ice);
395 * AC'97 mute controls
397 #define aureon_ac97_mute_info aureon_mono_bool_info
399 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
401 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
403 mutex_lock(&ice->gpio_mutex);
405 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
407 mutex_unlock(&ice->gpio_mutex);
411 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
413 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
414 unsigned short ovol, nvol;
417 snd_ice1712_save_gpio_status(ice);
419 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
420 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
422 if ((change = (ovol != nvol)))
423 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
425 snd_ice1712_restore_gpio_status(ice);
431 * AC'97 mute controls
433 #define aureon_ac97_micboost_info aureon_mono_bool_info
435 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
437 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
439 mutex_lock(&ice->gpio_mutex);
441 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
443 mutex_unlock(&ice->gpio_mutex);
447 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
449 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
450 unsigned short ovol, nvol;
453 snd_ice1712_save_gpio_status(ice);
455 ovol = aureon_ac97_read(ice, AC97_MIC);
456 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
458 if ((change = (ovol != nvol)))
459 aureon_ac97_write(ice, AC97_MIC, nvol);
461 snd_ice1712_restore_gpio_status(ice);
467 * write data in the SPI mode
469 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
473 unsigned int mosi, clk;
475 tmp = snd_ice1712_gpio_read(ice);
477 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) {
478 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
479 mosi = PRODIGY_SPI_MOSI;
480 clk = PRODIGY_SPI_CLK;
483 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
484 AUREON_WM_CS|AUREON_CS8415_CS));
485 mosi = AUREON_SPI_MOSI;
486 clk = AUREON_SPI_CLK;
492 snd_ice1712_gpio_write(ice, tmp);
495 for (i = bits - 1; i >= 0; i--) {
497 snd_ice1712_gpio_write(ice, tmp);
503 snd_ice1712_gpio_write(ice, tmp);
506 snd_ice1712_gpio_write(ice, tmp);
512 snd_ice1712_gpio_write(ice, tmp);
515 snd_ice1712_gpio_write(ice, tmp);
520 * Read data in SPI mode
522 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
526 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
527 snd_ice1712_gpio_write(ice, tmp);
529 snd_ice1712_gpio_write(ice, tmp);
532 for (i=bits-1; i>=0; i--) {
534 tmp |= AUREON_SPI_MOSI;
536 tmp &= ~AUREON_SPI_MOSI;
537 snd_ice1712_gpio_write(ice, tmp);
540 tmp |= AUREON_SPI_CLK;
541 snd_ice1712_gpio_write(ice, tmp);
544 tmp &= ~AUREON_SPI_CLK;
545 snd_ice1712_gpio_write(ice, tmp);
549 for (j=0; j<size; j++) {
550 unsigned char outdata = 0;
551 for (i=7; i>=0; i--) {
552 tmp = snd_ice1712_gpio_read(ice);
554 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
557 tmp |= AUREON_SPI_CLK;
558 snd_ice1712_gpio_write(ice, tmp);
561 tmp &= ~AUREON_SPI_CLK;
562 snd_ice1712_gpio_write(ice, tmp);
569 snd_ice1712_gpio_write(ice, tmp);
572 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
574 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
575 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
579 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
580 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
581 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
584 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
585 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
589 * get the current register value of WM codec
591 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
594 return ((unsigned short)ice->akm[0].images[reg] << 8) |
595 ice->akm[0].images[reg + 1];
599 * set the register value of WM codec
601 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
603 aureon_spi_write(ice,
604 (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS),
605 (reg << 9) | (val & 0x1ff), 16);
609 * set the register value of WM codec and remember it
611 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
613 wm_put_nocache(ice, reg, val);
615 ice->akm[0].images[reg] = val >> 8;
616 ice->akm[0].images[reg + 1] = val;
621 static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
623 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
625 uinfo->value.integer.min = 0;
626 uinfo->value.integer.max = 1;
631 * AC'97 master playback mute controls (Mute on WM8770 chip)
633 #define aureon_ac97_mmute_info aureon_mono_bool_info
635 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
637 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
639 mutex_lock(&ice->gpio_mutex);
641 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
643 mutex_unlock(&ice->gpio_mutex);
647 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
648 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
649 unsigned short ovol, nvol;
652 snd_ice1712_save_gpio_status(ice);
654 ovol = wm_get(ice, WM_OUT_MUX1);
655 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
656 if ((change = (ovol != nvol)))
657 wm_put(ice, WM_OUT_MUX1, nvol);
659 snd_ice1712_restore_gpio_status(ice);
664 static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
665 static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
666 static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
667 static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
668 static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
671 * Logarithmic volume values for WM8770
672 * Computed as 20 * Log10(255 / x)
674 static unsigned char wm_vol[256] = {
675 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
676 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
677 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
678 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
679 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
680 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,
681 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,
682 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,
683 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,
684 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,
685 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,
689 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
690 #define WM_VOL_MUTE 0x8000
692 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
696 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
699 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
701 wm_put(ice, index, nvol);
702 wm_put_nocache(ice, index, 0x180 | nvol);
708 #define wm_pcm_mute_info aureon_mono_bool_info
710 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
712 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
714 mutex_lock(&ice->gpio_mutex);
715 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
716 mutex_unlock(&ice->gpio_mutex);
720 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
722 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
723 unsigned short nval, oval;
726 snd_ice1712_save_gpio_status(ice);
727 oval = wm_get(ice, WM_MUTE);
728 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
729 if ((change = (nval != oval)))
730 wm_put(ice, WM_MUTE, nval);
731 snd_ice1712_restore_gpio_status(ice);
737 * Master volume attenuation mixer control
739 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
741 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
743 uinfo->value.integer.min = 0;
744 uinfo->value.integer.max = WM_VOL_MAX;
748 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
750 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
753 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
757 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
759 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
762 snd_ice1712_save_gpio_status(ice);
763 for (ch = 0; ch < 2; ch++) {
764 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
766 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
767 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
768 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
769 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
770 ice->spec.aureon.vol[dac + ch],
771 ice->spec.aureon.master[ch]);
775 snd_ice1712_restore_gpio_status(ice);
780 * DAC volume attenuation mixer control
782 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
784 int voices = kcontrol->private_value >> 8;
785 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
786 uinfo->count = voices;
787 uinfo->value.integer.min = 0; /* mute (-101dB) */
788 uinfo->value.integer.max = 0x7F; /* 0dB */
792 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
794 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
797 voices = kcontrol->private_value >> 8;
798 ofs = kcontrol->private_value & 0xff;
799 for (i = 0; i < voices; i++)
800 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
804 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
806 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
807 int i, idx, ofs, voices;
810 voices = kcontrol->private_value >> 8;
811 ofs = kcontrol->private_value & 0xff;
812 snd_ice1712_save_gpio_status(ice);
813 for (i = 0; i < voices; i++) {
814 idx = WM_DAC_ATTEN + ofs + i;
815 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
816 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
817 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
818 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
819 ice->spec.aureon.master[i]);
823 snd_ice1712_restore_gpio_status(ice);
828 * WM8770 mute control
830 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
831 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
832 uinfo->count = kcontrol->private_value >> 8;
833 uinfo->value.integer.min = 0;
834 uinfo->value.integer.max = 1;
838 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
840 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
843 voices = kcontrol->private_value >> 8;
844 ofs = kcontrol->private_value & 0xFF;
846 for (i = 0; i < voices; i++)
847 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
851 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
853 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
854 int change = 0, voices, ofs, i;
856 voices = kcontrol->private_value >> 8;
857 ofs = kcontrol->private_value & 0xFF;
859 snd_ice1712_save_gpio_status(ice);
860 for (i = 0; i < voices; i++) {
861 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
862 if (ucontrol->value.integer.value[i] != val) {
863 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
864 ice->spec.aureon.vol[ofs + i] |=
865 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
866 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
867 ice->spec.aureon.master[i]);
871 snd_ice1712_restore_gpio_status(ice);
877 * WM8770 master mute control
879 static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
880 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
882 uinfo->value.integer.min = 0;
883 uinfo->value.integer.max = 1;
887 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
889 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
891 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
892 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
896 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
898 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
901 snd_ice1712_save_gpio_status(ice);
902 for (i = 0; i < 2; i++) {
903 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
904 if (ucontrol->value.integer.value[i] != val) {
906 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
907 ice->spec.aureon.master[i] |=
908 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
909 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
910 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
911 ice->spec.aureon.vol[dac + i],
912 ice->spec.aureon.master[i]);
916 snd_ice1712_restore_gpio_status(ice);
921 /* digital master volume */
923 #define PCM_RES 128 /* -64dB */
924 #define PCM_MIN (PCM_0dB - PCM_RES)
925 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
927 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
929 uinfo->value.integer.min = 0; /* mute (-64dB) */
930 uinfo->value.integer.max = PCM_RES; /* 0dB */
934 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
936 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
939 mutex_lock(&ice->gpio_mutex);
940 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
941 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
942 ucontrol->value.integer.value[0] = val;
943 mutex_unlock(&ice->gpio_mutex);
947 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
949 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
950 unsigned short ovol, nvol;
953 snd_ice1712_save_gpio_status(ice);
954 nvol = ucontrol->value.integer.value[0];
955 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
956 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
958 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
959 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
962 snd_ice1712_restore_gpio_status(ice);
969 static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
971 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
973 uinfo->value.integer.min = 0;
974 uinfo->value.integer.max = 1;
978 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
980 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
984 mutex_lock(&ice->gpio_mutex);
985 for (i = 0; i < 2; i++) {
986 val = wm_get(ice, WM_ADC_GAIN + i);
987 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
989 mutex_unlock(&ice->gpio_mutex);
993 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
995 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
996 unsigned short new, old;
999 snd_ice1712_save_gpio_status(ice);
1000 for (i = 0; i < 2; i++) {
1001 old = wm_get(ice, WM_ADC_GAIN + i);
1002 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1004 wm_put(ice, WM_ADC_GAIN + i, new);
1008 snd_ice1712_restore_gpio_status(ice);
1014 * ADC gain mixer control
1016 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1018 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1020 uinfo->value.integer.min = 0; /* -12dB */
1021 uinfo->value.integer.max = 0x1f; /* 19dB */
1025 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1027 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031 mutex_lock(&ice->gpio_mutex);
1032 for (i = 0; i < 2; i++) {
1033 idx = WM_ADC_GAIN + i;
1034 vol = wm_get(ice, idx) & 0x1f;
1035 ucontrol->value.integer.value[i] = vol;
1037 mutex_unlock(&ice->gpio_mutex);
1041 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1043 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1045 unsigned short ovol, nvol;
1048 snd_ice1712_save_gpio_status(ice);
1049 for (i = 0; i < 2; i++) {
1050 idx = WM_ADC_GAIN + i;
1051 nvol = ucontrol->value.integer.value[i];
1052 ovol = wm_get(ice, idx);
1053 if ((ovol & 0x1f) != nvol) {
1054 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058 snd_ice1712_restore_gpio_status(ice);
1063 * ADC input mux mixer control
1065 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1067 static char *texts[] = {
1074 static char *universe_texts[] = {
1084 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1086 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1088 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1089 uinfo->value.enumerated.items = 8;
1090 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1091 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1092 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1095 uinfo->value.enumerated.items = 5;
1096 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1097 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1098 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1103 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1105 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1108 mutex_lock(&ice->gpio_mutex);
1109 val = wm_get(ice, WM_ADC_MUX);
1110 ucontrol->value.enumerated.item[0] = val & 7;
1111 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1112 mutex_unlock(&ice->gpio_mutex);
1116 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1118 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1119 unsigned short oval, nval;
1122 snd_ice1712_save_gpio_status(ice);
1123 oval = wm_get(ice, WM_ADC_MUX);
1124 nval = oval & ~0x77;
1125 nval |= ucontrol->value.enumerated.item[0] & 7;
1126 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1127 change = (oval != nval);
1129 wm_put(ice, WM_ADC_MUX, nval);
1130 snd_ice1712_restore_gpio_status(ice);
1137 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1139 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1140 static char *aureon_texts[] = {
1144 static char *prodigy_texts[] = {
1148 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1150 uinfo->value.enumerated.items = 2;
1151 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1152 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1153 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1154 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1156 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1160 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1162 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1164 //snd_ice1712_save_gpio_status(ice);
1165 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1166 ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1167 //snd_ice1712_restore_gpio_status(ice);
1171 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1173 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1174 unsigned short oval, nval;
1177 snd_ice1712_save_gpio_status(ice);
1178 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1179 nval = oval & ~0x07;
1180 nval |= ucontrol->value.enumerated.item[0] & 7;
1181 change = (oval != nval);
1183 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1184 snd_ice1712_restore_gpio_status(ice);
1185 ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1189 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1191 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1193 uinfo->value.integer.min = 0;
1194 uinfo->value.integer.max = 192000;
1198 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1200 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1201 unsigned char ratio;
1202 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1203 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1210 static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1212 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1217 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1219 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1220 snd_ice1712_save_gpio_status(ice);
1221 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1222 snd_ice1712_restore_gpio_status(ice);
1226 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1228 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1229 unsigned char oval, nval;
1231 snd_ice1712_save_gpio_status(ice);
1232 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1233 if (ucontrol->value.integer.value[0])
1234 nval = oval & ~0x20;
1237 if ((change = (oval != nval)))
1238 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1239 snd_ice1712_restore_gpio_status(ice);
1244 * CS8415A Q-Sub info
1246 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1247 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1252 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1253 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1255 snd_ice1712_save_gpio_status(ice);
1256 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1257 snd_ice1712_restore_gpio_status(ice);
1262 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1263 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1268 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1269 memset(ucontrol->value.iec958.status, 0xFF, 24);
1273 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1274 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1276 snd_ice1712_save_gpio_status(ice);
1277 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1278 snd_ice1712_restore_gpio_status(ice);
1283 * Headphone Amplifier
1285 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1287 unsigned int tmp, tmp2;
1289 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1291 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1292 tmp |= AUREON_HP_SEL;
1294 tmp |= PRODIGY_HP_SEL;
1296 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
1297 tmp &= ~ AUREON_HP_SEL;
1299 tmp &= ~ PRODIGY_HP_SEL;
1301 snd_ice1712_gpio_write(ice, tmp);
1307 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1309 unsigned int tmp = snd_ice1712_gpio_read(ice);
1311 return ( tmp & AUREON_HP_SEL )!= 0;
1314 #define aureon_hpamp_info aureon_mono_bool_info
1316 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1318 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1320 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1325 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1327 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1329 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1336 #define aureon_deemp_info aureon_mono_bool_info
1338 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1340 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1341 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1345 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1347 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1349 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1350 if (ucontrol->value.integer.value[0])
1354 if (temp != temp2) {
1355 wm_put(ice, WM_DAC_CTRL2, temp);
1364 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1366 static char *texts[2] = { "128x", "64x" };
1368 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1370 uinfo->value.enumerated.items = 2;
1372 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1373 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1374 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1379 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1381 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1382 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1386 static int aureon_oversampling_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_MASTER);
1393 if (ucontrol->value.enumerated.item[0])
1398 if (temp != temp2) {
1399 wm_put(ice, WM_MASTER, temp);
1409 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412 .name = "Master Playback Switch",
1413 .info = wm_master_mute_info,
1414 .get = wm_master_mute_get,
1415 .put = wm_master_mute_put
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1420 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1421 .name = "Master Playback Volume",
1422 .info = wm_master_vol_info,
1423 .get = wm_master_vol_get,
1424 .put = wm_master_vol_put,
1425 .tlv = { .p = db_scale_wm_dac }
1428 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1429 .name = "Front Playback Switch",
1430 .info = wm_mute_info,
1433 .private_value = (2 << 8) | 0
1436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1437 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1438 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1439 .name = "Front Playback Volume",
1440 .info = wm_vol_info,
1443 .private_value = (2 << 8) | 0,
1444 .tlv = { .p = db_scale_wm_dac }
1447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1448 .name = "Rear Playback Switch",
1449 .info = wm_mute_info,
1452 .private_value = (2 << 8) | 2
1455 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1456 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1457 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1458 .name = "Rear Playback Volume",
1459 .info = wm_vol_info,
1462 .private_value = (2 << 8) | 2,
1463 .tlv = { .p = db_scale_wm_dac }
1466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467 .name = "Center Playback Switch",
1468 .info = wm_mute_info,
1471 .private_value = (1 << 8) | 4
1474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1476 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1477 .name = "Center Playback Volume",
1478 .info = wm_vol_info,
1481 .private_value = (1 << 8) | 4,
1482 .tlv = { .p = db_scale_wm_dac }
1485 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1486 .name = "LFE Playback Switch",
1487 .info = wm_mute_info,
1490 .private_value = (1 << 8) | 5
1493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1494 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1495 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1496 .name = "LFE Playback Volume",
1497 .info = wm_vol_info,
1500 .private_value = (1 << 8) | 5,
1501 .tlv = { .p = db_scale_wm_dac }
1504 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1505 .name = "Side Playback Switch",
1506 .info = wm_mute_info,
1509 .private_value = (2 << 8) | 6
1512 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1513 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1514 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1515 .name = "Side Playback Volume",
1516 .info = wm_vol_info,
1519 .private_value = (2 << 8) | 6,
1520 .tlv = { .p = db_scale_wm_dac }
1524 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527 .name = "PCM Playback Switch",
1528 .info = wm_pcm_mute_info,
1529 .get = wm_pcm_mute_get,
1530 .put = wm_pcm_mute_put
1533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1536 .name = "PCM Playback Volume",
1537 .info = wm_pcm_vol_info,
1538 .get = wm_pcm_vol_get,
1539 .put = wm_pcm_vol_put,
1540 .tlv = { .p = db_scale_wm_pcm }
1543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544 .name = "Capture Switch",
1545 .info = wm_adc_mute_info,
1546 .get = wm_adc_mute_get,
1547 .put = wm_adc_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 = "Capture Volume",
1554 .info = wm_adc_vol_info,
1555 .get = wm_adc_vol_get,
1556 .put = wm_adc_vol_put,
1557 .tlv = { .p = db_scale_wm_adc }
1560 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1561 .name = "Capture Source",
1562 .info = wm_adc_mux_info,
1563 .get = wm_adc_mux_get,
1564 .put = wm_adc_mux_put,
1568 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1569 .name = "External Amplifier",
1570 .info = aureon_hpamp_info,
1571 .get = aureon_hpamp_get,
1572 .put = aureon_hpamp_put
1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576 .name = "DAC Deemphasis Switch",
1577 .info = aureon_deemp_info,
1578 .get = aureon_deemp_get,
1579 .put = aureon_deemp_put
1582 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1583 .name = "ADC Oversampling",
1584 .info = aureon_oversampling_info,
1585 .get = aureon_oversampling_get,
1586 .put = aureon_oversampling_put
1590 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593 .name = "AC97 Playback Switch",
1594 .info = aureon_ac97_mmute_info,
1595 .get = aureon_ac97_mmute_get,
1596 .put = aureon_ac97_mmute_put,
1597 .private_value = AC97_MASTER
1600 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1601 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1602 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1603 .name = "AC97 Playback Volume",
1604 .info = aureon_ac97_vol_info,
1605 .get = aureon_ac97_vol_get,
1606 .put = aureon_ac97_vol_put,
1607 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1608 .tlv = { .p = db_scale_ac97_master }
1611 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1612 .name = "CD Playback Switch",
1613 .info = aureon_ac97_mute_info,
1614 .get = aureon_ac97_mute_get,
1615 .put = aureon_ac97_mute_put,
1616 .private_value = AC97_CD
1619 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1620 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1621 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1622 .name = "CD Playback Volume",
1623 .info = aureon_ac97_vol_info,
1624 .get = aureon_ac97_vol_get,
1625 .put = aureon_ac97_vol_put,
1626 .private_value = AC97_CD|AUREON_AC97_STEREO,
1627 .tlv = { .p = db_scale_ac97_gain }
1630 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1631 .name = "Aux Playback Switch",
1632 .info = aureon_ac97_mute_info,
1633 .get = aureon_ac97_mute_get,
1634 .put = aureon_ac97_mute_put,
1635 .private_value = AC97_AUX,
1638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1639 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1640 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1641 .name = "Aux Playback Volume",
1642 .info = aureon_ac97_vol_info,
1643 .get = aureon_ac97_vol_get,
1644 .put = aureon_ac97_vol_put,
1645 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1646 .tlv = { .p = db_scale_ac97_gain }
1649 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1650 .name = "Line Playback Switch",
1651 .info = aureon_ac97_mute_info,
1652 .get = aureon_ac97_mute_get,
1653 .put = aureon_ac97_mute_put,
1654 .private_value = AC97_LINE
1657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1658 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1659 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1660 .name = "Line Playback Volume",
1661 .info = aureon_ac97_vol_info,
1662 .get = aureon_ac97_vol_get,
1663 .put = aureon_ac97_vol_put,
1664 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1665 .tlv = { .p = db_scale_ac97_gain }
1668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1669 .name = "Mic Playback Switch",
1670 .info = aureon_ac97_mute_info,
1671 .get = aureon_ac97_mute_get,
1672 .put = aureon_ac97_mute_put,
1673 .private_value = AC97_MIC
1676 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1677 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1678 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1679 .name = "Mic Playback Volume",
1680 .info = aureon_ac97_vol_info,
1681 .get = aureon_ac97_vol_get,
1682 .put = aureon_ac97_vol_put,
1683 .private_value = AC97_MIC,
1684 .tlv = { .p = db_scale_ac97_gain }
1687 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1688 .name = "Mic Boost (+20dB)",
1689 .info = aureon_ac97_micboost_info,
1690 .get = aureon_ac97_micboost_get,
1691 .put = aureon_ac97_micboost_put
1695 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1697 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1698 .name = "AC97 Playback Switch",
1699 .info = aureon_ac97_mmute_info,
1700 .get = aureon_ac97_mmute_get,
1701 .put = aureon_ac97_mmute_put,
1702 .private_value = AC97_MASTER
1705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1706 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1707 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1708 .name = "AC97 Playback Volume",
1709 .info = aureon_ac97_vol_info,
1710 .get = aureon_ac97_vol_get,
1711 .put = aureon_ac97_vol_put,
1712 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1713 .tlv = { .p = db_scale_ac97_master }
1716 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1717 .name = "CD Playback Switch",
1718 .info = aureon_ac97_mute_info,
1719 .get = aureon_ac97_mute_get,
1720 .put = aureon_ac97_mute_put,
1721 .private_value = AC97_AUX
1724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1725 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1726 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1727 .name = "CD Playback Volume",
1728 .info = aureon_ac97_vol_info,
1729 .get = aureon_ac97_vol_get,
1730 .put = aureon_ac97_vol_put,
1731 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1732 .tlv = { .p = db_scale_ac97_gain }
1735 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1736 .name = "Phono Playback Switch",
1737 .info = aureon_ac97_mute_info,
1738 .get = aureon_ac97_mute_get,
1739 .put = aureon_ac97_mute_put,
1740 .private_value = AC97_CD
1743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1744 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1745 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1746 .name = "Phono Playback Volume",
1747 .info = aureon_ac97_vol_info,
1748 .get = aureon_ac97_vol_get,
1749 .put = aureon_ac97_vol_put,
1750 .private_value = AC97_CD|AUREON_AC97_STEREO,
1751 .tlv = { .p = db_scale_ac97_gain }
1754 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1755 .name = "Line Playback Switch",
1756 .info = aureon_ac97_mute_info,
1757 .get = aureon_ac97_mute_get,
1758 .put = aureon_ac97_mute_put,
1759 .private_value = AC97_LINE
1762 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1763 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1764 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1765 .name = "Line Playback Volume",
1766 .info = aureon_ac97_vol_info,
1767 .get = aureon_ac97_vol_get,
1768 .put = aureon_ac97_vol_put,
1769 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1770 .tlv = { .p = db_scale_ac97_gain }
1773 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1774 .name = "Mic Playback Switch",
1775 .info = aureon_ac97_mute_info,
1776 .get = aureon_ac97_mute_get,
1777 .put = aureon_ac97_mute_put,
1778 .private_value = AC97_MIC
1781 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1782 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1783 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1784 .name = "Mic Playback Volume",
1785 .info = aureon_ac97_vol_info,
1786 .get = aureon_ac97_vol_get,
1787 .put = aureon_ac97_vol_put,
1788 .private_value = AC97_MIC,
1789 .tlv = { .p = db_scale_ac97_gain }
1792 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1793 .name = "Mic Boost (+20dB)",
1794 .info = aureon_ac97_micboost_info,
1795 .get = aureon_ac97_micboost_get,
1796 .put = aureon_ac97_micboost_put
1799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1800 .name = "Aux Playback Switch",
1801 .info = aureon_ac97_mute_info,
1802 .get = aureon_ac97_mute_get,
1803 .put = aureon_ac97_mute_put,
1804 .private_value = AC97_VIDEO,
1807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1808 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1809 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1810 .name = "Aux Playback Volume",
1811 .info = aureon_ac97_vol_info,
1812 .get = aureon_ac97_vol_get,
1813 .put = aureon_ac97_vol_put,
1814 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1815 .tlv = { .p = db_scale_ac97_gain }
1818 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1819 .name = "Aux Source",
1820 .info = aureon_universe_inmux_info,
1821 .get = aureon_universe_inmux_get,
1822 .put = aureon_universe_inmux_put
1828 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1830 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1831 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1832 .info = aureon_cs8415_mute_info,
1833 .get = aureon_cs8415_mute_get,
1834 .put = aureon_cs8415_mute_put
1837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1838 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1839 .info = aureon_cs8415_mux_info,
1840 .get = aureon_cs8415_mux_get,
1841 .put = aureon_cs8415_mux_put,
1844 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1845 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1846 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1847 .info = aureon_cs8415_qsub_info,
1848 .get = aureon_cs8415_qsub_get,
1851 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1852 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1853 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1854 .info = aureon_cs8415_spdif_info,
1855 .get = aureon_cs8415_mask_get
1858 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1859 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1860 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1861 .info = aureon_cs8415_spdif_info,
1862 .get = aureon_cs8415_spdif_get
1865 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1866 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1867 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1868 .info = aureon_cs8415_rate_info,
1869 .get = aureon_cs8415_rate_get
1874 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1876 unsigned int i, counts;
1879 counts = ARRAY_SIZE(aureon_dac_controls);
1880 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1881 counts -= 2; /* no side */
1882 for (i = 0; i < counts; i++) {
1883 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1888 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1889 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1894 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1895 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1896 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1901 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1902 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1903 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1909 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1911 snd_ice1712_save_gpio_status(ice);
1912 id = aureon_cs8415_get(ice, CS8415_ID);
1914 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1915 else if ((id & 0x0F) != 0x01)
1916 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1918 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1919 struct snd_kcontrol *kctl;
1920 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1924 kctl->id.device = ice->pcm->device;
1927 snd_ice1712_restore_gpio_status(ice);
1935 * initialize the chip
1937 static int __devinit aureon_init(struct snd_ice1712 *ice)
1939 static unsigned short wm_inits_aureon[] = {
1940 /* These come first to reduce init pop noise */
1941 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1942 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1943 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1945 0x18, 0x000, /* All power-up */
1947 0x16, 0x122, /* I2S, normal polarity, 24bit */
1948 0x17, 0x022, /* 256fs, slave mode */
1949 0x00, 0, /* DAC1 analog mute */
1950 0x01, 0, /* DAC2 analog mute */
1951 0x02, 0, /* DAC3 analog mute */
1952 0x03, 0, /* DAC4 analog mute */
1953 0x04, 0, /* DAC5 analog mute */
1954 0x05, 0, /* DAC6 analog mute */
1955 0x06, 0, /* DAC7 analog mute */
1956 0x07, 0, /* DAC8 analog mute */
1957 0x08, 0x100, /* master analog mute */
1958 0x09, 0xff, /* DAC1 digital full */
1959 0x0a, 0xff, /* DAC2 digital full */
1960 0x0b, 0xff, /* DAC3 digital full */
1961 0x0c, 0xff, /* DAC4 digital full */
1962 0x0d, 0xff, /* DAC5 digital full */
1963 0x0e, 0xff, /* DAC6 digital full */
1964 0x0f, 0xff, /* DAC7 digital full */
1965 0x10, 0xff, /* DAC8 digital full */
1966 0x11, 0x1ff, /* master digital full */
1967 0x12, 0x000, /* phase normal */
1968 0x13, 0x090, /* unmute DAC L/R */
1969 0x14, 0x000, /* all unmute */
1970 0x15, 0x000, /* no deemphasis, no ZFLG */
1971 0x19, 0x000, /* -12dB ADC/L */
1972 0x1a, 0x000, /* -12dB ADC/R */
1975 static unsigned short wm_inits_prodigy[] = {
1977 /* These come first to reduce init pop noise */
1978 0x1b, 0x000, /* ADC Mux */
1979 0x1c, 0x009, /* Out Mux1 */
1980 0x1d, 0x009, /* Out Mux2 */
1982 0x18, 0x000, /* All power-up */
1984 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1985 0x17, 0x006, /* 128fs, slave mode */
1987 0x00, 0, /* DAC1 analog mute */
1988 0x01, 0, /* DAC2 analog mute */
1989 0x02, 0, /* DAC3 analog mute */
1990 0x03, 0, /* DAC4 analog mute */
1991 0x04, 0, /* DAC5 analog mute */
1992 0x05, 0, /* DAC6 analog mute */
1993 0x06, 0, /* DAC7 analog mute */
1994 0x07, 0, /* DAC8 analog mute */
1995 0x08, 0x100, /* master analog mute */
1997 0x09, 0x7f, /* DAC1 digital full */
1998 0x0a, 0x7f, /* DAC2 digital full */
1999 0x0b, 0x7f, /* DAC3 digital full */
2000 0x0c, 0x7f, /* DAC4 digital full */
2001 0x0d, 0x7f, /* DAC5 digital full */
2002 0x0e, 0x7f, /* DAC6 digital full */
2003 0x0f, 0x7f, /* DAC7 digital full */
2004 0x10, 0x7f, /* DAC8 digital full */
2005 0x11, 0x1FF, /* master digital full */
2007 0x12, 0x000, /* phase normal */
2008 0x13, 0x090, /* unmute DAC L/R */
2009 0x14, 0x000, /* all unmute */
2010 0x15, 0x000, /* no deemphasis, no ZFLG */
2012 0x19, 0x000, /* -12dB ADC/L */
2013 0x1a, 0x000, /* -12dB ADC/R */
2017 static unsigned short cs_inits[] = {
2019 0x0180, /* no mute, OMCK output on RMCK pin */
2020 0x0201, /* S/PDIF source on RXP1 */
2021 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2028 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2029 ice->num_total_dacs = 6;
2030 ice->num_total_adcs = 2;
2032 /* aureon 7.1 and prodigy 7.1 */
2033 ice->num_total_dacs = 8;
2034 ice->num_total_adcs = 2;
2037 /* to remeber the register values of CS8415 */
2038 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2041 ice->akm_codecs = 1;
2043 if ((err = aureon_ac97_init(ice)) != 0)
2046 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2048 /* reset the wm codec as the SPI mode */
2049 snd_ice1712_save_gpio_status(ice);
2050 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2052 tmp = snd_ice1712_gpio_read(ice);
2053 tmp &= ~AUREON_WM_RESET;
2054 snd_ice1712_gpio_write(ice, tmp);
2056 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2057 snd_ice1712_gpio_write(ice, tmp);
2059 tmp |= AUREON_WM_RESET;
2060 snd_ice1712_gpio_write(ice, tmp);
2063 /* initialize WM8770 codec */
2064 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2065 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT)
2066 p = wm_inits_prodigy;
2068 p = wm_inits_aureon;
2069 for (; *p != (unsigned short)-1; p += 2)
2070 wm_put(ice, p[0], p[1]);
2072 /* initialize CS8415A codec */
2073 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
2074 for (p = cs_inits; *p != (unsigned short)-1; p++)
2075 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2076 ice->spec.aureon.cs8415_mux = 1;
2078 aureon_set_headphone_amp(ice, 1);
2081 snd_ice1712_restore_gpio_status(ice);
2083 /* initialize PCA9554 pin directions & set default input*/
2084 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2085 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2087 ice->spec.aureon.master[0] = WM_VOL_MUTE;
2088 ice->spec.aureon.master[1] = WM_VOL_MUTE;
2089 for (i = 0; i < ice->num_total_dacs; i++) {
2090 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2091 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2099 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2100 * hence the driver needs to sets up it properly.
2103 static unsigned char aureon51_eeprom[] __devinitdata = {
2104 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
2105 0x80, /* ACLINK: I2S */
2106 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2107 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2108 0xff, /* GPIO_DIR */
2109 0xff, /* GPIO_DIR1 */
2110 0x5f, /* GPIO_DIR2 */
2111 0x00, /* GPIO_MASK */
2112 0x00, /* GPIO_MASK1 */
2113 0x00, /* GPIO_MASK2 */
2114 0x00, /* GPIO_STATE */
2115 0x00, /* GPIO_STATE1 */
2116 0x00, /* GPIO_STATE2 */
2119 static unsigned char aureon71_eeprom[] __devinitdata = {
2120 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
2121 0x80, /* ACLINK: I2S */
2122 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2123 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2124 0xff, /* GPIO_DIR */
2125 0xff, /* GPIO_DIR1 */
2126 0x5f, /* GPIO_DIR2 */
2127 0x00, /* GPIO_MASK */
2128 0x00, /* GPIO_MASK1 */
2129 0x00, /* GPIO_MASK2 */
2130 0x00, /* GPIO_STATE */
2131 0x00, /* GPIO_STATE1 */
2132 0x00, /* GPIO_STATE2 */
2135 static unsigned char prodigy71_eeprom[] __devinitdata = {
2136 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
2137 0x80, /* ACLINK: I2S */
2138 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2139 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2140 0xff, /* GPIO_DIR */
2141 0xff, /* GPIO_DIR1 */
2142 0x5f, /* GPIO_DIR2 */
2143 0x00, /* GPIO_MASK */
2144 0x00, /* GPIO_MASK1 */
2145 0x00, /* GPIO_MASK2 */
2146 0x00, /* GPIO_STATE */
2147 0x00, /* GPIO_STATE1 */
2148 0x00, /* GPIO_STATE2 */
2151 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2152 0x4b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
2153 0x80, /* ACLINK: I2S */
2154 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2155 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2156 0xff, /* GPIO_DIR */
2157 0xff, /* GPIO_DIR1 */
2158 0x5f, /* GPIO_DIR2 */
2159 0x00, /* GPIO_MASK */
2160 0x00, /* GPIO_MASK1 */
2161 0x00, /* GPIO_MASK2 */
2162 0x00, /* GPIO_STATE */
2163 0x00, /* GPIO_STATE1 */
2164 0x00, /* GPIO_STATE2 */
2169 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2171 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2172 .name = "Terratec Aureon 5.1-Sky",
2173 .model = "aureon51",
2174 .chip_init = aureon_init,
2175 .build_controls = aureon_add_controls,
2176 .eeprom_size = sizeof(aureon51_eeprom),
2177 .eeprom_data = aureon51_eeprom,
2178 .driver = "Aureon51",
2181 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2182 .name = "Terratec Aureon 7.1-Space",
2183 .model = "aureon71",
2184 .chip_init = aureon_init,
2185 .build_controls = aureon_add_controls,
2186 .eeprom_size = sizeof(aureon71_eeprom),
2187 .eeprom_data = aureon71_eeprom,
2188 .driver = "Aureon71",
2191 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2192 .name = "Terratec Aureon 7.1-Universe",
2193 .model = "universe",
2194 .chip_init = aureon_init,
2195 .build_controls = aureon_add_controls,
2196 .eeprom_size = sizeof(aureon71_eeprom),
2197 .eeprom_data = aureon71_eeprom,
2198 .driver = "Aureon71Univ", /* keep in 15 letters */
2201 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2202 .name = "Audiotrak Prodigy 7.1",
2203 .model = "prodigy71",
2204 .chip_init = aureon_init,
2205 .build_controls = aureon_add_controls,
2206 .eeprom_size = sizeof(prodigy71_eeprom),
2207 .eeprom_data = prodigy71_eeprom,
2208 .driver = "Prodigy71", /* should be identical with Aureon71 */
2211 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2212 .name = "Audiotrak Prodigy 7.1 LT",
2213 .model = "prodigy71lt",
2214 .chip_init = aureon_init,
2215 .build_controls = aureon_add_controls,
2216 .eeprom_size = sizeof(prodigy71lt_eeprom),
2217 .eeprom_data = prodigy71lt_eeprom,
2218 .driver = "Prodigy71LT",
2220 { } /* terminator */