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