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 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 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
762 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
763 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
764 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
765 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
766 ice->spec.aureon.vol[dac + ch],
767 ice->spec.aureon.master[ch]);
771 snd_ice1712_restore_gpio_status(ice);
776 * DAC volume attenuation mixer control
778 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
780 int voices = kcontrol->private_value >> 8;
781 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
782 uinfo->count = voices;
783 uinfo->value.integer.min = 0; /* mute (-101dB) */
784 uinfo->value.integer.max = 0x7F; /* 0dB */
788 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
790 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
793 voices = kcontrol->private_value >> 8;
794 ofs = kcontrol->private_value & 0xff;
795 for (i = 0; i < voices; i++)
796 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
800 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
802 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
803 int i, idx, ofs, voices;
806 voices = kcontrol->private_value >> 8;
807 ofs = kcontrol->private_value & 0xff;
808 snd_ice1712_save_gpio_status(ice);
809 for (i = 0; i < voices; i++) {
810 idx = WM_DAC_ATTEN + ofs + i;
811 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
812 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
813 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
814 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
815 ice->spec.aureon.master[i]);
819 snd_ice1712_restore_gpio_status(ice);
824 * WM8770 mute control
826 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
827 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
828 uinfo->count = kcontrol->private_value >> 8;
829 uinfo->value.integer.min = 0;
830 uinfo->value.integer.max = 1;
834 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
836 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
839 voices = kcontrol->private_value >> 8;
840 ofs = kcontrol->private_value & 0xFF;
842 for (i = 0; i < voices; i++)
843 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
847 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
849 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
850 int change = 0, voices, ofs, i;
852 voices = kcontrol->private_value >> 8;
853 ofs = kcontrol->private_value & 0xFF;
855 snd_ice1712_save_gpio_status(ice);
856 for (i = 0; i < voices; i++) {
857 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
858 if (ucontrol->value.integer.value[i] != val) {
859 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
860 ice->spec.aureon.vol[ofs + i] |=
861 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
862 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
863 ice->spec.aureon.master[i]);
867 snd_ice1712_restore_gpio_status(ice);
873 * WM8770 master mute control
875 #define wm_master_mute_info snd_ctl_boolean_stereo_info
877 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
879 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
881 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
882 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
886 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
888 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
891 snd_ice1712_save_gpio_status(ice);
892 for (i = 0; i < 2; i++) {
893 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
894 if (ucontrol->value.integer.value[i] != val) {
896 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
897 ice->spec.aureon.master[i] |=
898 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
899 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
900 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
901 ice->spec.aureon.vol[dac + i],
902 ice->spec.aureon.master[i]);
906 snd_ice1712_restore_gpio_status(ice);
911 /* digital master volume */
913 #define PCM_RES 128 /* -64dB */
914 #define PCM_MIN (PCM_0dB - PCM_RES)
915 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
917 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
919 uinfo->value.integer.min = 0; /* mute (-64dB) */
920 uinfo->value.integer.max = PCM_RES; /* 0dB */
924 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
926 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
929 mutex_lock(&ice->gpio_mutex);
930 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
931 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
932 ucontrol->value.integer.value[0] = val;
933 mutex_unlock(&ice->gpio_mutex);
937 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
939 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
940 unsigned short ovol, nvol;
943 snd_ice1712_save_gpio_status(ice);
944 nvol = ucontrol->value.integer.value[0];
945 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
946 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
948 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
949 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
952 snd_ice1712_restore_gpio_status(ice);
959 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
961 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
963 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
967 mutex_lock(&ice->gpio_mutex);
968 for (i = 0; i < 2; i++) {
969 val = wm_get(ice, WM_ADC_GAIN + i);
970 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
972 mutex_unlock(&ice->gpio_mutex);
976 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
978 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
979 unsigned short new, old;
982 snd_ice1712_save_gpio_status(ice);
983 for (i = 0; i < 2; i++) {
984 old = wm_get(ice, WM_ADC_GAIN + i);
985 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
987 wm_put(ice, WM_ADC_GAIN + i, new);
991 snd_ice1712_restore_gpio_status(ice);
997 * ADC gain mixer control
999 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1001 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1003 uinfo->value.integer.min = 0; /* -12dB */
1004 uinfo->value.integer.max = 0x1f; /* 19dB */
1008 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1010 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1014 mutex_lock(&ice->gpio_mutex);
1015 for (i = 0; i < 2; i++) {
1016 idx = WM_ADC_GAIN + i;
1017 vol = wm_get(ice, idx) & 0x1f;
1018 ucontrol->value.integer.value[i] = vol;
1020 mutex_unlock(&ice->gpio_mutex);
1024 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1026 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1028 unsigned short ovol, nvol;
1031 snd_ice1712_save_gpio_status(ice);
1032 for (i = 0; i < 2; i++) {
1033 idx = WM_ADC_GAIN + i;
1034 nvol = ucontrol->value.integer.value[i];
1035 ovol = wm_get(ice, idx);
1036 if ((ovol & 0x1f) != nvol) {
1037 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1041 snd_ice1712_restore_gpio_status(ice);
1046 * ADC input mux mixer control
1048 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1050 static const char * const texts[] = {
1057 static const char * const universe_texts[] = {
1067 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1069 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1071 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1072 uinfo->value.enumerated.items = 8;
1073 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1074 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1075 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1078 uinfo->value.enumerated.items = 5;
1079 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1080 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1081 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1086 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1088 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1091 mutex_lock(&ice->gpio_mutex);
1092 val = wm_get(ice, WM_ADC_MUX);
1093 ucontrol->value.enumerated.item[0] = val & 7;
1094 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1095 mutex_unlock(&ice->gpio_mutex);
1099 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1101 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1102 unsigned short oval, nval;
1105 snd_ice1712_save_gpio_status(ice);
1106 oval = wm_get(ice, WM_ADC_MUX);
1107 nval = oval & ~0x77;
1108 nval |= ucontrol->value.enumerated.item[0] & 7;
1109 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1110 change = (oval != nval);
1112 wm_put(ice, WM_ADC_MUX, nval);
1113 snd_ice1712_restore_gpio_status(ice);
1120 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1122 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1123 static const char * const aureon_texts[] = {
1127 static const char * const prodigy_texts[] = {
1131 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1133 uinfo->value.enumerated.items = 2;
1134 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1135 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1136 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1137 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1139 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1143 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1145 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1147 //snd_ice1712_save_gpio_status(ice);
1148 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1149 ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1150 //snd_ice1712_restore_gpio_status(ice);
1154 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1156 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1157 unsigned short oval, nval;
1160 snd_ice1712_save_gpio_status(ice);
1161 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1162 nval = oval & ~0x07;
1163 nval |= ucontrol->value.enumerated.item[0] & 7;
1164 change = (oval != nval);
1166 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1167 snd_ice1712_restore_gpio_status(ice);
1168 ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1172 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1174 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1176 uinfo->value.integer.min = 0;
1177 uinfo->value.integer.max = 192000;
1181 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1183 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1184 unsigned char ratio;
1185 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1186 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1193 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1195 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1197 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1198 snd_ice1712_save_gpio_status(ice);
1199 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1200 snd_ice1712_restore_gpio_status(ice);
1204 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1206 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1207 unsigned char oval, nval;
1209 snd_ice1712_save_gpio_status(ice);
1210 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1211 if (ucontrol->value.integer.value[0])
1212 nval = oval & ~0x20;
1215 if ((change = (oval != nval)))
1216 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1217 snd_ice1712_restore_gpio_status(ice);
1222 * CS8415A Q-Sub info
1224 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1225 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1230 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1231 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1233 snd_ice1712_save_gpio_status(ice);
1234 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1235 snd_ice1712_restore_gpio_status(ice);
1240 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1241 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1246 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1247 memset(ucontrol->value.iec958.status, 0xFF, 24);
1251 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1252 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1254 snd_ice1712_save_gpio_status(ice);
1255 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1256 snd_ice1712_restore_gpio_status(ice);
1261 * Headphone Amplifier
1263 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1265 unsigned int tmp, tmp2;
1267 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1269 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1270 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1271 tmp |= AUREON_HP_SEL;
1273 tmp |= PRODIGY_HP_SEL;
1275 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1276 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1277 tmp &= ~ AUREON_HP_SEL;
1279 tmp &= ~ PRODIGY_HP_SEL;
1281 snd_ice1712_gpio_write(ice, tmp);
1287 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1289 unsigned int tmp = snd_ice1712_gpio_read(ice);
1291 return ( tmp & AUREON_HP_SEL )!= 0;
1294 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1296 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1298 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1300 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1305 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1307 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1309 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1316 #define aureon_deemp_info snd_ctl_boolean_mono_info
1318 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1320 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1321 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1325 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1327 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1329 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1330 if (ucontrol->value.integer.value[0])
1334 if (temp != temp2) {
1335 wm_put(ice, WM_DAC_CTRL2, temp);
1344 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1346 static const char * const texts[2] = { "128x", "64x" };
1348 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1350 uinfo->value.enumerated.items = 2;
1352 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1353 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1354 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1359 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1361 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1362 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1366 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1369 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1371 temp2 = temp = wm_get(ice, WM_MASTER);
1373 if (ucontrol->value.enumerated.item[0])
1378 if (temp != temp2) {
1379 wm_put(ice, WM_MASTER, temp);
1389 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1392 .name = "Master Playback Switch",
1393 .info = wm_master_mute_info,
1394 .get = wm_master_mute_get,
1395 .put = wm_master_mute_put
1398 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1399 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1400 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1401 .name = "Master Playback Volume",
1402 .info = wm_master_vol_info,
1403 .get = wm_master_vol_get,
1404 .put = wm_master_vol_put,
1405 .tlv = { .p = db_scale_wm_dac }
1408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1409 .name = "Front Playback Switch",
1410 .info = wm_mute_info,
1413 .private_value = (2 << 8) | 0
1416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1417 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1418 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1419 .name = "Front Playback Volume",
1420 .info = wm_vol_info,
1423 .private_value = (2 << 8) | 0,
1424 .tlv = { .p = db_scale_wm_dac }
1427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1428 .name = "Rear Playback Switch",
1429 .info = wm_mute_info,
1432 .private_value = (2 << 8) | 2
1435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1436 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1437 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1438 .name = "Rear Playback Volume",
1439 .info = wm_vol_info,
1442 .private_value = (2 << 8) | 2,
1443 .tlv = { .p = db_scale_wm_dac }
1446 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1447 .name = "Center Playback Switch",
1448 .info = wm_mute_info,
1451 .private_value = (1 << 8) | 4
1454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1455 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1456 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1457 .name = "Center Playback Volume",
1458 .info = wm_vol_info,
1461 .private_value = (1 << 8) | 4,
1462 .tlv = { .p = db_scale_wm_dac }
1465 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1466 .name = "LFE Playback Switch",
1467 .info = wm_mute_info,
1470 .private_value = (1 << 8) | 5
1473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1474 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1475 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1476 .name = "LFE Playback Volume",
1477 .info = wm_vol_info,
1480 .private_value = (1 << 8) | 5,
1481 .tlv = { .p = db_scale_wm_dac }
1484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485 .name = "Side Playback Switch",
1486 .info = wm_mute_info,
1489 .private_value = (2 << 8) | 6
1492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1493 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1494 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1495 .name = "Side Playback Volume",
1496 .info = wm_vol_info,
1499 .private_value = (2 << 8) | 6,
1500 .tlv = { .p = db_scale_wm_dac }
1504 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1507 .name = "PCM Playback Switch",
1508 .info = wm_pcm_mute_info,
1509 .get = wm_pcm_mute_get,
1510 .put = wm_pcm_mute_put
1513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1514 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1515 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1516 .name = "PCM Playback Volume",
1517 .info = wm_pcm_vol_info,
1518 .get = wm_pcm_vol_get,
1519 .put = wm_pcm_vol_put,
1520 .tlv = { .p = db_scale_wm_pcm }
1523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1524 .name = "Capture Switch",
1525 .info = wm_adc_mute_info,
1526 .get = wm_adc_mute_get,
1527 .put = wm_adc_mute_put,
1530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1531 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1532 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1533 .name = "Capture Volume",
1534 .info = wm_adc_vol_info,
1535 .get = wm_adc_vol_get,
1536 .put = wm_adc_vol_put,
1537 .tlv = { .p = db_scale_wm_adc }
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Capture Source",
1542 .info = wm_adc_mux_info,
1543 .get = wm_adc_mux_get,
1544 .put = wm_adc_mux_put,
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "External Amplifier",
1550 .info = aureon_hpamp_info,
1551 .get = aureon_hpamp_get,
1552 .put = aureon_hpamp_put
1555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1556 .name = "DAC Deemphasis Switch",
1557 .info = aureon_deemp_info,
1558 .get = aureon_deemp_get,
1559 .put = aureon_deemp_put
1562 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1563 .name = "ADC Oversampling",
1564 .info = aureon_oversampling_info,
1565 .get = aureon_oversampling_get,
1566 .put = aureon_oversampling_put
1570 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1572 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1573 .name = "AC97 Playback Switch",
1574 .info = aureon_ac97_mmute_info,
1575 .get = aureon_ac97_mmute_get,
1576 .put = aureon_ac97_mmute_put,
1577 .private_value = AC97_MASTER
1580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1581 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1582 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1583 .name = "AC97 Playback Volume",
1584 .info = aureon_ac97_vol_info,
1585 .get = aureon_ac97_vol_get,
1586 .put = aureon_ac97_vol_put,
1587 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1588 .tlv = { .p = db_scale_ac97_master }
1591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592 .name = "CD Playback Switch",
1593 .info = aureon_ac97_mute_info,
1594 .get = aureon_ac97_mute_get,
1595 .put = aureon_ac97_mute_put,
1596 .private_value = AC97_CD
1599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1600 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1601 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1602 .name = "CD Playback Volume",
1603 .info = aureon_ac97_vol_info,
1604 .get = aureon_ac97_vol_get,
1605 .put = aureon_ac97_vol_put,
1606 .private_value = AC97_CD|AUREON_AC97_STEREO,
1607 .tlv = { .p = db_scale_ac97_gain }
1610 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1611 .name = "Aux Playback Switch",
1612 .info = aureon_ac97_mute_info,
1613 .get = aureon_ac97_mute_get,
1614 .put = aureon_ac97_mute_put,
1615 .private_value = AC97_AUX,
1618 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1619 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1620 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1621 .name = "Aux Playback Volume",
1622 .info = aureon_ac97_vol_info,
1623 .get = aureon_ac97_vol_get,
1624 .put = aureon_ac97_vol_put,
1625 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1626 .tlv = { .p = db_scale_ac97_gain }
1629 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1630 .name = "Line Playback Switch",
1631 .info = aureon_ac97_mute_info,
1632 .get = aureon_ac97_mute_get,
1633 .put = aureon_ac97_mute_put,
1634 .private_value = AC97_LINE
1637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1638 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1639 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1640 .name = "Line Playback Volume",
1641 .info = aureon_ac97_vol_info,
1642 .get = aureon_ac97_vol_get,
1643 .put = aureon_ac97_vol_put,
1644 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1645 .tlv = { .p = db_scale_ac97_gain }
1648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1649 .name = "Mic Playback Switch",
1650 .info = aureon_ac97_mute_info,
1651 .get = aureon_ac97_mute_get,
1652 .put = aureon_ac97_mute_put,
1653 .private_value = AC97_MIC
1656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1657 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1658 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1659 .name = "Mic Playback Volume",
1660 .info = aureon_ac97_vol_info,
1661 .get = aureon_ac97_vol_get,
1662 .put = aureon_ac97_vol_put,
1663 .private_value = AC97_MIC,
1664 .tlv = { .p = db_scale_ac97_gain }
1667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1668 .name = "Mic Boost (+20dB)",
1669 .info = aureon_ac97_micboost_info,
1670 .get = aureon_ac97_micboost_get,
1671 .put = aureon_ac97_micboost_put
1675 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1678 .name = "AC97 Playback Switch",
1679 .info = aureon_ac97_mmute_info,
1680 .get = aureon_ac97_mmute_get,
1681 .put = aureon_ac97_mmute_put,
1682 .private_value = AC97_MASTER
1685 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1686 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1687 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1688 .name = "AC97 Playback Volume",
1689 .info = aureon_ac97_vol_info,
1690 .get = aureon_ac97_vol_get,
1691 .put = aureon_ac97_vol_put,
1692 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1693 .tlv = { .p = db_scale_ac97_master }
1696 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1697 .name = "CD Playback Switch",
1698 .info = aureon_ac97_mute_info,
1699 .get = aureon_ac97_mute_get,
1700 .put = aureon_ac97_mute_put,
1701 .private_value = AC97_AUX
1704 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1705 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1706 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1707 .name = "CD Playback Volume",
1708 .info = aureon_ac97_vol_info,
1709 .get = aureon_ac97_vol_get,
1710 .put = aureon_ac97_vol_put,
1711 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1712 .tlv = { .p = db_scale_ac97_gain }
1715 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1716 .name = "Phono Playback Switch",
1717 .info = aureon_ac97_mute_info,
1718 .get = aureon_ac97_mute_get,
1719 .put = aureon_ac97_mute_put,
1720 .private_value = AC97_CD
1723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1724 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1725 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1726 .name = "Phono Playback Volume",
1727 .info = aureon_ac97_vol_info,
1728 .get = aureon_ac97_vol_get,
1729 .put = aureon_ac97_vol_put,
1730 .private_value = AC97_CD|AUREON_AC97_STEREO,
1731 .tlv = { .p = db_scale_ac97_gain }
1734 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1735 .name = "Line Playback Switch",
1736 .info = aureon_ac97_mute_info,
1737 .get = aureon_ac97_mute_get,
1738 .put = aureon_ac97_mute_put,
1739 .private_value = AC97_LINE
1742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1743 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1744 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1745 .name = "Line Playback Volume",
1746 .info = aureon_ac97_vol_info,
1747 .get = aureon_ac97_vol_get,
1748 .put = aureon_ac97_vol_put,
1749 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1750 .tlv = { .p = db_scale_ac97_gain }
1753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1754 .name = "Mic Playback Switch",
1755 .info = aureon_ac97_mute_info,
1756 .get = aureon_ac97_mute_get,
1757 .put = aureon_ac97_mute_put,
1758 .private_value = AC97_MIC
1761 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1762 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1763 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1764 .name = "Mic Playback Volume",
1765 .info = aureon_ac97_vol_info,
1766 .get = aureon_ac97_vol_get,
1767 .put = aureon_ac97_vol_put,
1768 .private_value = AC97_MIC,
1769 .tlv = { .p = db_scale_ac97_gain }
1772 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1773 .name = "Mic Boost (+20dB)",
1774 .info = aureon_ac97_micboost_info,
1775 .get = aureon_ac97_micboost_get,
1776 .put = aureon_ac97_micboost_put
1779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780 .name = "Aux Playback Switch",
1781 .info = aureon_ac97_mute_info,
1782 .get = aureon_ac97_mute_get,
1783 .put = aureon_ac97_mute_put,
1784 .private_value = AC97_VIDEO,
1787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1788 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1789 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1790 .name = "Aux Playback Volume",
1791 .info = aureon_ac97_vol_info,
1792 .get = aureon_ac97_vol_get,
1793 .put = aureon_ac97_vol_put,
1794 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1795 .tlv = { .p = db_scale_ac97_gain }
1798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1799 .name = "Aux Source",
1800 .info = aureon_universe_inmux_info,
1801 .get = aureon_universe_inmux_get,
1802 .put = aureon_universe_inmux_put
1807 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1809 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1810 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1811 .info = aureon_cs8415_mute_info,
1812 .get = aureon_cs8415_mute_get,
1813 .put = aureon_cs8415_mute_put
1816 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1817 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1818 .info = aureon_cs8415_mux_info,
1819 .get = aureon_cs8415_mux_get,
1820 .put = aureon_cs8415_mux_put,
1823 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1824 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1825 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1826 .info = aureon_cs8415_qsub_info,
1827 .get = aureon_cs8415_qsub_get,
1830 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1831 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1832 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1833 .info = aureon_cs8415_spdif_info,
1834 .get = aureon_cs8415_mask_get
1837 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1838 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1839 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1840 .info = aureon_cs8415_spdif_info,
1841 .get = aureon_cs8415_spdif_get
1844 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1845 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1846 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1847 .info = aureon_cs8415_rate_info,
1848 .get = aureon_cs8415_rate_get
1852 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1854 unsigned int i, counts;
1857 counts = ARRAY_SIZE(aureon_dac_controls);
1858 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1859 counts -= 2; /* no side */
1860 for (i = 0; i < counts; i++) {
1861 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1866 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1867 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1872 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1873 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1874 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1879 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1880 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1881 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1882 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1888 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1889 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1891 snd_ice1712_save_gpio_status(ice);
1892 id = aureon_cs8415_get(ice, CS8415_ID);
1894 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1895 else if ((id & 0x0F) != 0x01)
1896 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1898 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1899 struct snd_kcontrol *kctl;
1900 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1904 kctl->id.device = ice->pcm->device;
1907 snd_ice1712_restore_gpio_status(ice);
1915 * initialize the chip
1917 static int __devinit aureon_init(struct snd_ice1712 *ice)
1919 static const unsigned short wm_inits_aureon[] = {
1920 /* These come first to reduce init pop noise */
1921 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1922 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1923 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1925 0x18, 0x000, /* All power-up */
1927 0x16, 0x122, /* I2S, normal polarity, 24bit */
1928 0x17, 0x022, /* 256fs, slave mode */
1929 0x00, 0, /* DAC1 analog mute */
1930 0x01, 0, /* DAC2 analog mute */
1931 0x02, 0, /* DAC3 analog mute */
1932 0x03, 0, /* DAC4 analog mute */
1933 0x04, 0, /* DAC5 analog mute */
1934 0x05, 0, /* DAC6 analog mute */
1935 0x06, 0, /* DAC7 analog mute */
1936 0x07, 0, /* DAC8 analog mute */
1937 0x08, 0x100, /* master analog mute */
1938 0x09, 0xff, /* DAC1 digital full */
1939 0x0a, 0xff, /* DAC2 digital full */
1940 0x0b, 0xff, /* DAC3 digital full */
1941 0x0c, 0xff, /* DAC4 digital full */
1942 0x0d, 0xff, /* DAC5 digital full */
1943 0x0e, 0xff, /* DAC6 digital full */
1944 0x0f, 0xff, /* DAC7 digital full */
1945 0x10, 0xff, /* DAC8 digital full */
1946 0x11, 0x1ff, /* master digital full */
1947 0x12, 0x000, /* phase normal */
1948 0x13, 0x090, /* unmute DAC L/R */
1949 0x14, 0x000, /* all unmute */
1950 0x15, 0x000, /* no deemphasis, no ZFLG */
1951 0x19, 0x000, /* -12dB ADC/L */
1952 0x1a, 0x000, /* -12dB ADC/R */
1955 static const unsigned short wm_inits_prodigy[] = {
1957 /* These come first to reduce init pop noise */
1958 0x1b, 0x000, /* ADC Mux */
1959 0x1c, 0x009, /* Out Mux1 */
1960 0x1d, 0x009, /* Out Mux2 */
1962 0x18, 0x000, /* All power-up */
1964 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1965 0x17, 0x006, /* 128fs, slave mode */
1967 0x00, 0, /* DAC1 analog mute */
1968 0x01, 0, /* DAC2 analog mute */
1969 0x02, 0, /* DAC3 analog mute */
1970 0x03, 0, /* DAC4 analog mute */
1971 0x04, 0, /* DAC5 analog mute */
1972 0x05, 0, /* DAC6 analog mute */
1973 0x06, 0, /* DAC7 analog mute */
1974 0x07, 0, /* DAC8 analog mute */
1975 0x08, 0x100, /* master analog mute */
1977 0x09, 0x7f, /* DAC1 digital full */
1978 0x0a, 0x7f, /* DAC2 digital full */
1979 0x0b, 0x7f, /* DAC3 digital full */
1980 0x0c, 0x7f, /* DAC4 digital full */
1981 0x0d, 0x7f, /* DAC5 digital full */
1982 0x0e, 0x7f, /* DAC6 digital full */
1983 0x0f, 0x7f, /* DAC7 digital full */
1984 0x10, 0x7f, /* DAC8 digital full */
1985 0x11, 0x1FF, /* master digital full */
1987 0x12, 0x000, /* phase normal */
1988 0x13, 0x090, /* unmute DAC L/R */
1989 0x14, 0x000, /* all unmute */
1990 0x15, 0x000, /* no deemphasis, no ZFLG */
1992 0x19, 0x000, /* -12dB ADC/L */
1993 0x1a, 0x000, /* -12dB ADC/R */
1997 static const unsigned short cs_inits[] = {
1999 0x0180, /* no mute, OMCK output on RMCK pin */
2000 0x0201, /* S/PDIF source on RXP1 */
2001 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2005 const unsigned short *p;
2008 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2009 ice->num_total_dacs = 6;
2010 ice->num_total_adcs = 2;
2012 /* aureon 7.1 and prodigy 7.1 */
2013 ice->num_total_dacs = 8;
2014 ice->num_total_adcs = 2;
2017 /* to remeber the register values of CS8415 */
2018 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2021 ice->akm_codecs = 1;
2023 if ((err = aureon_ac97_init(ice)) != 0)
2026 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2028 /* reset the wm codec as the SPI mode */
2029 snd_ice1712_save_gpio_status(ice);
2030 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2032 tmp = snd_ice1712_gpio_read(ice);
2033 tmp &= ~AUREON_WM_RESET;
2034 snd_ice1712_gpio_write(ice, tmp);
2036 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2037 snd_ice1712_gpio_write(ice, tmp);
2039 tmp |= AUREON_WM_RESET;
2040 snd_ice1712_gpio_write(ice, tmp);
2043 /* initialize WM8770 codec */
2044 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2045 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2046 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2047 p = wm_inits_prodigy;
2049 p = wm_inits_aureon;
2050 for (; *p != (unsigned short)-1; p += 2)
2051 wm_put(ice, p[0], p[1]);
2053 /* initialize CS8415A codec */
2054 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2055 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2056 for (p = cs_inits; *p != (unsigned short)-1; p++)
2057 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2058 ice->spec.aureon.cs8415_mux = 1;
2060 aureon_set_headphone_amp(ice, 1);
2063 snd_ice1712_restore_gpio_status(ice);
2065 /* initialize PCA9554 pin directions & set default input*/
2066 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2067 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2069 ice->spec.aureon.master[0] = WM_VOL_MUTE;
2070 ice->spec.aureon.master[1] = WM_VOL_MUTE;
2071 for (i = 0; i < ice->num_total_dacs; i++) {
2072 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2073 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2081 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2082 * hence the driver needs to sets up it properly.
2085 static unsigned char aureon51_eeprom[] __devinitdata = {
2086 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2087 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2088 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2089 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2090 [ICE_EEP2_GPIO_DIR] = 0xff,
2091 [ICE_EEP2_GPIO_DIR1] = 0xff,
2092 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2093 [ICE_EEP2_GPIO_MASK] = 0x00,
2094 [ICE_EEP2_GPIO_MASK1] = 0x00,
2095 [ICE_EEP2_GPIO_MASK2] = 0x00,
2096 [ICE_EEP2_GPIO_STATE] = 0x00,
2097 [ICE_EEP2_GPIO_STATE1] = 0x00,
2098 [ICE_EEP2_GPIO_STATE2] = 0x00,
2101 static unsigned char aureon71_eeprom[] __devinitdata = {
2102 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2103 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2104 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2105 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2106 [ICE_EEP2_GPIO_DIR] = 0xff,
2107 [ICE_EEP2_GPIO_DIR1] = 0xff,
2108 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2109 [ICE_EEP2_GPIO_MASK] = 0x00,
2110 [ICE_EEP2_GPIO_MASK1] = 0x00,
2111 [ICE_EEP2_GPIO_MASK2] = 0x00,
2112 [ICE_EEP2_GPIO_STATE] = 0x00,
2113 [ICE_EEP2_GPIO_STATE1] = 0x00,
2114 [ICE_EEP2_GPIO_STATE2] = 0x00,
2116 #define prodigy71_eeprom aureon71_eeprom
2118 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2119 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2120 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2121 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2122 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2123 [ICE_EEP2_GPIO_DIR] = 0xff,
2124 [ICE_EEP2_GPIO_DIR1] = 0xff,
2125 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2126 [ICE_EEP2_GPIO_MASK] = 0x00,
2127 [ICE_EEP2_GPIO_MASK1] = 0x00,
2128 [ICE_EEP2_GPIO_MASK2] = 0x00,
2129 [ICE_EEP2_GPIO_STATE] = 0x00,
2130 [ICE_EEP2_GPIO_STATE1] = 0x00,
2131 [ICE_EEP2_GPIO_STATE2] = 0x00,
2133 #define prodigy71xt_eeprom prodigy71lt_eeprom
2136 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2138 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2139 .name = "Terratec Aureon 5.1-Sky",
2140 .model = "aureon51",
2141 .chip_init = aureon_init,
2142 .build_controls = aureon_add_controls,
2143 .eeprom_size = sizeof(aureon51_eeprom),
2144 .eeprom_data = aureon51_eeprom,
2145 .driver = "Aureon51",
2148 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2149 .name = "Terratec Aureon 7.1-Space",
2150 .model = "aureon71",
2151 .chip_init = aureon_init,
2152 .build_controls = aureon_add_controls,
2153 .eeprom_size = sizeof(aureon71_eeprom),
2154 .eeprom_data = aureon71_eeprom,
2155 .driver = "Aureon71",
2158 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2159 .name = "Terratec Aureon 7.1-Universe",
2160 .model = "universe",
2161 .chip_init = aureon_init,
2162 .build_controls = aureon_add_controls,
2163 .eeprom_size = sizeof(aureon71_eeprom),
2164 .eeprom_data = aureon71_eeprom,
2165 .driver = "Aureon71Univ", /* keep in 15 letters */
2168 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2169 .name = "Audiotrak Prodigy 7.1",
2170 .model = "prodigy71",
2171 .chip_init = aureon_init,
2172 .build_controls = aureon_add_controls,
2173 .eeprom_size = sizeof(prodigy71_eeprom),
2174 .eeprom_data = prodigy71_eeprom,
2175 .driver = "Prodigy71", /* should be identical with Aureon71 */
2178 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2179 .name = "Audiotrak Prodigy 7.1 LT",
2180 .model = "prodigy71lt",
2181 .chip_init = aureon_init,
2182 .build_controls = aureon_add_controls,
2183 .eeprom_size = sizeof(prodigy71lt_eeprom),
2184 .eeprom_data = prodigy71lt_eeprom,
2185 .driver = "Prodigy71LT",
2188 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2189 .name = "Audiotrak Prodigy 7.1 XT",
2190 .model = "prodigy71xt",
2191 .chip_init = aureon_init,
2192 .build_controls = aureon_add_controls,
2193 .eeprom_size = sizeof(prodigy71xt_eeprom),
2194 .eeprom_data = prodigy71xt_eeprom,
2195 .driver = "Prodigy71LT",
2197 { } /* terminator */