2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Terratec Aureon cards
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
26 * both wm and akm codecs are pretty similar, so we can integrate
27 * both controls in the future, once if wm codecs are reused in
30 * - DAC digital volumes are not implemented in the mixer.
31 * if they show better response than DAC analog volumes, we can use them
34 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
37 * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
38 * added 64x/128x oversampling switch (should be 64x only for 96khz)
39 * fixed some recording labels (still need to check the rest)
40 * recording is working probably thanks to correct wm8770 initialization
42 * version 0.5: Initial release:
43 * working: analog output, mixer, headphone amplifier switch
44 * not working: prety much everything else, at least i could verify that
45 * we have no digital output, no capture, pretty bad clicks and poops
46 * on mixer switch and other coll stuff.
50 #include <sound/driver.h>
52 #include <linux/delay.h>
53 #include <linux/interrupt.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <sound/core.h>
62 /* WM8770 registers */
63 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
64 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
65 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
66 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
67 #define WM_PHASE_SWAP 0x12 /* DAC phase */
68 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
69 #define WM_MUTE 0x14 /* mute controls */
70 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
71 #define WM_INT_CTRL 0x16 /* interface control */
72 #define WM_MASTER 0x17 /* master clock and mode */
73 #define WM_POWERDOWN 0x18 /* power-down controls */
74 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
75 #define WM_ADC_MUX 0x1b /* input MUX */
76 #define WM_OUT_MUX1 0x1c /* output MUX */
77 #define WM_OUT_MUX2 0x1e /* output MUX */
78 #define WM_RESET 0x1f /* software reset */
80 /* CS8415A registers */
81 #define CS8415_CTRL1 0x01
82 #define CS8415_CTRL2 0x02
83 #define CS8415_QSUB 0x14
84 #define CS8415_RATIO 0x1E
85 #define CS8415_C_BUFFER 0x20
86 #define CS8415_ID 0x7F
88 static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
91 /* Send address to XILINX chip */
92 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
93 snd_ice1712_gpio_write(ice, tmp);
95 tmp |= AUREON_AC97_ADDR;
96 snd_ice1712_gpio_write(ice, tmp);
98 tmp &= ~AUREON_AC97_ADDR;
99 snd_ice1712_gpio_write(ice, tmp);
102 /* Send low-order byte to XILINX chip */
103 tmp &= ~AUREON_AC97_DATA_MASK;
104 tmp |= val & AUREON_AC97_DATA_MASK;
105 snd_ice1712_gpio_write(ice, tmp);
107 tmp |= AUREON_AC97_DATA_LOW;
108 snd_ice1712_gpio_write(ice, tmp);
110 tmp &= ~AUREON_AC97_DATA_LOW;
111 snd_ice1712_gpio_write(ice, tmp);
114 /* Send high-order byte to XILINX chip */
115 tmp &= ~AUREON_AC97_DATA_MASK;
116 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
118 snd_ice1712_gpio_write(ice, tmp);
120 tmp |= AUREON_AC97_DATA_HIGH;
121 snd_ice1712_gpio_write(ice, tmp);
123 tmp &= ~AUREON_AC97_DATA_HIGH;
124 snd_ice1712_gpio_write(ice, tmp);
127 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
128 tmp |= AUREON_AC97_COMMIT;
129 snd_ice1712_gpio_write(ice, tmp);
131 tmp &= ~AUREON_AC97_COMMIT;
132 snd_ice1712_gpio_write(ice, tmp);
135 /* Store the data in out private buffer */
136 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
139 static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
141 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
145 * Initialize STAC9744 chip
147 static int aureon_ac97_init (ice1712_t *ice) {
149 static unsigned short ac97_defaults[] = {
173 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
174 snd_ice1712_gpio_write(ice, tmp);
177 tmp &= ~AUREON_AC97_RESET;
178 snd_ice1712_gpio_write(ice, tmp);
181 tmp |= AUREON_AC97_RESET;
182 snd_ice1712_gpio_write(ice, tmp);
185 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
186 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
187 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
189 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
194 #define AUREON_AC97_STEREO 0x80
197 * AC'97 volume controls
199 static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
201 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
202 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
203 uinfo->value.integer.min = 0;
204 uinfo->value.integer.max = 31;
208 static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
210 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
213 down(&ice->gpio_mutex);
215 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
216 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
217 if (kcontrol->private_value & AUREON_AC97_STEREO)
218 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
220 up(&ice->gpio_mutex);
224 static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
226 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
227 unsigned short ovol, nvol;
230 snd_ice1712_save_gpio_status(ice);
232 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
233 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
234 if (kcontrol->private_value & AUREON_AC97_STEREO)
235 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
236 nvol |= ovol & ~0x1F1F;
238 if ((change = (ovol != nvol)))
239 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
241 snd_ice1712_restore_gpio_status(ice);
247 * AC'97 mute controls
249 #define aureon_ac97_mute_info aureon_mono_bool_info
251 static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
253 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
255 down(&ice->gpio_mutex);
257 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
259 up(&ice->gpio_mutex);
263 static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
265 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
266 unsigned short ovol, nvol;
269 snd_ice1712_save_gpio_status(ice);
271 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
272 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
274 if ((change = (ovol != nvol)))
275 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
277 snd_ice1712_restore_gpio_status(ice);
283 * AC'97 mute controls
285 #define aureon_ac97_micboost_info aureon_mono_bool_info
287 static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
289 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
291 down(&ice->gpio_mutex);
293 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
295 up(&ice->gpio_mutex);
299 static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
301 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
302 unsigned short ovol, nvol;
305 snd_ice1712_save_gpio_status(ice);
307 ovol = aureon_ac97_read(ice, AC97_MIC);
308 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
310 if ((change = (ovol != nvol)))
311 aureon_ac97_write(ice, AC97_MIC, nvol);
313 snd_ice1712_restore_gpio_status(ice);
319 * write data in the SPI mode
321 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
326 tmp = snd_ice1712_gpio_read(ice);
328 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
329 AUREON_WM_CS|AUREON_CS8415_CS));
332 snd_ice1712_gpio_write(ice, tmp);
335 for (i = bits - 1; i >= 0; i--) {
336 tmp &= ~AUREON_SPI_CLK;
337 snd_ice1712_gpio_write(ice, tmp);
340 tmp |= AUREON_SPI_MOSI;
342 tmp &= ~AUREON_SPI_MOSI;
343 snd_ice1712_gpio_write(ice, tmp);
345 tmp |= AUREON_SPI_CLK;
346 snd_ice1712_gpio_write(ice, tmp);
350 tmp &= ~AUREON_SPI_CLK;
352 snd_ice1712_gpio_write(ice, tmp);
354 tmp |= AUREON_SPI_CLK;
355 snd_ice1712_gpio_write(ice, tmp);
360 * Read data in SPI mode
362 static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
366 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
367 snd_ice1712_gpio_write(ice, tmp);
369 snd_ice1712_gpio_write(ice, tmp);
372 for (i=bits-1; i>=0; i--) {
374 tmp |= AUREON_SPI_MOSI;
376 tmp &= ~AUREON_SPI_MOSI;
377 snd_ice1712_gpio_write(ice, tmp);
380 tmp |= AUREON_SPI_CLK;
381 snd_ice1712_gpio_write(ice, tmp);
384 tmp &= ~AUREON_SPI_CLK;
385 snd_ice1712_gpio_write(ice, tmp);
389 for (j=0; j<size; j++) {
390 unsigned char outdata = 0;
391 for (i=7; i>=0; i--) {
392 tmp = snd_ice1712_gpio_read(ice);
394 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
397 tmp |= AUREON_SPI_CLK;
398 snd_ice1712_gpio_write(ice, tmp);
401 tmp &= ~AUREON_SPI_CLK;
402 snd_ice1712_gpio_write(ice, tmp);
409 snd_ice1712_gpio_write(ice, tmp);
412 static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) {
414 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
415 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
419 static void aureon_cs8415_read(ice1712_t *ice, int reg, unsigned char *buffer, int size) {
420 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
421 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
424 static void aureon_cs8415_put(ice1712_t *ice, int reg, unsigned char val) {
425 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
429 * get the current register value of WM codec
431 static unsigned short wm_get(ice1712_t *ice, int reg)
434 return ((unsigned short)ice->akm[0].images[reg] << 8) |
435 ice->akm[0].images[reg + 1];
439 * set the register value of WM codec
441 static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
443 aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
447 * set the register value of WM codec and remember it
449 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
451 wm_put_nocache(ice, reg, val);
453 ice->akm[0].images[reg] = val >> 8;
454 ice->akm[0].images[reg + 1] = val;
459 static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
461 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
463 uinfo->value.integer.min = 0;
464 uinfo->value.integer.max = 1;
469 * AC'97 master playback mute controls (Mute on WM8770 chip)
471 #define aureon_ac97_mmute_info aureon_mono_bool_info
473 static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
475 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
477 down(&ice->gpio_mutex);
479 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
481 up(&ice->gpio_mutex);
485 static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
486 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
487 unsigned short ovol, nvol;
490 snd_ice1712_save_gpio_status(ice);
492 ovol = wm_get(ice, WM_OUT_MUX1);
493 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
494 if ((change = (ovol != nvol)))
495 wm_put(ice, WM_OUT_MUX1, nvol);
497 snd_ice1712_restore_gpio_status(ice);
503 * Logarithmic volume values for WM8770
504 * Computed as 20 * Log10(255 / x)
506 static unsigned char wm_vol[256] = {
507 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
508 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
509 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
510 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
511 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
512 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,
513 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,
514 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,
515 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,
516 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,
517 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,
521 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
522 #define WM_VOL_MUTE 0x8000
524 static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
528 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
531 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
533 wm_put(ice, index, nvol);
534 wm_put_nocache(ice, index, 0x180 | nvol);
540 #define wm_pcm_mute_info aureon_mono_bool_info
542 static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
544 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
546 down(&ice->gpio_mutex);
547 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
548 up(&ice->gpio_mutex);
552 static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
554 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
555 unsigned short nval, oval;
558 snd_ice1712_save_gpio_status(ice);
559 oval = wm_get(ice, WM_MUTE);
560 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
561 if ((change = (nval != oval)))
562 wm_put(ice, WM_MUTE, nval);
563 snd_ice1712_restore_gpio_status(ice);
569 * Master volume attenuation mixer control
571 static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
573 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
575 uinfo->value.integer.min = 0;
576 uinfo->value.integer.max = WM_VOL_MAX;
580 static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
582 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
585 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
589 static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
591 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
594 snd_ice1712_save_gpio_status(ice);
595 for (ch = 0; ch < 2; ch++) {
596 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
598 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
599 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
600 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
601 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
602 ice->spec.aureon.vol[dac + ch],
603 ice->spec.aureon.master[ch]);
607 snd_ice1712_restore_gpio_status(ice);
612 * DAC volume attenuation mixer control
614 static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
616 int voices = kcontrol->private_value >> 8;
617 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
618 uinfo->count = voices;
619 uinfo->value.integer.min = 0; /* mute (-101dB) */
620 uinfo->value.integer.max = 0x7F; /* 0dB */
624 static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
626 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
629 voices = kcontrol->private_value >> 8;
630 ofs = kcontrol->private_value & 0xff;
631 for (i = 0; i < voices; i++)
632 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
636 static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
638 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
639 int i, idx, ofs, voices;
642 voices = kcontrol->private_value >> 8;
643 ofs = kcontrol->private_value & 0xff;
644 snd_ice1712_save_gpio_status(ice);
645 for (i = 0; i < voices; i++) {
646 idx = WM_DAC_ATTEN + ofs + i;
647 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
648 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
649 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
650 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
651 ice->spec.aureon.master[i]);
655 snd_ice1712_restore_gpio_status(ice);
660 * WM8770 mute control
662 static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
663 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
664 uinfo->count = kcontrol->private_value >> 8;
665 uinfo->value.integer.min = 0;
666 uinfo->value.integer.max = 1;
670 static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
672 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
675 voices = kcontrol->private_value >> 8;
676 ofs = kcontrol->private_value & 0xFF;
678 for (i = 0; i < voices; i++)
679 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
683 static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
685 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
686 int change = 0, voices, ofs, i;
688 voices = kcontrol->private_value >> 8;
689 ofs = kcontrol->private_value & 0xFF;
691 snd_ice1712_save_gpio_status(ice);
692 for (i = 0; i < voices; i++) {
693 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
694 if (ucontrol->value.integer.value[i] != val) {
695 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
696 ice->spec.aureon.vol[ofs + i] |=
697 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
698 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
699 ice->spec.aureon.master[i]);
703 snd_ice1712_restore_gpio_status(ice);
709 * WM8770 master mute control
711 static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
712 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
714 uinfo->value.integer.min = 0;
715 uinfo->value.integer.max = 1;
719 static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
721 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
723 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
724 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
728 static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
730 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
733 snd_ice1712_save_gpio_status(ice);
734 for (i = 0; i < 2; i++) {
735 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
736 if (ucontrol->value.integer.value[i] != val) {
738 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
739 ice->spec.aureon.master[i] |=
740 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
741 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
742 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
743 ice->spec.aureon.vol[dac + i],
744 ice->spec.aureon.master[i]);
748 snd_ice1712_restore_gpio_status(ice);
753 /* digital master volume */
755 #define PCM_RES 128 /* -64dB */
756 #define PCM_MIN (PCM_0dB - PCM_RES)
757 static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
759 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
761 uinfo->value.integer.min = 0; /* mute (-64dB) */
762 uinfo->value.integer.max = PCM_RES; /* 0dB */
766 static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
768 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
771 down(&ice->gpio_mutex);
772 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
773 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
774 ucontrol->value.integer.value[0] = val;
775 up(&ice->gpio_mutex);
779 static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
781 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
782 unsigned short ovol, nvol;
785 snd_ice1712_save_gpio_status(ice);
786 nvol = ucontrol->value.integer.value[0];
787 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
788 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
790 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
791 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
794 snd_ice1712_restore_gpio_status(ice);
801 static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
803 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
805 uinfo->value.integer.min = 0;
806 uinfo->value.integer.max = 1;
810 static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
812 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
816 down(&ice->gpio_mutex);
817 for (i = 0; i < 2; i++) {
818 val = wm_get(ice, WM_ADC_GAIN + i);
819 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
821 up(&ice->gpio_mutex);
825 static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
827 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
828 unsigned short new, old;
831 snd_ice1712_save_gpio_status(ice);
832 for (i = 0; i < 2; i++) {
833 old = wm_get(ice, WM_ADC_GAIN + i);
834 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
836 wm_put(ice, WM_ADC_GAIN + i, new);
840 snd_ice1712_restore_gpio_status(ice);
846 * ADC gain mixer control
848 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
850 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
852 uinfo->value.integer.min = 0; /* -12dB */
853 uinfo->value.integer.max = 0x1f; /* 19dB */
857 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
859 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
863 down(&ice->gpio_mutex);
864 for (i = 0; i < 2; i++) {
865 idx = WM_ADC_GAIN + i;
866 vol = wm_get(ice, idx) & 0x1f;
867 ucontrol->value.integer.value[i] = vol;
869 up(&ice->gpio_mutex);
873 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
875 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
877 unsigned short ovol, nvol;
880 snd_ice1712_save_gpio_status(ice);
881 for (i = 0; i < 2; i++) {
882 idx = WM_ADC_GAIN + i;
883 nvol = ucontrol->value.integer.value[i];
884 ovol = wm_get(ice, idx);
885 if ((ovol & 0x1f) != nvol) {
886 wm_put(ice, idx, nvol | (ovol & ~0x1f));
890 snd_ice1712_restore_gpio_status(ice);
895 * ADC input mux mixer control
897 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
899 static char *texts[] = {
906 static char *universe_texts[] = {
916 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
918 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
920 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
921 uinfo->value.enumerated.items = 8;
922 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
923 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
924 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
927 uinfo->value.enumerated.items = 5;
928 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
929 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
930 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
935 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
937 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
940 down(&ice->gpio_mutex);
941 val = wm_get(ice, WM_ADC_MUX);
942 ucontrol->value.integer.value[0] = val & 7;
943 ucontrol->value.integer.value[1] = (val >> 4) & 7;
944 up(&ice->gpio_mutex);
948 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
950 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
951 unsigned short oval, nval;
954 snd_ice1712_save_gpio_status(ice);
955 oval = wm_get(ice, WM_ADC_MUX);
957 nval |= ucontrol->value.integer.value[0] & 7;
958 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
959 change = (oval != nval);
961 wm_put(ice, WM_ADC_MUX, nval);
962 snd_ice1712_restore_gpio_status(ice);
969 static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
971 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
972 static char *aureon_texts[] = {
976 static char *prodigy_texts[] = {
980 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
982 uinfo->value.enumerated.items = 2;
983 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
984 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
985 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
986 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
988 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
992 static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
994 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
996 //snd_ice1712_save_gpio_status(ice);
997 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
998 ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
999 //snd_ice1712_restore_gpio_status(ice);
1003 static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
1005 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1006 unsigned short oval, nval;
1009 snd_ice1712_save_gpio_status(ice);
1010 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1011 nval = oval & ~0x07;
1012 nval |= ucontrol->value.integer.value[0] & 7;
1013 change = (oval != nval);
1015 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1016 snd_ice1712_restore_gpio_status(ice);
1017 ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
1021 static int aureon_cs8415_rate_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1023 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1025 uinfo->value.integer.min = 0;
1026 uinfo->value.integer.max = 192000;
1030 static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1032 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1033 unsigned char ratio;
1034 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1035 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1042 static int aureon_cs8415_mute_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1044 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1049 static int aureon_cs8415_mute_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1051 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1052 snd_ice1712_save_gpio_status(ice);
1053 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1054 snd_ice1712_restore_gpio_status(ice);
1058 static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1060 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1061 unsigned char oval, nval;
1063 snd_ice1712_save_gpio_status(ice);
1064 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1065 if (ucontrol->value.integer.value[0])
1066 nval = oval & ~0x20;
1069 if ((change = (oval != nval)))
1070 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1071 snd_ice1712_restore_gpio_status(ice);
1076 * CS8415A Q-Sub info
1078 static int aureon_cs8415_qsub_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1079 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1084 static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1085 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1087 snd_ice1712_save_gpio_status(ice);
1088 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1089 snd_ice1712_restore_gpio_status(ice);
1094 static int aureon_cs8415_spdif_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1095 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1100 static int aureon_cs8415_mask_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1101 memset(ucontrol->value.iec958.status, 0xFF, 24);
1105 static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1106 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1108 snd_ice1712_save_gpio_status(ice);
1109 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1110 snd_ice1712_restore_gpio_status(ice);
1115 * Headphone Amplifier
1117 static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
1119 unsigned int tmp, tmp2;
1121 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1123 tmp |= AUREON_HP_SEL;
1125 tmp &= ~ AUREON_HP_SEL;
1127 snd_ice1712_gpio_write(ice, tmp);
1133 static int aureon_get_headphone_amp(ice1712_t *ice)
1135 unsigned int tmp = snd_ice1712_gpio_read(ice);
1137 return ( tmp & AUREON_HP_SEL )!= 0;
1140 #define aureon_hpamp_info aureon_mono_bool_info
1142 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1144 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1146 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1151 static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1153 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1155 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1162 #define aureon_deemp_info aureon_mono_bool_info
1164 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1166 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1167 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1171 static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1173 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1175 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1176 if (ucontrol->value.integer.value[0])
1180 if (temp != temp2) {
1181 wm_put(ice, WM_DAC_CTRL2, temp);
1190 static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
1192 static char *texts[2] = { "128x", "64x" };
1194 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1196 uinfo->value.enumerated.items = 2;
1198 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1199 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1205 static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1207 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1208 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1212 static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1215 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1217 temp2 = temp = wm_get(ice, WM_MASTER);
1219 if (ucontrol->value.enumerated.item[0])
1224 if (temp != temp2) {
1225 wm_put(ice, WM_MASTER, temp);
1235 static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
1237 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1238 .name = "Master Playback Switch",
1239 .info = wm_master_mute_info,
1240 .get = wm_master_mute_get,
1241 .put = wm_master_mute_put
1244 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1245 .name = "Master Playback Volume",
1246 .info = wm_master_vol_info,
1247 .get = wm_master_vol_get,
1248 .put = wm_master_vol_put
1251 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1252 .name = "Front Playback Switch",
1253 .info = wm_mute_info,
1256 .private_value = (2 << 8) | 0
1259 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1260 .name = "Front Playback Volume",
1261 .info = wm_vol_info,
1264 .private_value = (2 << 8) | 0
1267 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1268 .name = "Rear Playback Switch",
1269 .info = wm_mute_info,
1272 .private_value = (2 << 8) | 2
1275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276 .name = "Rear Playback Volume",
1277 .info = wm_vol_info,
1280 .private_value = (2 << 8) | 2
1283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1284 .name = "Center Playback Switch",
1285 .info = wm_mute_info,
1288 .private_value = (1 << 8) | 4
1291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1292 .name = "Center Playback Volume",
1293 .info = wm_vol_info,
1296 .private_value = (1 << 8) | 4
1299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1300 .name = "LFE Playback Switch",
1301 .info = wm_mute_info,
1304 .private_value = (1 << 8) | 5
1307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308 .name = "LFE Playback Volume",
1309 .info = wm_vol_info,
1312 .private_value = (1 << 8) | 5
1315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1316 .name = "Side Playback Switch",
1317 .info = wm_mute_info,
1320 .private_value = (2 << 8) | 6
1323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1324 .name = "Side Playback Volume",
1325 .info = wm_vol_info,
1328 .private_value = (2 << 8) | 6
1332 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
1334 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1335 .name = "PCM Playback Switch",
1336 .info = wm_pcm_mute_info,
1337 .get = wm_pcm_mute_get,
1338 .put = wm_pcm_mute_put
1341 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1342 .name = "PCM Playback Volume",
1343 .info = wm_pcm_vol_info,
1344 .get = wm_pcm_vol_get,
1345 .put = wm_pcm_vol_put
1348 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1349 .name = "Capture Switch",
1350 .info = wm_adc_mute_info,
1351 .get = wm_adc_mute_get,
1352 .put = wm_adc_mute_put,
1355 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1356 .name = "Capture Volume",
1357 .info = wm_adc_vol_info,
1358 .get = wm_adc_vol_get,
1359 .put = wm_adc_vol_put
1362 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1363 .name = "Capture Source",
1364 .info = wm_adc_mux_info,
1365 .get = wm_adc_mux_get,
1366 .put = wm_adc_mux_put,
1370 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1371 .name = "External Amplifier",
1372 .info = aureon_hpamp_info,
1373 .get = aureon_hpamp_get,
1374 .put = aureon_hpamp_put
1377 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1378 .name = "DAC Deemphasis Switch",
1379 .info = aureon_deemp_info,
1380 .get = aureon_deemp_get,
1381 .put = aureon_deemp_put
1384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1385 .name = "ADC Oversampling",
1386 .info = aureon_oversampling_info,
1387 .get = aureon_oversampling_get,
1388 .put = aureon_oversampling_put
1392 static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395 .name = "AC97 Playback Switch",
1396 .info = aureon_ac97_mmute_info,
1397 .get = aureon_ac97_mmute_get,
1398 .put = aureon_ac97_mmute_put,
1399 .private_value = AC97_MASTER
1402 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1403 .name = "AC97 Playback Volume",
1404 .info = aureon_ac97_vol_info,
1405 .get = aureon_ac97_vol_get,
1406 .put = aureon_ac97_vol_put,
1407 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1411 .name = "CD Playback Switch",
1412 .info = aureon_ac97_mute_info,
1413 .get = aureon_ac97_mute_get,
1414 .put = aureon_ac97_mute_put,
1415 .private_value = AC97_CD
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .name = "CD Playback Volume",
1420 .info = aureon_ac97_vol_info,
1421 .get = aureon_ac97_vol_get,
1422 .put = aureon_ac97_vol_put,
1423 .private_value = AC97_CD|AUREON_AC97_STEREO
1426 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1427 .name = "Aux Playback Switch",
1428 .info = aureon_ac97_mute_info,
1429 .get = aureon_ac97_mute_get,
1430 .put = aureon_ac97_mute_put,
1431 .private_value = AC97_AUX,
1434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1435 .name = "Aux Playback Volume",
1436 .info = aureon_ac97_vol_info,
1437 .get = aureon_ac97_vol_get,
1438 .put = aureon_ac97_vol_put,
1439 .private_value = AC97_AUX|AUREON_AC97_STEREO
1442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443 .name = "Line Playback Switch",
1444 .info = aureon_ac97_mute_info,
1445 .get = aureon_ac97_mute_get,
1446 .put = aureon_ac97_mute_put,
1447 .private_value = AC97_LINE
1450 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451 .name = "Line Playback Volume",
1452 .info = aureon_ac97_vol_info,
1453 .get = aureon_ac97_vol_get,
1454 .put = aureon_ac97_vol_put,
1455 .private_value = AC97_LINE|AUREON_AC97_STEREO
1458 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1459 .name = "Mic Playback Switch",
1460 .info = aureon_ac97_mute_info,
1461 .get = aureon_ac97_mute_get,
1462 .put = aureon_ac97_mute_put,
1463 .private_value = AC97_MIC
1466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467 .name = "Mic Playback Volume",
1468 .info = aureon_ac97_vol_info,
1469 .get = aureon_ac97_vol_get,
1470 .put = aureon_ac97_vol_put,
1471 .private_value = AC97_MIC
1474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475 .name = "Mic Boost (+20dB)",
1476 .info = aureon_ac97_micboost_info,
1477 .get = aureon_ac97_micboost_get,
1478 .put = aureon_ac97_micboost_put
1482 static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = {
1484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485 .name = "AC97 Playback Switch",
1486 .info = aureon_ac97_mmute_info,
1487 .get = aureon_ac97_mmute_get,
1488 .put = aureon_ac97_mmute_put,
1489 .private_value = AC97_MASTER
1492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1493 .name = "AC97 Playback Volume",
1494 .info = aureon_ac97_vol_info,
1495 .get = aureon_ac97_vol_get,
1496 .put = aureon_ac97_vol_put,
1497 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1500 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1501 .name = "CD Playback Switch",
1502 .info = aureon_ac97_mute_info,
1503 .get = aureon_ac97_mute_get,
1504 .put = aureon_ac97_mute_put,
1505 .private_value = AC97_AUX
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "CD Playback Volume",
1510 .info = aureon_ac97_vol_info,
1511 .get = aureon_ac97_vol_get,
1512 .put = aureon_ac97_vol_put,
1513 .private_value = AC97_AUX|AUREON_AC97_STEREO
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .name = "Phono Playback Switch",
1518 .info = aureon_ac97_mute_info,
1519 .get = aureon_ac97_mute_get,
1520 .put = aureon_ac97_mute_put,
1521 .private_value = AC97_CD,
1524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1525 .name = "Phono Playback Volume",
1526 .info = aureon_ac97_vol_info,
1527 .get = aureon_ac97_vol_get,
1528 .put = aureon_ac97_vol_put,
1529 .private_value = AC97_CD|AUREON_AC97_STEREO
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533 .name = "Line Playback Switch",
1534 .info = aureon_ac97_mute_info,
1535 .get = aureon_ac97_mute_get,
1536 .put = aureon_ac97_mute_put,
1537 .private_value = AC97_LINE
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Line Playback Volume",
1542 .info = aureon_ac97_vol_info,
1543 .get = aureon_ac97_vol_get,
1544 .put = aureon_ac97_vol_put,
1545 .private_value = AC97_LINE|AUREON_AC97_STEREO
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "Mic Playback Switch",
1550 .info = aureon_ac97_mute_info,
1551 .get = aureon_ac97_mute_get,
1552 .put = aureon_ac97_mute_put,
1553 .private_value = AC97_MIC
1556 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557 .name = "Mic Playback Volume",
1558 .info = aureon_ac97_vol_info,
1559 .get = aureon_ac97_vol_get,
1560 .put = aureon_ac97_vol_put,
1561 .private_value = AC97_MIC
1564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1565 .name = "Mic Boost (+20dB)",
1566 .info = aureon_ac97_micboost_info,
1567 .get = aureon_ac97_micboost_get,
1568 .put = aureon_ac97_micboost_put
1571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572 .name = "Aux Playback Switch",
1573 .info = aureon_ac97_mute_info,
1574 .get = aureon_ac97_mute_get,
1575 .put = aureon_ac97_mute_put,
1576 .private_value = AC97_VIDEO,
1579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1580 .name = "Aux Playback Volume",
1581 .info = aureon_ac97_vol_info,
1582 .get = aureon_ac97_vol_get,
1583 .put = aureon_ac97_vol_put,
1584 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1589 static snd_kcontrol_new_t cs8415_controls[] __devinitdata = {
1591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1593 .info = aureon_cs8415_mute_info,
1594 .get = aureon_cs8415_mute_get,
1595 .put = aureon_cs8415_mute_put
1598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1599 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1600 .info = aureon_cs8415_mux_info,
1601 .get = aureon_cs8415_mux_get,
1602 .put = aureon_cs8415_mux_put,
1605 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1606 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1607 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1608 .info = aureon_cs8415_qsub_info,
1609 .get = aureon_cs8415_qsub_get,
1612 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1613 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1614 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1615 .info = aureon_cs8415_spdif_info,
1616 .get = aureon_cs8415_mask_get
1619 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1620 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1621 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1622 .info = aureon_cs8415_spdif_info,
1623 .get = aureon_cs8415_spdif_get
1626 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1627 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1628 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1629 .info = aureon_cs8415_rate_info,
1630 .get = aureon_cs8415_rate_get
1635 static int __devinit aureon_add_controls(ice1712_t *ice)
1637 unsigned int i, counts;
1640 counts = ARRAY_SIZE(aureon_dac_controls);
1641 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1642 counts -= 2; /* no side */
1643 for (i = 0; i < counts; i++) {
1644 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1649 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1650 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1655 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1656 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1657 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1663 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1664 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1672 snd_ice1712_save_gpio_status(ice);
1673 id = aureon_cs8415_get(ice, CS8415_ID);
1675 snd_printk("No CS8415 chip. Skipping CS8415 controls.\n");
1676 else if ((id & 0x0F) != 0x01)
1677 snd_printk("Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1679 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1680 snd_kcontrol_t *kctl;
1681 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1685 kctl->id.device = ice->pcm->device;
1688 snd_ice1712_restore_gpio_status(ice);
1696 * initialize the chip
1698 static int __devinit aureon_init(ice1712_t *ice)
1700 static unsigned short wm_inits_aureon[] = {
1701 /* These come first to reduce init pop noise */
1702 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1703 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1704 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1706 0x18, 0x000, /* All power-up */
1708 0x16, 0x122, /* I2S, normal polarity, 24bit */
1709 0x17, 0x022, /* 256fs, slave mode */
1710 0x00, 0, /* DAC1 analog mute */
1711 0x01, 0, /* DAC2 analog mute */
1712 0x02, 0, /* DAC3 analog mute */
1713 0x03, 0, /* DAC4 analog mute */
1714 0x04, 0, /* DAC5 analog mute */
1715 0x05, 0, /* DAC6 analog mute */
1716 0x06, 0, /* DAC7 analog mute */
1717 0x07, 0, /* DAC8 analog mute */
1718 0x08, 0x100, /* master analog mute */
1719 0x09, 0xff, /* DAC1 digital full */
1720 0x0a, 0xff, /* DAC2 digital full */
1721 0x0b, 0xff, /* DAC3 digital full */
1722 0x0c, 0xff, /* DAC4 digital full */
1723 0x0d, 0xff, /* DAC5 digital full */
1724 0x0e, 0xff, /* DAC6 digital full */
1725 0x0f, 0xff, /* DAC7 digital full */
1726 0x10, 0xff, /* DAC8 digital full */
1727 0x11, 0x1ff, /* master digital full */
1728 0x12, 0x000, /* phase normal */
1729 0x13, 0x090, /* unmute DAC L/R */
1730 0x14, 0x000, /* all unmute */
1731 0x15, 0x000, /* no deemphasis, no ZFLG */
1732 0x19, 0x000, /* -12dB ADC/L */
1733 0x1a, 0x000, /* -12dB ADC/R */
1736 static unsigned short wm_inits_prodigy[] = {
1738 /* These come first to reduce init pop noise */
1739 0x1b, 0x000, /* ADC Mux */
1740 0x1c, 0x009, /* Out Mux1 */
1741 0x1d, 0x009, /* Out Mux2 */
1743 0x18, 0x000, /* All power-up */
1745 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1746 0x17, 0x006, /* 128fs, slave mode */
1748 0x00, 0, /* DAC1 analog mute */
1749 0x01, 0, /* DAC2 analog mute */
1750 0x02, 0, /* DAC3 analog mute */
1751 0x03, 0, /* DAC4 analog mute */
1752 0x04, 0, /* DAC5 analog mute */
1753 0x05, 0, /* DAC6 analog mute */
1754 0x06, 0, /* DAC7 analog mute */
1755 0x07, 0, /* DAC8 analog mute */
1756 0x08, 0x100, /* master analog mute */
1758 0x09, 0x7f, /* DAC1 digital full */
1759 0x0a, 0x7f, /* DAC2 digital full */
1760 0x0b, 0x7f, /* DAC3 digital full */
1761 0x0c, 0x7f, /* DAC4 digital full */
1762 0x0d, 0x7f, /* DAC5 digital full */
1763 0x0e, 0x7f, /* DAC6 digital full */
1764 0x0f, 0x7f, /* DAC7 digital full */
1765 0x10, 0x7f, /* DAC8 digital full */
1766 0x11, 0x1FF, /* master digital full */
1768 0x12, 0x000, /* phase normal */
1769 0x13, 0x090, /* unmute DAC L/R */
1770 0x14, 0x000, /* all unmute */
1771 0x15, 0x000, /* no deemphasis, no ZFLG */
1773 0x19, 0x000, /* -12dB ADC/L */
1774 0x1a, 0x000, /* -12dB ADC/R */
1778 static unsigned short cs_inits[] = {
1780 0x0180, /* no mute, OMCK output on RMCK pin */
1781 0x0201, /* S/PDIF source on RXP1 */
1782 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1789 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1790 ice->num_total_dacs = 6;
1791 ice->num_total_adcs = 2;
1793 /* aureon 7.1 and prodigy 7.1 */
1794 ice->num_total_dacs = 8;
1795 ice->num_total_adcs = 2;
1798 /* to remeber the register values of CS8415 */
1799 ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
1802 ice->akm_codecs = 1;
1804 if ((err = aureon_ac97_init(ice)) != 0)
1807 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1809 /* reset the wm codec as the SPI mode */
1810 snd_ice1712_save_gpio_status(ice);
1811 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1813 tmp = snd_ice1712_gpio_read(ice);
1814 tmp &= ~AUREON_WM_RESET;
1815 snd_ice1712_gpio_write(ice, tmp);
1817 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1818 snd_ice1712_gpio_write(ice, tmp);
1820 tmp |= AUREON_WM_RESET;
1821 snd_ice1712_gpio_write(ice, tmp);
1824 /* initialize WM8770 codec */
1825 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1826 p = wm_inits_prodigy;
1828 p = wm_inits_aureon;
1829 for (; *p != (unsigned short)-1; p += 2)
1830 wm_put(ice, p[0], p[1]);
1832 /* initialize CS8415A codec */
1833 for (p = cs_inits; *p != (unsigned short)-1; p++)
1834 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
1835 ice->spec.aureon.cs8415_mux = 1;
1837 aureon_set_headphone_amp(ice, 1);
1839 snd_ice1712_restore_gpio_status(ice);
1841 ice->spec.aureon.master[0] = WM_VOL_MUTE;
1842 ice->spec.aureon.master[1] = WM_VOL_MUTE;
1843 for (i = 0; i < ice->num_total_dacs; i++) {
1844 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1845 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1853 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1854 * hence the driver needs to sets up it properly.
1857 static unsigned char aureon51_eeprom[] __devinitdata = {
1858 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1859 0x80, /* ACLINK: I2S */
1860 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1861 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1862 0xff, /* GPIO_DIR */
1863 0xff, /* GPIO_DIR1 */
1864 0x5f, /* GPIO_DIR2 */
1865 0x00, /* GPIO_MASK */
1866 0x00, /* GPIO_MASK1 */
1867 0x00, /* GPIO_MASK2 */
1868 0x00, /* GPIO_STATE */
1869 0x00, /* GPIO_STATE1 */
1870 0x00, /* GPIO_STATE2 */
1873 static unsigned char aureon71_eeprom[] __devinitdata = {
1874 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1875 0x80, /* ACLINK: I2S */
1876 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1877 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1878 0xff, /* GPIO_DIR */
1879 0xff, /* GPIO_DIR1 */
1880 0x5f, /* GPIO_DIR2 */
1881 0x00, /* GPIO_MASK */
1882 0x00, /* GPIO_MASK1 */
1883 0x00, /* GPIO_MASK2 */
1884 0x00, /* GPIO_STATE */
1885 0x00, /* GPIO_STATE1 */
1886 0x00, /* GPIO_STATE2 */
1889 static unsigned char prodigy71_eeprom[] __devinitdata = {
1890 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1891 0x80, /* ACLINK: I2S */
1892 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1893 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1894 0xff, /* GPIO_DIR */
1895 0xff, /* GPIO_DIR1 */
1896 0x5f, /* GPIO_DIR2 */
1897 0x00, /* GPIO_MASK */
1898 0x00, /* GPIO_MASK1 */
1899 0x00, /* GPIO_MASK2 */
1900 0x00, /* GPIO_STATE */
1901 0x00, /* GPIO_STATE1 */
1902 0x00, /* GPIO_STATE2 */
1906 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1908 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1909 .name = "Terratec Aureon 5.1-Sky",
1910 .model = "aureon51",
1911 .chip_init = aureon_init,
1912 .build_controls = aureon_add_controls,
1913 .eeprom_size = sizeof(aureon51_eeprom),
1914 .eeprom_data = aureon51_eeprom,
1915 .driver = "Aureon51",
1918 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1919 .name = "Terratec Aureon 7.1-Space",
1920 .model = "aureon71",
1921 .chip_init = aureon_init,
1922 .build_controls = aureon_add_controls,
1923 .eeprom_size = sizeof(aureon71_eeprom),
1924 .eeprom_data = aureon71_eeprom,
1925 .driver = "Aureon71",
1928 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1929 .name = "Terratec Aureon 7.1-Universe",
1930 .model = "universe",
1931 .chip_init = aureon_init,
1932 .build_controls = aureon_add_controls,
1933 .eeprom_size = sizeof(aureon71_eeprom),
1934 .eeprom_data = aureon71_eeprom,
1935 .driver = "Aureon71Universe",
1938 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1939 .name = "Audiotrak Prodigy 7.1",
1940 .model = "prodigy71",
1941 .chip_init = aureon_init,
1942 .build_controls = aureon_add_controls,
1943 .eeprom_size = sizeof(prodigy71_eeprom),
1944 .eeprom_data = prodigy71_eeprom,
1945 .driver = "Prodigy71", /* should be identical with Aureon71 */
1947 { } /* terminator */