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