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 /* WM8770 registers */
65 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
66 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
67 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
68 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
69 #define WM_PHASE_SWAP 0x12 /* DAC phase */
70 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
71 #define WM_MUTE 0x14 /* mute controls */
72 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
73 #define WM_INT_CTRL 0x16 /* interface control */
74 #define WM_MASTER 0x17 /* master clock and mode */
75 #define WM_POWERDOWN 0x18 /* power-down controls */
76 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
77 #define WM_ADC_MUX 0x1b /* input MUX */
78 #define WM_OUT_MUX1 0x1c /* output MUX */
79 #define WM_OUT_MUX2 0x1e /* output MUX */
80 #define WM_RESET 0x1f /* software reset */
82 /* CS8415A registers */
83 #define CS8415_CTRL1 0x01
84 #define CS8415_CTRL2 0x02
85 #define CS8415_QSUB 0x14
86 #define CS8415_RATIO 0x1E
87 #define CS8415_C_BUFFER 0x20
88 #define CS8415_ID 0x7F
90 /* PCA9554 registers */
91 #define PCA9554_DEV 0x40 /* I2C device address */
92 #define PCA9554_IN 0x00 /* input port */
93 #define PCA9554_OUT 0x01 /* output port */
94 #define PCA9554_INVERT 0x02 /* input invert */
95 #define PCA9554_DIR 0x03 /* port directions */
98 * Aureon Universe additional controls using PCA9554
102 * Send data to pca9554
104 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
109 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
110 unsigned char val = 0;
112 tmp = snd_ice1712_gpio_read(ice);
114 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
115 AUREON_WM_RW|AUREON_WM_CS|
118 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
120 tmp &= ~AUREON_SPI_MOSI;
121 tmp &= ~AUREON_SPI_CLK;
122 snd_ice1712_gpio_write(ice, tmp);
126 * send i2c stop condition and start condition
127 * to obtain sane state
129 tmp |= AUREON_SPI_CLK;
130 snd_ice1712_gpio_write(ice, tmp);
132 tmp |= AUREON_SPI_MOSI;
133 snd_ice1712_gpio_write(ice, tmp);
135 tmp &= ~AUREON_SPI_MOSI;
136 snd_ice1712_gpio_write(ice, tmp);
138 tmp &= ~AUREON_SPI_CLK;
139 snd_ice1712_gpio_write(ice, tmp);
142 * send device address, command and value,
143 * skipping ack cycles inbetween
145 for (j = 0; j < 3; j++) {
147 case 0: val = dev; break;
148 case 1: val = reg; break;
149 case 2: val = data; break;
151 for (i = 7; i >= 0; i--) {
152 tmp &= ~AUREON_SPI_CLK;
153 snd_ice1712_gpio_write(ice, tmp);
156 tmp |= AUREON_SPI_MOSI;
158 tmp &= ~AUREON_SPI_MOSI;
159 snd_ice1712_gpio_write(ice, tmp);
161 tmp |= AUREON_SPI_CLK;
162 snd_ice1712_gpio_write(ice, tmp);
165 tmp &= ~AUREON_SPI_CLK;
166 snd_ice1712_gpio_write(ice, tmp);
168 tmp |= AUREON_SPI_CLK;
169 snd_ice1712_gpio_write(ice, tmp);
171 tmp &= ~AUREON_SPI_CLK;
172 snd_ice1712_gpio_write(ice, tmp);
175 tmp &= ~AUREON_SPI_CLK;
176 snd_ice1712_gpio_write(ice, tmp);
178 tmp &= ~AUREON_SPI_MOSI;
179 snd_ice1712_gpio_write(ice, tmp);
181 tmp |= AUREON_SPI_CLK;
182 snd_ice1712_gpio_write(ice, tmp);
184 tmp |= AUREON_SPI_MOSI;
185 snd_ice1712_gpio_write(ice, tmp);
189 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
190 struct snd_ctl_elem_info *uinfo)
192 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
194 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
196 uinfo->value.enumerated.items = 3;
197 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
198 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
199 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
203 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_value *ucontrol)
206 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
207 ucontrol->value.enumerated.item[0] = ice->spec.aureon.pca9554_out;
211 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
212 struct snd_ctl_elem_value *ucontrol)
214 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
215 unsigned char oval, nval;
218 nval = ucontrol->value.enumerated.item[0];
221 snd_ice1712_save_gpio_status(ice);
222 oval = ice->spec.aureon.pca9554_out;
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 const 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 snd_ctl_boolean_mono_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 snd_ctl_boolean_mono_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 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
479 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
480 mosi = PRODIGY_SPI_MOSI;
481 clk = PRODIGY_SPI_CLK;
484 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
485 AUREON_WM_CS|AUREON_CS8415_CS));
486 mosi = AUREON_SPI_MOSI;
487 clk = AUREON_SPI_CLK;
493 snd_ice1712_gpio_write(ice, tmp);
496 for (i = bits - 1; i >= 0; i--) {
498 snd_ice1712_gpio_write(ice, tmp);
504 snd_ice1712_gpio_write(ice, tmp);
507 snd_ice1712_gpio_write(ice, tmp);
513 snd_ice1712_gpio_write(ice, tmp);
516 snd_ice1712_gpio_write(ice, tmp);
521 * Read data in SPI mode
523 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
527 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
528 snd_ice1712_gpio_write(ice, tmp);
530 snd_ice1712_gpio_write(ice, tmp);
533 for (i=bits-1; i>=0; i--) {
535 tmp |= AUREON_SPI_MOSI;
537 tmp &= ~AUREON_SPI_MOSI;
538 snd_ice1712_gpio_write(ice, tmp);
541 tmp |= AUREON_SPI_CLK;
542 snd_ice1712_gpio_write(ice, tmp);
545 tmp &= ~AUREON_SPI_CLK;
546 snd_ice1712_gpio_write(ice, tmp);
550 for (j=0; j<size; j++) {
551 unsigned char outdata = 0;
552 for (i=7; i>=0; i--) {
553 tmp = snd_ice1712_gpio_read(ice);
555 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
558 tmp |= AUREON_SPI_CLK;
559 snd_ice1712_gpio_write(ice, tmp);
562 tmp &= ~AUREON_SPI_CLK;
563 snd_ice1712_gpio_write(ice, tmp);
570 snd_ice1712_gpio_write(ice, tmp);
573 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
575 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
576 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
580 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
581 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
582 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
585 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
586 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
590 * get the current register value of WM codec
592 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
595 return ((unsigned short)ice->akm[0].images[reg] << 8) |
596 ice->akm[0].images[reg + 1];
600 * set the register value of WM codec
602 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
604 aureon_spi_write(ice,
605 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
606 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
607 PRODIGY_WM_CS : AUREON_WM_CS),
608 (reg << 9) | (val & 0x1ff), 16);
612 * set the register value of WM codec and remember it
614 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
616 wm_put_nocache(ice, reg, val);
618 ice->akm[0].images[reg] = val >> 8;
619 ice->akm[0].images[reg + 1] = val;
624 #define aureon_mono_bool_info snd_ctl_boolean_mono_info
627 * AC'97 master playback mute controls (Mute on WM8770 chip)
629 #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
631 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
633 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
635 mutex_lock(&ice->gpio_mutex);
637 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
639 mutex_unlock(&ice->gpio_mutex);
643 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
644 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
645 unsigned short ovol, nvol;
648 snd_ice1712_save_gpio_status(ice);
650 ovol = wm_get(ice, WM_OUT_MUX1);
651 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
652 if ((change = (ovol != nvol)))
653 wm_put(ice, WM_OUT_MUX1, nvol);
655 snd_ice1712_restore_gpio_status(ice);
660 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
661 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
662 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
663 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
664 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
667 * Logarithmic volume values for WM8770
668 * Computed as 20 * Log10(255 / x)
670 static const unsigned char wm_vol[256] = {
671 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
672 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
673 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
674 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
675 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
676 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,
677 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,
678 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,
679 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,
680 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,
681 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,
685 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
686 #define WM_VOL_MUTE 0x8000
688 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
692 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
695 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
697 wm_put(ice, index, nvol);
698 wm_put_nocache(ice, index, 0x180 | nvol);
704 #define wm_pcm_mute_info snd_ctl_boolean_mono_info
706 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
708 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
710 mutex_lock(&ice->gpio_mutex);
711 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
712 mutex_unlock(&ice->gpio_mutex);
716 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
718 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
719 unsigned short nval, oval;
722 snd_ice1712_save_gpio_status(ice);
723 oval = wm_get(ice, WM_MUTE);
724 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
725 if ((change = (nval != oval)))
726 wm_put(ice, WM_MUTE, nval);
727 snd_ice1712_restore_gpio_status(ice);
733 * Master volume attenuation mixer control
735 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
737 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
739 uinfo->value.integer.min = 0;
740 uinfo->value.integer.max = WM_VOL_MAX;
744 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
746 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
749 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
753 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
755 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
758 snd_ice1712_save_gpio_status(ice);
759 for (ch = 0; ch < 2; ch++) {
760 unsigned int vol = ucontrol->value.integer.value[ch];
761 if (vol > WM_VOL_MAX)
763 vol |= ice->spec.aureon.master[ch] & WM_VOL_MUTE;
764 if (vol != ice->spec.aureon.master[ch]) {
766 ice->spec.aureon.master[ch] = vol;
767 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
768 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
769 ice->spec.aureon.vol[dac + ch],
770 ice->spec.aureon.master[ch]);
774 snd_ice1712_restore_gpio_status(ice);
779 * DAC volume attenuation mixer control
781 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
783 int voices = kcontrol->private_value >> 8;
784 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
785 uinfo->count = voices;
786 uinfo->value.integer.min = 0; /* mute (-101dB) */
787 uinfo->value.integer.max = 0x7F; /* 0dB */
791 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
793 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
796 voices = kcontrol->private_value >> 8;
797 ofs = kcontrol->private_value & 0xff;
798 for (i = 0; i < voices; i++)
799 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
803 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
805 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
806 int i, idx, ofs, voices;
809 voices = kcontrol->private_value >> 8;
810 ofs = kcontrol->private_value & 0xff;
811 snd_ice1712_save_gpio_status(ice);
812 for (i = 0; i < voices; i++) {
813 unsigned int vol = ucontrol->value.integer.value[i];
816 vol |= ice->spec.aureon.vol[ofs+i];
817 if (vol != ice->spec.aureon.vol[ofs+i]) {
818 ice->spec.aureon.vol[ofs+i] = vol;
819 idx = WM_DAC_ATTEN + ofs + i;
820 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
821 ice->spec.aureon.master[i]);
825 snd_ice1712_restore_gpio_status(ice);
830 * WM8770 mute control
832 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
833 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
834 uinfo->count = kcontrol->private_value >> 8;
835 uinfo->value.integer.min = 0;
836 uinfo->value.integer.max = 1;
840 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
842 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
845 voices = kcontrol->private_value >> 8;
846 ofs = kcontrol->private_value & 0xFF;
848 for (i = 0; i < voices; i++)
849 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
853 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
855 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
856 int change = 0, voices, ofs, i;
858 voices = kcontrol->private_value >> 8;
859 ofs = kcontrol->private_value & 0xFF;
861 snd_ice1712_save_gpio_status(ice);
862 for (i = 0; i < voices; i++) {
863 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
864 if (ucontrol->value.integer.value[i] != val) {
865 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
866 ice->spec.aureon.vol[ofs + i] |=
867 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
868 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
869 ice->spec.aureon.master[i]);
873 snd_ice1712_restore_gpio_status(ice);
879 * WM8770 master mute control
881 #define wm_master_mute_info snd_ctl_boolean_stereo_info
883 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
885 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
887 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
888 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
892 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
894 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
897 snd_ice1712_save_gpio_status(ice);
898 for (i = 0; i < 2; i++) {
899 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
900 if (ucontrol->value.integer.value[i] != val) {
902 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
903 ice->spec.aureon.master[i] |=
904 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
905 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
906 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
907 ice->spec.aureon.vol[dac + i],
908 ice->spec.aureon.master[i]);
912 snd_ice1712_restore_gpio_status(ice);
917 /* digital master volume */
919 #define PCM_RES 128 /* -64dB */
920 #define PCM_MIN (PCM_0dB - PCM_RES)
921 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
923 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
925 uinfo->value.integer.min = 0; /* mute (-64dB) */
926 uinfo->value.integer.max = PCM_RES; /* 0dB */
930 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
932 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
935 mutex_lock(&ice->gpio_mutex);
936 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
937 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
938 ucontrol->value.integer.value[0] = val;
939 mutex_unlock(&ice->gpio_mutex);
943 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
945 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
946 unsigned short ovol, nvol;
949 nvol = ucontrol->value.integer.value[0];
952 snd_ice1712_save_gpio_status(ice);
953 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
954 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
956 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
957 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
960 snd_ice1712_restore_gpio_status(ice);
967 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
969 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
971 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
975 mutex_lock(&ice->gpio_mutex);
976 for (i = 0; i < 2; i++) {
977 val = wm_get(ice, WM_ADC_GAIN + i);
978 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
980 mutex_unlock(&ice->gpio_mutex);
984 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
986 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
987 unsigned short new, old;
990 snd_ice1712_save_gpio_status(ice);
991 for (i = 0; i < 2; i++) {
992 old = wm_get(ice, WM_ADC_GAIN + i);
993 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
995 wm_put(ice, WM_ADC_GAIN + i, new);
999 snd_ice1712_restore_gpio_status(ice);
1005 * ADC gain mixer control
1007 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1009 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1011 uinfo->value.integer.min = 0; /* -12dB */
1012 uinfo->value.integer.max = 0x1f; /* 19dB */
1016 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1018 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1022 mutex_lock(&ice->gpio_mutex);
1023 for (i = 0; i < 2; i++) {
1024 idx = WM_ADC_GAIN + i;
1025 vol = wm_get(ice, idx) & 0x1f;
1026 ucontrol->value.integer.value[i] = vol;
1028 mutex_unlock(&ice->gpio_mutex);
1032 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1034 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1036 unsigned short ovol, nvol;
1039 snd_ice1712_save_gpio_status(ice);
1040 for (i = 0; i < 2; i++) {
1041 idx = WM_ADC_GAIN + i;
1042 nvol = ucontrol->value.integer.value[i] & 0x1f;
1043 ovol = wm_get(ice, idx);
1044 if ((ovol & 0x1f) != nvol) {
1045 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1049 snd_ice1712_restore_gpio_status(ice);
1054 * ADC input mux mixer control
1056 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1058 static const char * const texts[] = {
1065 static const char * const universe_texts[] = {
1075 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1077 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1079 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1080 uinfo->value.enumerated.items = 8;
1081 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1082 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1083 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1086 uinfo->value.enumerated.items = 5;
1087 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1088 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1089 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1094 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1096 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1099 mutex_lock(&ice->gpio_mutex);
1100 val = wm_get(ice, WM_ADC_MUX);
1101 ucontrol->value.enumerated.item[0] = val & 7;
1102 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1103 mutex_unlock(&ice->gpio_mutex);
1107 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1109 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1110 unsigned short oval, nval;
1113 snd_ice1712_save_gpio_status(ice);
1114 oval = wm_get(ice, WM_ADC_MUX);
1115 nval = oval & ~0x77;
1116 nval |= ucontrol->value.enumerated.item[0] & 7;
1117 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1118 change = (oval != nval);
1120 wm_put(ice, WM_ADC_MUX, nval);
1121 snd_ice1712_restore_gpio_status(ice);
1128 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1131 static const char * const aureon_texts[] = {
1135 static const char * const prodigy_texts[] = {
1139 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1141 uinfo->value.enumerated.items = 2;
1142 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1143 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1144 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1145 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1147 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1151 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1153 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1155 //snd_ice1712_save_gpio_status(ice);
1156 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1157 ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1158 //snd_ice1712_restore_gpio_status(ice);
1162 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1164 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1165 unsigned short oval, nval;
1168 snd_ice1712_save_gpio_status(ice);
1169 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1170 nval = oval & ~0x07;
1171 nval |= ucontrol->value.enumerated.item[0] & 7;
1172 change = (oval != nval);
1174 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1175 snd_ice1712_restore_gpio_status(ice);
1176 ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1180 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1182 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1184 uinfo->value.integer.min = 0;
1185 uinfo->value.integer.max = 192000;
1189 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1191 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1192 unsigned char ratio;
1193 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1194 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1201 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1203 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1205 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1206 snd_ice1712_save_gpio_status(ice);
1207 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1208 snd_ice1712_restore_gpio_status(ice);
1212 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1214 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1215 unsigned char oval, nval;
1217 snd_ice1712_save_gpio_status(ice);
1218 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1219 if (ucontrol->value.integer.value[0])
1220 nval = oval & ~0x20;
1223 if ((change = (oval != nval)))
1224 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1225 snd_ice1712_restore_gpio_status(ice);
1230 * CS8415A Q-Sub info
1232 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1233 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1238 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1239 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1241 snd_ice1712_save_gpio_status(ice);
1242 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1243 snd_ice1712_restore_gpio_status(ice);
1248 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1249 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1254 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1255 memset(ucontrol->value.iec958.status, 0xFF, 24);
1259 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1260 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1262 snd_ice1712_save_gpio_status(ice);
1263 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1264 snd_ice1712_restore_gpio_status(ice);
1269 * Headphone Amplifier
1271 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1273 unsigned int tmp, tmp2;
1275 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1277 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1278 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1279 tmp |= AUREON_HP_SEL;
1281 tmp |= PRODIGY_HP_SEL;
1283 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1284 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1285 tmp &= ~ AUREON_HP_SEL;
1287 tmp &= ~ PRODIGY_HP_SEL;
1289 snd_ice1712_gpio_write(ice, tmp);
1295 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1297 unsigned int tmp = snd_ice1712_gpio_read(ice);
1299 return ( tmp & AUREON_HP_SEL )!= 0;
1302 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1304 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1306 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1308 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1313 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1315 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1317 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1324 #define aureon_deemp_info snd_ctl_boolean_mono_info
1326 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1328 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1329 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1333 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1335 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1337 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1338 if (ucontrol->value.integer.value[0])
1342 if (temp != temp2) {
1343 wm_put(ice, WM_DAC_CTRL2, temp);
1352 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1354 static const char * const texts[2] = { "128x", "64x" };
1356 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1358 uinfo->value.enumerated.items = 2;
1360 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1361 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1362 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1367 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1369 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1370 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1374 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1377 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1379 temp2 = temp = wm_get(ice, WM_MASTER);
1381 if (ucontrol->value.enumerated.item[0])
1386 if (temp != temp2) {
1387 wm_put(ice, WM_MASTER, temp);
1397 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1399 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1400 .name = "Master Playback Switch",
1401 .info = wm_master_mute_info,
1402 .get = wm_master_mute_get,
1403 .put = wm_master_mute_put
1406 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1407 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1408 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1409 .name = "Master Playback Volume",
1410 .info = wm_master_vol_info,
1411 .get = wm_master_vol_get,
1412 .put = wm_master_vol_put,
1413 .tlv = { .p = db_scale_wm_dac }
1416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1417 .name = "Front Playback Switch",
1418 .info = wm_mute_info,
1421 .private_value = (2 << 8) | 0
1424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1425 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1426 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1427 .name = "Front Playback Volume",
1428 .info = wm_vol_info,
1431 .private_value = (2 << 8) | 0,
1432 .tlv = { .p = db_scale_wm_dac }
1435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1436 .name = "Rear Playback Switch",
1437 .info = wm_mute_info,
1440 .private_value = (2 << 8) | 2
1443 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1444 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1445 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1446 .name = "Rear Playback Volume",
1447 .info = wm_vol_info,
1450 .private_value = (2 << 8) | 2,
1451 .tlv = { .p = db_scale_wm_dac }
1454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1455 .name = "Center Playback Switch",
1456 .info = wm_mute_info,
1459 .private_value = (1 << 8) | 4
1462 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1463 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1464 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1465 .name = "Center Playback Volume",
1466 .info = wm_vol_info,
1469 .private_value = (1 << 8) | 4,
1470 .tlv = { .p = db_scale_wm_dac }
1473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1474 .name = "LFE Playback Switch",
1475 .info = wm_mute_info,
1478 .private_value = (1 << 8) | 5
1481 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1482 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1483 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1484 .name = "LFE Playback Volume",
1485 .info = wm_vol_info,
1488 .private_value = (1 << 8) | 5,
1489 .tlv = { .p = db_scale_wm_dac }
1492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1493 .name = "Side Playback Switch",
1494 .info = wm_mute_info,
1497 .private_value = (2 << 8) | 6
1500 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1501 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1502 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1503 .name = "Side Playback Volume",
1504 .info = wm_vol_info,
1507 .private_value = (2 << 8) | 6,
1508 .tlv = { .p = db_scale_wm_dac }
1512 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1514 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1515 .name = "PCM Playback Switch",
1516 .info = wm_pcm_mute_info,
1517 .get = wm_pcm_mute_get,
1518 .put = wm_pcm_mute_put
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1523 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1524 .name = "PCM Playback Volume",
1525 .info = wm_pcm_vol_info,
1526 .get = wm_pcm_vol_get,
1527 .put = wm_pcm_vol_put,
1528 .tlv = { .p = db_scale_wm_pcm }
1531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1532 .name = "Capture Switch",
1533 .info = wm_adc_mute_info,
1534 .get = wm_adc_mute_get,
1535 .put = wm_adc_mute_put,
1538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1539 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1540 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1541 .name = "Capture Volume",
1542 .info = wm_adc_vol_info,
1543 .get = wm_adc_vol_get,
1544 .put = wm_adc_vol_put,
1545 .tlv = { .p = db_scale_wm_adc }
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "Capture Source",
1550 .info = wm_adc_mux_info,
1551 .get = wm_adc_mux_get,
1552 .put = wm_adc_mux_put,
1556 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557 .name = "External Amplifier",
1558 .info = aureon_hpamp_info,
1559 .get = aureon_hpamp_get,
1560 .put = aureon_hpamp_put
1563 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1564 .name = "DAC Deemphasis Switch",
1565 .info = aureon_deemp_info,
1566 .get = aureon_deemp_get,
1567 .put = aureon_deemp_put
1570 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1571 .name = "ADC Oversampling",
1572 .info = aureon_oversampling_info,
1573 .get = aureon_oversampling_get,
1574 .put = aureon_oversampling_put
1578 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1581 .name = "AC97 Playback Switch",
1582 .info = aureon_ac97_mmute_info,
1583 .get = aureon_ac97_mmute_get,
1584 .put = aureon_ac97_mmute_put,
1585 .private_value = AC97_MASTER
1588 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1589 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1590 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1591 .name = "AC97 Playback Volume",
1592 .info = aureon_ac97_vol_info,
1593 .get = aureon_ac97_vol_get,
1594 .put = aureon_ac97_vol_put,
1595 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1596 .tlv = { .p = db_scale_ac97_master }
1599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1600 .name = "CD Playback Switch",
1601 .info = aureon_ac97_mute_info,
1602 .get = aureon_ac97_mute_get,
1603 .put = aureon_ac97_mute_put,
1604 .private_value = AC97_CD
1607 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1608 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1609 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1610 .name = "CD Playback Volume",
1611 .info = aureon_ac97_vol_info,
1612 .get = aureon_ac97_vol_get,
1613 .put = aureon_ac97_vol_put,
1614 .private_value = AC97_CD|AUREON_AC97_STEREO,
1615 .tlv = { .p = db_scale_ac97_gain }
1618 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1619 .name = "Aux Playback Switch",
1620 .info = aureon_ac97_mute_info,
1621 .get = aureon_ac97_mute_get,
1622 .put = aureon_ac97_mute_put,
1623 .private_value = AC97_AUX,
1626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1627 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1628 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1629 .name = "Aux Playback Volume",
1630 .info = aureon_ac97_vol_info,
1631 .get = aureon_ac97_vol_get,
1632 .put = aureon_ac97_vol_put,
1633 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1634 .tlv = { .p = db_scale_ac97_gain }
1637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1638 .name = "Line Playback Switch",
1639 .info = aureon_ac97_mute_info,
1640 .get = aureon_ac97_mute_get,
1641 .put = aureon_ac97_mute_put,
1642 .private_value = AC97_LINE
1645 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1646 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1647 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1648 .name = "Line Playback Volume",
1649 .info = aureon_ac97_vol_info,
1650 .get = aureon_ac97_vol_get,
1651 .put = aureon_ac97_vol_put,
1652 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1653 .tlv = { .p = db_scale_ac97_gain }
1656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1657 .name = "Mic Playback Switch",
1658 .info = aureon_ac97_mute_info,
1659 .get = aureon_ac97_mute_get,
1660 .put = aureon_ac97_mute_put,
1661 .private_value = AC97_MIC
1664 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1665 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1666 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1667 .name = "Mic Playback Volume",
1668 .info = aureon_ac97_vol_info,
1669 .get = aureon_ac97_vol_get,
1670 .put = aureon_ac97_vol_put,
1671 .private_value = AC97_MIC,
1672 .tlv = { .p = db_scale_ac97_gain }
1675 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1676 .name = "Mic Boost (+20dB)",
1677 .info = aureon_ac97_micboost_info,
1678 .get = aureon_ac97_micboost_get,
1679 .put = aureon_ac97_micboost_put
1683 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1685 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1686 .name = "AC97 Playback Switch",
1687 .info = aureon_ac97_mmute_info,
1688 .get = aureon_ac97_mmute_get,
1689 .put = aureon_ac97_mmute_put,
1690 .private_value = AC97_MASTER
1693 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1694 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1695 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1696 .name = "AC97 Playback Volume",
1697 .info = aureon_ac97_vol_info,
1698 .get = aureon_ac97_vol_get,
1699 .put = aureon_ac97_vol_put,
1700 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1701 .tlv = { .p = db_scale_ac97_master }
1704 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1705 .name = "CD Playback Switch",
1706 .info = aureon_ac97_mute_info,
1707 .get = aureon_ac97_mute_get,
1708 .put = aureon_ac97_mute_put,
1709 .private_value = AC97_AUX
1712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1713 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1714 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1715 .name = "CD Playback Volume",
1716 .info = aureon_ac97_vol_info,
1717 .get = aureon_ac97_vol_get,
1718 .put = aureon_ac97_vol_put,
1719 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1720 .tlv = { .p = db_scale_ac97_gain }
1723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1724 .name = "Phono Playback Switch",
1725 .info = aureon_ac97_mute_info,
1726 .get = aureon_ac97_mute_get,
1727 .put = aureon_ac97_mute_put,
1728 .private_value = AC97_CD
1731 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1732 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1733 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1734 .name = "Phono Playback Volume",
1735 .info = aureon_ac97_vol_info,
1736 .get = aureon_ac97_vol_get,
1737 .put = aureon_ac97_vol_put,
1738 .private_value = AC97_CD|AUREON_AC97_STEREO,
1739 .tlv = { .p = db_scale_ac97_gain }
1742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1743 .name = "Line Playback Switch",
1744 .info = aureon_ac97_mute_info,
1745 .get = aureon_ac97_mute_get,
1746 .put = aureon_ac97_mute_put,
1747 .private_value = AC97_LINE
1750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1751 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1752 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1753 .name = "Line Playback Volume",
1754 .info = aureon_ac97_vol_info,
1755 .get = aureon_ac97_vol_get,
1756 .put = aureon_ac97_vol_put,
1757 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1758 .tlv = { .p = db_scale_ac97_gain }
1761 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1762 .name = "Mic Playback Switch",
1763 .info = aureon_ac97_mute_info,
1764 .get = aureon_ac97_mute_get,
1765 .put = aureon_ac97_mute_put,
1766 .private_value = AC97_MIC
1769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1770 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1771 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1772 .name = "Mic Playback Volume",
1773 .info = aureon_ac97_vol_info,
1774 .get = aureon_ac97_vol_get,
1775 .put = aureon_ac97_vol_put,
1776 .private_value = AC97_MIC,
1777 .tlv = { .p = db_scale_ac97_gain }
1780 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1781 .name = "Mic Boost (+20dB)",
1782 .info = aureon_ac97_micboost_info,
1783 .get = aureon_ac97_micboost_get,
1784 .put = aureon_ac97_micboost_put
1787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1788 .name = "Aux Playback Switch",
1789 .info = aureon_ac97_mute_info,
1790 .get = aureon_ac97_mute_get,
1791 .put = aureon_ac97_mute_put,
1792 .private_value = AC97_VIDEO,
1795 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1796 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1797 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1798 .name = "Aux Playback Volume",
1799 .info = aureon_ac97_vol_info,
1800 .get = aureon_ac97_vol_get,
1801 .put = aureon_ac97_vol_put,
1802 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1803 .tlv = { .p = db_scale_ac97_gain }
1806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1807 .name = "Aux Source",
1808 .info = aureon_universe_inmux_info,
1809 .get = aureon_universe_inmux_get,
1810 .put = aureon_universe_inmux_put
1815 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1817 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1818 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1819 .info = aureon_cs8415_mute_info,
1820 .get = aureon_cs8415_mute_get,
1821 .put = aureon_cs8415_mute_put
1824 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1825 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1826 .info = aureon_cs8415_mux_info,
1827 .get = aureon_cs8415_mux_get,
1828 .put = aureon_cs8415_mux_put,
1831 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1832 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1833 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1834 .info = aureon_cs8415_qsub_info,
1835 .get = aureon_cs8415_qsub_get,
1838 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1839 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1840 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1841 .info = aureon_cs8415_spdif_info,
1842 .get = aureon_cs8415_mask_get
1845 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1846 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1847 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1848 .info = aureon_cs8415_spdif_info,
1849 .get = aureon_cs8415_spdif_get
1852 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1853 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1854 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1855 .info = aureon_cs8415_rate_info,
1856 .get = aureon_cs8415_rate_get
1860 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1862 unsigned int i, counts;
1865 counts = ARRAY_SIZE(aureon_dac_controls);
1866 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1867 counts -= 2; /* no side */
1868 for (i = 0; i < counts; i++) {
1869 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1874 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1875 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1880 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1881 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1882 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1887 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1888 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1889 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1890 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1896 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1897 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1899 snd_ice1712_save_gpio_status(ice);
1900 id = aureon_cs8415_get(ice, CS8415_ID);
1902 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1903 else if ((id & 0x0F) != 0x01)
1904 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1906 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1907 struct snd_kcontrol *kctl;
1908 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1912 kctl->id.device = ice->pcm->device;
1915 snd_ice1712_restore_gpio_status(ice);
1923 * initialize the chip
1925 static int __devinit aureon_init(struct snd_ice1712 *ice)
1927 static const unsigned short wm_inits_aureon[] = {
1928 /* These come first to reduce init pop noise */
1929 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1930 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1931 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1933 0x18, 0x000, /* All power-up */
1935 0x16, 0x122, /* I2S, normal polarity, 24bit */
1936 0x17, 0x022, /* 256fs, slave mode */
1937 0x00, 0, /* DAC1 analog mute */
1938 0x01, 0, /* DAC2 analog mute */
1939 0x02, 0, /* DAC3 analog mute */
1940 0x03, 0, /* DAC4 analog mute */
1941 0x04, 0, /* DAC5 analog mute */
1942 0x05, 0, /* DAC6 analog mute */
1943 0x06, 0, /* DAC7 analog mute */
1944 0x07, 0, /* DAC8 analog mute */
1945 0x08, 0x100, /* master analog mute */
1946 0x09, 0xff, /* DAC1 digital full */
1947 0x0a, 0xff, /* DAC2 digital full */
1948 0x0b, 0xff, /* DAC3 digital full */
1949 0x0c, 0xff, /* DAC4 digital full */
1950 0x0d, 0xff, /* DAC5 digital full */
1951 0x0e, 0xff, /* DAC6 digital full */
1952 0x0f, 0xff, /* DAC7 digital full */
1953 0x10, 0xff, /* DAC8 digital full */
1954 0x11, 0x1ff, /* master digital full */
1955 0x12, 0x000, /* phase normal */
1956 0x13, 0x090, /* unmute DAC L/R */
1957 0x14, 0x000, /* all unmute */
1958 0x15, 0x000, /* no deemphasis, no ZFLG */
1959 0x19, 0x000, /* -12dB ADC/L */
1960 0x1a, 0x000, /* -12dB ADC/R */
1963 static const unsigned short wm_inits_prodigy[] = {
1965 /* These come first to reduce init pop noise */
1966 0x1b, 0x000, /* ADC Mux */
1967 0x1c, 0x009, /* Out Mux1 */
1968 0x1d, 0x009, /* Out Mux2 */
1970 0x18, 0x000, /* All power-up */
1972 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1973 0x17, 0x006, /* 128fs, slave mode */
1975 0x00, 0, /* DAC1 analog mute */
1976 0x01, 0, /* DAC2 analog mute */
1977 0x02, 0, /* DAC3 analog mute */
1978 0x03, 0, /* DAC4 analog mute */
1979 0x04, 0, /* DAC5 analog mute */
1980 0x05, 0, /* DAC6 analog mute */
1981 0x06, 0, /* DAC7 analog mute */
1982 0x07, 0, /* DAC8 analog mute */
1983 0x08, 0x100, /* master analog mute */
1985 0x09, 0x7f, /* DAC1 digital full */
1986 0x0a, 0x7f, /* DAC2 digital full */
1987 0x0b, 0x7f, /* DAC3 digital full */
1988 0x0c, 0x7f, /* DAC4 digital full */
1989 0x0d, 0x7f, /* DAC5 digital full */
1990 0x0e, 0x7f, /* DAC6 digital full */
1991 0x0f, 0x7f, /* DAC7 digital full */
1992 0x10, 0x7f, /* DAC8 digital full */
1993 0x11, 0x1FF, /* master digital full */
1995 0x12, 0x000, /* phase normal */
1996 0x13, 0x090, /* unmute DAC L/R */
1997 0x14, 0x000, /* all unmute */
1998 0x15, 0x000, /* no deemphasis, no ZFLG */
2000 0x19, 0x000, /* -12dB ADC/L */
2001 0x1a, 0x000, /* -12dB ADC/R */
2005 static const unsigned short cs_inits[] = {
2007 0x0180, /* no mute, OMCK output on RMCK pin */
2008 0x0201, /* S/PDIF source on RXP1 */
2009 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2013 const unsigned short *p;
2016 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2017 ice->num_total_dacs = 6;
2018 ice->num_total_adcs = 2;
2020 /* aureon 7.1 and prodigy 7.1 */
2021 ice->num_total_dacs = 8;
2022 ice->num_total_adcs = 2;
2025 /* to remeber the register values of CS8415 */
2026 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2029 ice->akm_codecs = 1;
2031 if ((err = aureon_ac97_init(ice)) != 0)
2034 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2036 /* reset the wm codec as the SPI mode */
2037 snd_ice1712_save_gpio_status(ice);
2038 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2040 tmp = snd_ice1712_gpio_read(ice);
2041 tmp &= ~AUREON_WM_RESET;
2042 snd_ice1712_gpio_write(ice, tmp);
2044 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2045 snd_ice1712_gpio_write(ice, tmp);
2047 tmp |= AUREON_WM_RESET;
2048 snd_ice1712_gpio_write(ice, tmp);
2051 /* initialize WM8770 codec */
2052 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2053 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2054 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2055 p = wm_inits_prodigy;
2057 p = wm_inits_aureon;
2058 for (; *p != (unsigned short)-1; p += 2)
2059 wm_put(ice, p[0], p[1]);
2061 /* initialize CS8415A codec */
2062 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2063 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2064 for (p = cs_inits; *p != (unsigned short)-1; p++)
2065 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2066 ice->spec.aureon.cs8415_mux = 1;
2068 aureon_set_headphone_amp(ice, 1);
2071 snd_ice1712_restore_gpio_status(ice);
2073 /* initialize PCA9554 pin directions & set default input*/
2074 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2075 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2077 ice->spec.aureon.master[0] = WM_VOL_MUTE;
2078 ice->spec.aureon.master[1] = WM_VOL_MUTE;
2079 for (i = 0; i < ice->num_total_dacs; i++) {
2080 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2081 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2089 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2090 * hence the driver needs to sets up it properly.
2093 static unsigned char aureon51_eeprom[] __devinitdata = {
2094 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2095 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2096 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2097 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2098 [ICE_EEP2_GPIO_DIR] = 0xff,
2099 [ICE_EEP2_GPIO_DIR1] = 0xff,
2100 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2101 [ICE_EEP2_GPIO_MASK] = 0x00,
2102 [ICE_EEP2_GPIO_MASK1] = 0x00,
2103 [ICE_EEP2_GPIO_MASK2] = 0x00,
2104 [ICE_EEP2_GPIO_STATE] = 0x00,
2105 [ICE_EEP2_GPIO_STATE1] = 0x00,
2106 [ICE_EEP2_GPIO_STATE2] = 0x00,
2109 static unsigned char aureon71_eeprom[] __devinitdata = {
2110 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2111 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2112 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2113 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2114 [ICE_EEP2_GPIO_DIR] = 0xff,
2115 [ICE_EEP2_GPIO_DIR1] = 0xff,
2116 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2117 [ICE_EEP2_GPIO_MASK] = 0x00,
2118 [ICE_EEP2_GPIO_MASK1] = 0x00,
2119 [ICE_EEP2_GPIO_MASK2] = 0x00,
2120 [ICE_EEP2_GPIO_STATE] = 0x00,
2121 [ICE_EEP2_GPIO_STATE1] = 0x00,
2122 [ICE_EEP2_GPIO_STATE2] = 0x00,
2124 #define prodigy71_eeprom aureon71_eeprom
2126 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2127 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2128 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2129 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2130 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2131 [ICE_EEP2_GPIO_DIR] = 0xff,
2132 [ICE_EEP2_GPIO_DIR1] = 0xff,
2133 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2134 [ICE_EEP2_GPIO_MASK] = 0x00,
2135 [ICE_EEP2_GPIO_MASK1] = 0x00,
2136 [ICE_EEP2_GPIO_MASK2] = 0x00,
2137 [ICE_EEP2_GPIO_STATE] = 0x00,
2138 [ICE_EEP2_GPIO_STATE1] = 0x00,
2139 [ICE_EEP2_GPIO_STATE2] = 0x00,
2141 #define prodigy71xt_eeprom prodigy71lt_eeprom
2144 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2146 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2147 .name = "Terratec Aureon 5.1-Sky",
2148 .model = "aureon51",
2149 .chip_init = aureon_init,
2150 .build_controls = aureon_add_controls,
2151 .eeprom_size = sizeof(aureon51_eeprom),
2152 .eeprom_data = aureon51_eeprom,
2153 .driver = "Aureon51",
2156 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2157 .name = "Terratec Aureon 7.1-Space",
2158 .model = "aureon71",
2159 .chip_init = aureon_init,
2160 .build_controls = aureon_add_controls,
2161 .eeprom_size = sizeof(aureon71_eeprom),
2162 .eeprom_data = aureon71_eeprom,
2163 .driver = "Aureon71",
2166 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2167 .name = "Terratec Aureon 7.1-Universe",
2168 .model = "universe",
2169 .chip_init = aureon_init,
2170 .build_controls = aureon_add_controls,
2171 .eeprom_size = sizeof(aureon71_eeprom),
2172 .eeprom_data = aureon71_eeprom,
2173 .driver = "Aureon71Univ", /* keep in 15 letters */
2176 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2177 .name = "Audiotrak Prodigy 7.1",
2178 .model = "prodigy71",
2179 .chip_init = aureon_init,
2180 .build_controls = aureon_add_controls,
2181 .eeprom_size = sizeof(prodigy71_eeprom),
2182 .eeprom_data = prodigy71_eeprom,
2183 .driver = "Prodigy71", /* should be identical with Aureon71 */
2186 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2187 .name = "Audiotrak Prodigy 7.1 LT",
2188 .model = "prodigy71lt",
2189 .chip_init = aureon_init,
2190 .build_controls = aureon_add_controls,
2191 .eeprom_size = sizeof(prodigy71lt_eeprom),
2192 .eeprom_data = prodigy71lt_eeprom,
2193 .driver = "Prodigy71LT",
2196 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2197 .name = "Audiotrak Prodigy 7.1 XT",
2198 .model = "prodigy71xt",
2199 .chip_init = aureon_init,
2200 .build_controls = aureon_add_controls,
2201 .eeprom_size = sizeof(prodigy71xt_eeprom),
2202 .eeprom_data = prodigy71xt_eeprom,
2203 .driver = "Prodigy71LT",
2205 { } /* terminator */