Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / ice1712 / aureon.c
blob4405d96cbedf925d7fe9a4e928a7079694fc2e52
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 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
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 <sound/driver.h>
51 #include <asm/io.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>
58 #include "ice1712.h"
59 #include "envy24ht.h"
60 #include "aureon.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) {
89 unsigned int tmp;
91 /* Send address to XILINX chip */
92 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
93 snd_ice1712_gpio_write(ice, tmp);
94 udelay(10);
95 tmp |= AUREON_AC97_ADDR;
96 snd_ice1712_gpio_write(ice, tmp);
97 udelay(10);
98 tmp &= ~AUREON_AC97_ADDR;
99 snd_ice1712_gpio_write(ice, tmp);
100 udelay(10);
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);
106 udelay(10);
107 tmp |= AUREON_AC97_DATA_LOW;
108 snd_ice1712_gpio_write(ice, tmp);
109 udelay(10);
110 tmp &= ~AUREON_AC97_DATA_LOW;
111 snd_ice1712_gpio_write(ice, tmp);
112 udelay(10);
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);
119 udelay(10);
120 tmp |= AUREON_AC97_DATA_HIGH;
121 snd_ice1712_gpio_write(ice, tmp);
122 udelay(10);
123 tmp &= ~AUREON_AC97_DATA_HIGH;
124 snd_ice1712_gpio_write(ice, tmp);
125 udelay(10);
127 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
128 tmp |= AUREON_AC97_COMMIT;
129 snd_ice1712_gpio_write(ice, tmp);
130 udelay(10);
131 tmp &= ~AUREON_AC97_COMMIT;
132 snd_ice1712_gpio_write(ice, tmp);
133 udelay(10);
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) {
148 int i;
149 static unsigned short ac97_defaults[] = {
150 0x00, 0x9640,
151 0x02, 0x8000,
152 0x04, 0x8000,
153 0x06, 0x8000,
154 0x0C, 0x8008,
155 0x0E, 0x8008,
156 0x10, 0x8808,
157 0x12, 0x8808,
158 0x14, 0x8808,
159 0x16, 0x8808,
160 0x18, 0x8808,
161 0x1C, 0x8000,
162 0x26, 0x000F,
163 0x28, 0x0201,
164 0x2C, 0xBB80,
165 0x32, 0xBB80,
166 0x7C, 0x8384,
167 0x7E, 0x7644,
168 (unsigned short)-1
170 unsigned int tmp;
172 /* Cold reset */
173 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
174 snd_ice1712_gpio_write(ice, tmp);
175 udelay(3);
177 tmp &= ~AUREON_AC97_RESET;
178 snd_ice1712_gpio_write(ice, tmp);
179 udelay(3);
181 tmp |= AUREON_AC97_RESET;
182 snd_ice1712_gpio_write(ice, tmp);
183 udelay(3);
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
191 return 0;
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;
205 return 0;
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);
211 unsigned short vol;
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);
221 return 0;
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;
228 int change;
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);
243 return change;
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);
260 return 0;
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;
267 int change;
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);
279 return change;
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);
296 return 0;
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;
303 int change;
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);
315 return change;
319 * write data in the SPI mode
321 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
323 unsigned int tmp;
324 int i;
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));
330 tmp |= AUREON_WM_RW;
331 tmp &= ~cs;
332 snd_ice1712_gpio_write(ice, tmp);
333 udelay(1);
335 for (i = bits - 1; i >= 0; i--) {
336 tmp &= ~AUREON_SPI_CLK;
337 snd_ice1712_gpio_write(ice, tmp);
338 udelay(1);
339 if (data & (1 << i))
340 tmp |= AUREON_SPI_MOSI;
341 else
342 tmp &= ~AUREON_SPI_MOSI;
343 snd_ice1712_gpio_write(ice, tmp);
344 udelay(1);
345 tmp |= AUREON_SPI_CLK;
346 snd_ice1712_gpio_write(ice, tmp);
347 udelay(1);
350 tmp &= ~AUREON_SPI_CLK;
351 tmp |= cs;
352 snd_ice1712_gpio_write(ice, tmp);
353 udelay(1);
354 tmp |= AUREON_SPI_CLK;
355 snd_ice1712_gpio_write(ice, tmp);
356 udelay(1);
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) {
363 int i, j;
364 unsigned int tmp;
366 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
367 snd_ice1712_gpio_write(ice, tmp);
368 tmp &= ~cs;
369 snd_ice1712_gpio_write(ice, tmp);
370 udelay(1);
372 for (i=bits-1; i>=0; i--) {
373 if (data & (1 << i))
374 tmp |= AUREON_SPI_MOSI;
375 else
376 tmp &= ~AUREON_SPI_MOSI;
377 snd_ice1712_gpio_write(ice, tmp);
378 udelay(1);
380 tmp |= AUREON_SPI_CLK;
381 snd_ice1712_gpio_write(ice, tmp);
382 udelay(1);
384 tmp &= ~AUREON_SPI_CLK;
385 snd_ice1712_gpio_write(ice, tmp);
386 udelay(1);
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);
393 outdata <<= 1;
394 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
395 udelay(1);
397 tmp |= AUREON_SPI_CLK;
398 snd_ice1712_gpio_write(ice, tmp);
399 udelay(1);
401 tmp &= ~AUREON_SPI_CLK;
402 snd_ice1712_gpio_write(ice, tmp);
403 udelay(1);
405 buffer[j] = outdata;
408 tmp |= cs;
409 snd_ice1712_gpio_write(ice, tmp);
412 static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) {
413 unsigned char val;
414 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
415 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
416 return val;
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)
433 reg <<= 1;
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);
452 reg <<= 1;
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;
462 uinfo->count = 1;
463 uinfo->value.integer.min = 0;
464 uinfo->value.integer.max = 1;
465 return 0;
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);
482 return 0;
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;
488 int change;
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);
499 return change;
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,
518 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)
526 unsigned char nvol;
528 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
529 nvol = 0;
530 else
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);
538 * DAC mute control
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);
549 return 0;
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;
556 int change;
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);
565 return change;
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;
574 uinfo->count = 2;
575 uinfo->value.integer.min = 0;
576 uinfo->value.integer.max = WM_VOL_MAX;
577 return 0;
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);
583 int i;
584 for (i=0; i<2; i++)
585 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
586 return 0;
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);
592 int ch, change = 0;
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]) {
597 int dac;
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]);
604 change = 1;
607 snd_ice1712_restore_gpio_status(ice);
608 return change;
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 */
621 return 0;
624 static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
626 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
627 int i, ofs, voices;
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;
633 return 0;
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;
640 int change = 0;
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]);
652 change = 1;
655 snd_ice1712_restore_gpio_status(ice);
656 return change;
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;
667 return 0;
670 static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
672 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
673 int voices, ofs, i;
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;
680 return 0;
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]);
700 change = 1;
703 snd_ice1712_restore_gpio_status(ice);
705 return change;
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;
713 uinfo->count = 2;
714 uinfo->value.integer.min = 0;
715 uinfo->value.integer.max = 1;
716 return 0;
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;
725 return 0;
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);
731 int change = 0, i;
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) {
737 int dac;
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]);
745 change = 1;
748 snd_ice1712_restore_gpio_status(ice);
750 return change;
753 /* digital master volume */
754 #define PCM_0dB 0xff
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;
760 uinfo->count = 1;
761 uinfo->value.integer.min = 0; /* mute (-64dB) */
762 uinfo->value.integer.max = PCM_RES; /* 0dB */
763 return 0;
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);
769 unsigned short val;
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);
776 return 0;
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;
783 int change = 0;
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;
789 if (ovol != nvol) {
790 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
791 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
792 change = 1;
794 snd_ice1712_restore_gpio_status(ice);
795 return change;
799 * ADC mute control
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;
804 uinfo->count = 2;
805 uinfo->value.integer.min = 0;
806 uinfo->value.integer.max = 1;
807 return 0;
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);
813 unsigned short val;
814 int i;
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);
822 return 0;
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;
829 int i, change = 0;
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);
835 if (new != old) {
836 wm_put(ice, WM_ADC_GAIN + i, new);
837 change = 1;
840 snd_ice1712_restore_gpio_status(ice);
842 return change;
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;
851 uinfo->count = 2;
852 uinfo->value.integer.min = 0; /* -12dB */
853 uinfo->value.integer.max = 0x1f; /* 19dB */
854 return 0;
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);
860 int i, idx;
861 unsigned short vol;
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);
870 return 0;
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);
876 int i, idx;
877 unsigned short ovol, nvol;
878 int change = 0;
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));
887 change = 1;
890 snd_ice1712_restore_gpio_status(ice);
891 return change;
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[] = {
900 "CD", //AIN1
901 "Aux", //AIN2
902 "Line", //AIN3
903 "Mic", //AIN4
904 "AC97" //AIN5
906 static char *universe_texts[] = {
907 "Aux1", //AIN1
908 "CD", //AIN2
909 "Phono", //AIN3
910 "Line", //AIN4
911 "Aux2", //AIN5
912 "Mic", //AIN6
913 "Aux3", //AIN7
914 "AC97" //AIN8
916 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
918 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
919 uinfo->count = 2;
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]);
926 else {
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]);
932 return 0;
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);
938 unsigned short val;
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);
945 return 0;
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;
952 int change;
954 snd_ice1712_save_gpio_status(ice);
955 oval = wm_get(ice, WM_ADC_MUX);
956 nval = oval & ~0x77;
957 nval |= ucontrol->value.integer.value[0] & 7;
958 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
959 change = (oval != nval);
960 if (change)
961 wm_put(ice, WM_ADC_MUX, nval);
962 snd_ice1712_restore_gpio_status(ice);
963 return 0;
967 * CS8415 Input mux
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[] = {
973 "CD", //RXP0
974 "Optical" //RXP1
976 static char *prodigy_texts[] = {
977 "CD",
978 "Coax"
980 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
981 uinfo->count = 1;
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]);
987 else
988 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
989 return 0;
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);
1000 return 0;
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;
1007 int change;
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);
1014 if (change)
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];
1018 return change;
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;
1024 uinfo->count = 1;
1025 uinfo->value.integer.min = 0;
1026 uinfo->value.integer.max = 192000;
1027 return 0;
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);
1036 return 0;
1040 * CS8415A Mute
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;
1045 uinfo->count = 1;
1046 return 0;
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);
1055 return 0;
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;
1062 int change;
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;
1067 else
1068 nval = oval | 0x20;
1069 if ((change = (oval != nval)))
1070 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1071 snd_ice1712_restore_gpio_status(ice);
1072 return change;
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;
1080 uinfo->count = 10;
1081 return 0;
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);
1091 return 0;
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;
1096 uinfo->count = 1;
1097 return 0;
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);
1102 return 0;
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);
1111 return 0;
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);
1122 if (enable)
1123 tmp |= AUREON_HP_SEL;
1124 else
1125 tmp &= ~ AUREON_HP_SEL;
1126 if (tmp != tmp2) {
1127 snd_ice1712_gpio_write(ice, tmp);
1128 return 1;
1130 return 0;
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);
1147 return 0;
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]);
1159 * Deemphasis
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;
1168 return 0;
1171 static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1173 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1174 int temp, temp2;
1175 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1176 if (ucontrol->value.integer.value[0])
1177 temp |= 0xf;
1178 else
1179 temp &= ~0xf;
1180 if (temp != temp2) {
1181 wm_put(ice, WM_DAC_CTRL2, temp);
1182 return 1;
1184 return 0;
1188 * ADC Oversampling
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;
1195 uinfo->count = 1;
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]);
1202 return 0;
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;
1209 return 0;
1212 static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1214 int temp, temp2;
1215 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1217 temp2 = temp = wm_get(ice, WM_MASTER);
1219 if (ucontrol->value.enumerated.item[0])
1220 temp |= 0x8;
1221 else
1222 temp &= ~0x8;
1224 if (temp != temp2) {
1225 wm_put(ice, WM_MASTER, temp);
1226 return 1;
1228 return 0;
1232 * mixers
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,
1254 .get = wm_mute_get,
1255 .put = wm_mute_put,
1256 .private_value = (2 << 8) | 0
1259 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1260 .name = "Front Playback Volume",
1261 .info = wm_vol_info,
1262 .get = wm_vol_get,
1263 .put = wm_vol_put,
1264 .private_value = (2 << 8) | 0
1267 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1268 .name = "Rear Playback Switch",
1269 .info = wm_mute_info,
1270 .get = wm_mute_get,
1271 .put = wm_mute_put,
1272 .private_value = (2 << 8) | 2
1275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276 .name = "Rear Playback Volume",
1277 .info = wm_vol_info,
1278 .get = wm_vol_get,
1279 .put = wm_vol_put,
1280 .private_value = (2 << 8) | 2
1283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1284 .name = "Center Playback Switch",
1285 .info = wm_mute_info,
1286 .get = wm_mute_get,
1287 .put = wm_mute_put,
1288 .private_value = (1 << 8) | 4
1291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1292 .name = "Center Playback Volume",
1293 .info = wm_vol_info,
1294 .get = wm_vol_get,
1295 .put = wm_vol_put,
1296 .private_value = (1 << 8) | 4
1299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1300 .name = "LFE Playback Switch",
1301 .info = wm_mute_info,
1302 .get = wm_mute_get,
1303 .put = wm_mute_put,
1304 .private_value = (1 << 8) | 5
1307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308 .name = "LFE Playback Volume",
1309 .info = wm_vol_info,
1310 .get = wm_vol_get,
1311 .put = wm_vol_put,
1312 .private_value = (1 << 8) | 5
1315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1316 .name = "Side Playback Switch",
1317 .info = wm_mute_info,
1318 .get = wm_mute_get,
1319 .put = wm_mute_put,
1320 .private_value = (2 << 8) | 6
1323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1324 .name = "Side Playback Volume",
1325 .info = wm_vol_info,
1326 .get = wm_vol_get,
1327 .put = wm_vol_put,
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,
1367 .private_value = 5
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;
1638 int err;
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));
1645 if (err < 0)
1646 return err;
1649 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1650 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1651 if (err < 0)
1652 return err;
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));
1658 if (err < 0)
1659 return err;
1662 else {
1663 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1664 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1665 if (err < 0)
1666 return err;
1671 unsigned char id;
1672 snd_ice1712_save_gpio_status(ice);
1673 id = aureon_cs8415_get(ice, CS8415_ID);
1674 if (id != 0x41)
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));
1678 else {
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)));
1682 if (err < 0)
1683 return err;
1684 if (i > 1)
1685 kctl->id.device = ice->pcm->device;
1688 snd_ice1712_restore_gpio_status(ice);
1691 return 0;
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 */
1734 (unsigned short)-1
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 */
1775 (unsigned short)-1
1778 static unsigned short cs_inits[] = {
1779 0x0441, /* RUN */
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 */
1783 (unsigned short)-1
1785 unsigned int tmp;
1786 unsigned short *p;
1787 int err, i;
1789 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1790 ice->num_total_dacs = 6;
1791 ice->num_total_adcs = 2;
1792 } else {
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 = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
1800 if (! ice->akm)
1801 return -ENOMEM;
1802 ice->akm_codecs = 1;
1804 if ((err = aureon_ac97_init(ice)) != 0)
1805 return err;
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);
1816 udelay(1);
1817 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1818 snd_ice1712_gpio_write(ice, tmp);
1819 udelay(1);
1820 tmp |= AUREON_WM_RESET;
1821 snd_ice1712_gpio_write(ice, tmp);
1822 udelay(1);
1824 /* initialize WM8770 codec */
1825 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1826 p = wm_inits_prodigy;
1827 else
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]);
1848 return 0;
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 */
1905 /* entry point */
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 */