[ALSA] semaphore -> mutex (PCI part)
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / ice1712 / aureon.c
blob0f7f4d8263c0eb1d186b095f928daaa7407f7bb2
1 /*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Terratec Aureon cards
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * NOTES:
25 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
26 * both wm and akm codecs are pretty similar, so we can integrate
27 * both controls in the future, once if wm codecs are reused in
28 * many boards.
30 * - DAC digital volumes are not implemented in the mixer.
31 * if they show better response than DAC analog volumes, we can use them
32 * instead.
34 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
37 * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
38 * added 64x/128x oversampling switch (should be 64x only for 96khz)
39 * fixed some recording labels (still need to check the rest)
40 * recording is working probably thanks to correct wm8770 initialization
42 * version 0.5: Initial release:
43 * working: analog output, mixer, headphone amplifier switch
44 * not working: prety much everything else, at least i could verify that
45 * we have no digital output, no capture, pretty bad clicks and poops
46 * on mixer switch and other coll stuff.
48 */
50 #include <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 <linux/mutex.h>
58 #include <sound/core.h>
60 #include "ice1712.h"
61 #include "envy24ht.h"
62 #include "aureon.h"
64 /* WM8770 registers */
65 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
66 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
67 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
68 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
69 #define WM_PHASE_SWAP 0x12 /* DAC phase */
70 #define WM_DAC_CTRL1 0x13 /* DAC control bits */
71 #define WM_MUTE 0x14 /* mute controls */
72 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
73 #define WM_INT_CTRL 0x16 /* interface control */
74 #define WM_MASTER 0x17 /* master clock and mode */
75 #define WM_POWERDOWN 0x18 /* power-down controls */
76 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
77 #define WM_ADC_MUX 0x1b /* input MUX */
78 #define WM_OUT_MUX1 0x1c /* output MUX */
79 #define WM_OUT_MUX2 0x1e /* output MUX */
80 #define WM_RESET 0x1f /* software reset */
82 /* CS8415A registers */
83 #define CS8415_CTRL1 0x01
84 #define CS8415_CTRL2 0x02
85 #define CS8415_QSUB 0x14
86 #define CS8415_RATIO 0x1E
87 #define CS8415_C_BUFFER 0x20
88 #define CS8415_ID 0x7F
90 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
91 unsigned int tmp;
93 /* Send address to XILINX chip */
94 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
95 snd_ice1712_gpio_write(ice, tmp);
96 udelay(10);
97 tmp |= AUREON_AC97_ADDR;
98 snd_ice1712_gpio_write(ice, tmp);
99 udelay(10);
100 tmp &= ~AUREON_AC97_ADDR;
101 snd_ice1712_gpio_write(ice, tmp);
102 udelay(10);
104 /* Send low-order byte to XILINX chip */
105 tmp &= ~AUREON_AC97_DATA_MASK;
106 tmp |= val & AUREON_AC97_DATA_MASK;
107 snd_ice1712_gpio_write(ice, tmp);
108 udelay(10);
109 tmp |= AUREON_AC97_DATA_LOW;
110 snd_ice1712_gpio_write(ice, tmp);
111 udelay(10);
112 tmp &= ~AUREON_AC97_DATA_LOW;
113 snd_ice1712_gpio_write(ice, tmp);
114 udelay(10);
116 /* Send high-order byte to XILINX chip */
117 tmp &= ~AUREON_AC97_DATA_MASK;
118 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
120 snd_ice1712_gpio_write(ice, tmp);
121 udelay(10);
122 tmp |= AUREON_AC97_DATA_HIGH;
123 snd_ice1712_gpio_write(ice, tmp);
124 udelay(10);
125 tmp &= ~AUREON_AC97_DATA_HIGH;
126 snd_ice1712_gpio_write(ice, tmp);
127 udelay(10);
129 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
130 tmp |= AUREON_AC97_COMMIT;
131 snd_ice1712_gpio_write(ice, tmp);
132 udelay(10);
133 tmp &= ~AUREON_AC97_COMMIT;
134 snd_ice1712_gpio_write(ice, tmp);
135 udelay(10);
137 /* Store the data in out private buffer */
138 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
141 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
143 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
147 * Initialize STAC9744 chip
149 static int aureon_ac97_init (struct snd_ice1712 *ice) {
150 int i;
151 static unsigned short ac97_defaults[] = {
152 0x00, 0x9640,
153 0x02, 0x8000,
154 0x04, 0x8000,
155 0x06, 0x8000,
156 0x0C, 0x8008,
157 0x0E, 0x8008,
158 0x10, 0x8808,
159 0x12, 0x8808,
160 0x14, 0x8808,
161 0x16, 0x8808,
162 0x18, 0x8808,
163 0x1C, 0x8000,
164 0x26, 0x000F,
165 0x28, 0x0201,
166 0x2C, 0xBB80,
167 0x32, 0xBB80,
168 0x7C, 0x8384,
169 0x7E, 0x7644,
170 (unsigned short)-1
172 unsigned int tmp;
174 /* Cold reset */
175 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
176 snd_ice1712_gpio_write(ice, tmp);
177 udelay(3);
179 tmp &= ~AUREON_AC97_RESET;
180 snd_ice1712_gpio_write(ice, tmp);
181 udelay(3);
183 tmp |= AUREON_AC97_RESET;
184 snd_ice1712_gpio_write(ice, tmp);
185 udelay(3);
187 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
188 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
189 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
191 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
193 return 0;
196 #define AUREON_AC97_STEREO 0x80
199 * AC'97 volume controls
201 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
203 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
204 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
205 uinfo->value.integer.min = 0;
206 uinfo->value.integer.max = 31;
207 return 0;
210 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
212 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
213 unsigned short vol;
215 mutex_lock(&ice->gpio_mutex);
217 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
218 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
219 if (kcontrol->private_value & AUREON_AC97_STEREO)
220 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
222 mutex_unlock(&ice->gpio_mutex);
223 return 0;
226 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
228 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
229 unsigned short ovol, nvol;
230 int change;
232 snd_ice1712_save_gpio_status(ice);
234 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
235 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
236 if (kcontrol->private_value & AUREON_AC97_STEREO)
237 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
238 nvol |= ovol & ~0x1F1F;
240 if ((change = (ovol != nvol)))
241 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
243 snd_ice1712_restore_gpio_status(ice);
245 return change;
249 * AC'97 mute controls
251 #define aureon_ac97_mute_info aureon_mono_bool_info
253 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
255 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
257 mutex_lock(&ice->gpio_mutex);
259 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
261 mutex_unlock(&ice->gpio_mutex);
262 return 0;
265 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
267 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
268 unsigned short ovol, nvol;
269 int change;
271 snd_ice1712_save_gpio_status(ice);
273 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
274 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
276 if ((change = (ovol != nvol)))
277 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
279 snd_ice1712_restore_gpio_status(ice);
281 return change;
285 * AC'97 mute controls
287 #define aureon_ac97_micboost_info aureon_mono_bool_info
289 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
291 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
293 mutex_lock(&ice->gpio_mutex);
295 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
297 mutex_unlock(&ice->gpio_mutex);
298 return 0;
301 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
303 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
304 unsigned short ovol, nvol;
305 int change;
307 snd_ice1712_save_gpio_status(ice);
309 ovol = aureon_ac97_read(ice, AC97_MIC);
310 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
312 if ((change = (ovol != nvol)))
313 aureon_ac97_write(ice, AC97_MIC, nvol);
315 snd_ice1712_restore_gpio_status(ice);
317 return change;
321 * write data in the SPI mode
323 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
325 unsigned int tmp;
326 int i;
327 unsigned int mosi, clk;
329 tmp = snd_ice1712_gpio_read(ice);
331 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) {
332 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
333 mosi = PRODIGY_SPI_MOSI;
334 clk = PRODIGY_SPI_CLK;
336 else {
337 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
338 AUREON_WM_CS|AUREON_CS8415_CS));
339 mosi = AUREON_SPI_MOSI;
340 clk = AUREON_SPI_CLK;
342 tmp |= AUREON_WM_RW;
345 tmp &= ~cs;
346 snd_ice1712_gpio_write(ice, tmp);
347 udelay(1);
349 for (i = bits - 1; i >= 0; i--) {
350 tmp &= ~clk;
351 snd_ice1712_gpio_write(ice, tmp);
352 udelay(1);
353 if (data & (1 << i))
354 tmp |= mosi;
355 else
356 tmp &= ~mosi;
357 snd_ice1712_gpio_write(ice, tmp);
358 udelay(1);
359 tmp |= clk;
360 snd_ice1712_gpio_write(ice, tmp);
361 udelay(1);
364 tmp &= ~clk;
365 tmp |= cs;
366 snd_ice1712_gpio_write(ice, tmp);
367 udelay(1);
368 tmp |= clk;
369 snd_ice1712_gpio_write(ice, tmp);
370 udelay(1);
374 * Read data in SPI mode
376 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
377 int i, j;
378 unsigned int tmp;
380 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
381 snd_ice1712_gpio_write(ice, tmp);
382 tmp &= ~cs;
383 snd_ice1712_gpio_write(ice, tmp);
384 udelay(1);
386 for (i=bits-1; i>=0; i--) {
387 if (data & (1 << i))
388 tmp |= AUREON_SPI_MOSI;
389 else
390 tmp &= ~AUREON_SPI_MOSI;
391 snd_ice1712_gpio_write(ice, tmp);
392 udelay(1);
394 tmp |= AUREON_SPI_CLK;
395 snd_ice1712_gpio_write(ice, tmp);
396 udelay(1);
398 tmp &= ~AUREON_SPI_CLK;
399 snd_ice1712_gpio_write(ice, tmp);
400 udelay(1);
403 for (j=0; j<size; j++) {
404 unsigned char outdata = 0;
405 for (i=7; i>=0; i--) {
406 tmp = snd_ice1712_gpio_read(ice);
407 outdata <<= 1;
408 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
409 udelay(1);
411 tmp |= AUREON_SPI_CLK;
412 snd_ice1712_gpio_write(ice, tmp);
413 udelay(1);
415 tmp &= ~AUREON_SPI_CLK;
416 snd_ice1712_gpio_write(ice, tmp);
417 udelay(1);
419 buffer[j] = outdata;
422 tmp |= cs;
423 snd_ice1712_gpio_write(ice, tmp);
426 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
427 unsigned char val;
428 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
429 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
430 return val;
433 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
434 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
435 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
438 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
439 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
443 * get the current register value of WM codec
445 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
447 reg <<= 1;
448 return ((unsigned short)ice->akm[0].images[reg] << 8) |
449 ice->akm[0].images[reg + 1];
453 * set the register value of WM codec
455 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
457 aureon_spi_write(ice,
458 (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS),
459 (reg << 9) | (val & 0x1ff), 16);
463 * set the register value of WM codec and remember it
465 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
467 wm_put_nocache(ice, reg, val);
468 reg <<= 1;
469 ice->akm[0].images[reg] = val >> 8;
470 ice->akm[0].images[reg + 1] = val;
475 static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
477 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
478 uinfo->count = 1;
479 uinfo->value.integer.min = 0;
480 uinfo->value.integer.max = 1;
481 return 0;
485 * AC'97 master playback mute controls (Mute on WM8770 chip)
487 #define aureon_ac97_mmute_info aureon_mono_bool_info
489 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
491 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
493 mutex_lock(&ice->gpio_mutex);
495 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
497 mutex_unlock(&ice->gpio_mutex);
498 return 0;
501 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
502 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
503 unsigned short ovol, nvol;
504 int change;
506 snd_ice1712_save_gpio_status(ice);
508 ovol = wm_get(ice, WM_OUT_MUX1);
509 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
510 if ((change = (ovol != nvol)))
511 wm_put(ice, WM_OUT_MUX1, nvol);
513 snd_ice1712_restore_gpio_status(ice);
515 return change;
519 * Logarithmic volume values for WM8770
520 * Computed as 20 * Log10(255 / x)
522 static unsigned char wm_vol[256] = {
523 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
524 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
525 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
526 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
527 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
528 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,
529 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,
530 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,
531 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,
532 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,
533 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,
534 0, 0
537 #define WM_VOL_MAX (sizeof(wm_vol) - 1)
538 #define WM_VOL_MUTE 0x8000
540 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
542 unsigned char nvol;
544 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
545 nvol = 0;
546 else
547 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
549 wm_put(ice, index, nvol);
550 wm_put_nocache(ice, index, 0x180 | nvol);
554 * DAC mute control
556 #define wm_pcm_mute_info aureon_mono_bool_info
558 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
560 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
562 mutex_lock(&ice->gpio_mutex);
563 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
564 mutex_unlock(&ice->gpio_mutex);
565 return 0;
568 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
570 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
571 unsigned short nval, oval;
572 int change;
574 snd_ice1712_save_gpio_status(ice);
575 oval = wm_get(ice, WM_MUTE);
576 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
577 if ((change = (nval != oval)))
578 wm_put(ice, WM_MUTE, nval);
579 snd_ice1712_restore_gpio_status(ice);
581 return change;
585 * Master volume attenuation mixer control
587 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
589 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
590 uinfo->count = 2;
591 uinfo->value.integer.min = 0;
592 uinfo->value.integer.max = WM_VOL_MAX;
593 return 0;
596 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
598 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
599 int i;
600 for (i=0; i<2; i++)
601 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
602 return 0;
605 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
607 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
608 int ch, change = 0;
610 snd_ice1712_save_gpio_status(ice);
611 for (ch = 0; ch < 2; ch++) {
612 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
613 int dac;
614 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
615 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
616 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
617 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
618 ice->spec.aureon.vol[dac + ch],
619 ice->spec.aureon.master[ch]);
620 change = 1;
623 snd_ice1712_restore_gpio_status(ice);
624 return change;
628 * DAC volume attenuation mixer control
630 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
632 int voices = kcontrol->private_value >> 8;
633 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
634 uinfo->count = voices;
635 uinfo->value.integer.min = 0; /* mute (-101dB) */
636 uinfo->value.integer.max = 0x7F; /* 0dB */
637 return 0;
640 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
642 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
643 int i, ofs, voices;
645 voices = kcontrol->private_value >> 8;
646 ofs = kcontrol->private_value & 0xff;
647 for (i = 0; i < voices; i++)
648 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
649 return 0;
652 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
654 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
655 int i, idx, ofs, voices;
656 int change = 0;
658 voices = kcontrol->private_value >> 8;
659 ofs = kcontrol->private_value & 0xff;
660 snd_ice1712_save_gpio_status(ice);
661 for (i = 0; i < voices; i++) {
662 idx = WM_DAC_ATTEN + ofs + i;
663 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
664 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
665 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
666 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
667 ice->spec.aureon.master[i]);
668 change = 1;
671 snd_ice1712_restore_gpio_status(ice);
672 return change;
676 * WM8770 mute control
678 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
679 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
680 uinfo->count = kcontrol->private_value >> 8;
681 uinfo->value.integer.min = 0;
682 uinfo->value.integer.max = 1;
683 return 0;
686 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
688 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
689 int voices, ofs, i;
691 voices = kcontrol->private_value >> 8;
692 ofs = kcontrol->private_value & 0xFF;
694 for (i = 0; i < voices; i++)
695 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
696 return 0;
699 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
701 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
702 int change = 0, voices, ofs, i;
704 voices = kcontrol->private_value >> 8;
705 ofs = kcontrol->private_value & 0xFF;
707 snd_ice1712_save_gpio_status(ice);
708 for (i = 0; i < voices; i++) {
709 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
710 if (ucontrol->value.integer.value[i] != val) {
711 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
712 ice->spec.aureon.vol[ofs + i] |=
713 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
714 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
715 ice->spec.aureon.master[i]);
716 change = 1;
719 snd_ice1712_restore_gpio_status(ice);
721 return change;
725 * WM8770 master mute control
727 static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
728 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
729 uinfo->count = 2;
730 uinfo->value.integer.min = 0;
731 uinfo->value.integer.max = 1;
732 return 0;
735 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
737 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
739 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
740 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
741 return 0;
744 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
746 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
747 int change = 0, i;
749 snd_ice1712_save_gpio_status(ice);
750 for (i = 0; i < 2; i++) {
751 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
752 if (ucontrol->value.integer.value[i] != val) {
753 int dac;
754 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
755 ice->spec.aureon.master[i] |=
756 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
757 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
758 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
759 ice->spec.aureon.vol[dac + i],
760 ice->spec.aureon.master[i]);
761 change = 1;
764 snd_ice1712_restore_gpio_status(ice);
766 return change;
769 /* digital master volume */
770 #define PCM_0dB 0xff
771 #define PCM_RES 128 /* -64dB */
772 #define PCM_MIN (PCM_0dB - PCM_RES)
773 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
775 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
776 uinfo->count = 1;
777 uinfo->value.integer.min = 0; /* mute (-64dB) */
778 uinfo->value.integer.max = PCM_RES; /* 0dB */
779 return 0;
782 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
784 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
785 unsigned short val;
787 mutex_lock(&ice->gpio_mutex);
788 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
789 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
790 ucontrol->value.integer.value[0] = val;
791 mutex_unlock(&ice->gpio_mutex);
792 return 0;
795 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
797 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
798 unsigned short ovol, nvol;
799 int change = 0;
801 snd_ice1712_save_gpio_status(ice);
802 nvol = ucontrol->value.integer.value[0];
803 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
804 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
805 if (ovol != nvol) {
806 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
807 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
808 change = 1;
810 snd_ice1712_restore_gpio_status(ice);
811 return change;
815 * ADC mute control
817 static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
819 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
820 uinfo->count = 2;
821 uinfo->value.integer.min = 0;
822 uinfo->value.integer.max = 1;
823 return 0;
826 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
828 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
829 unsigned short val;
830 int i;
832 mutex_lock(&ice->gpio_mutex);
833 for (i = 0; i < 2; i++) {
834 val = wm_get(ice, WM_ADC_GAIN + i);
835 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
837 mutex_unlock(&ice->gpio_mutex);
838 return 0;
841 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
843 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
844 unsigned short new, old;
845 int i, change = 0;
847 snd_ice1712_save_gpio_status(ice);
848 for (i = 0; i < 2; i++) {
849 old = wm_get(ice, WM_ADC_GAIN + i);
850 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
851 if (new != old) {
852 wm_put(ice, WM_ADC_GAIN + i, new);
853 change = 1;
856 snd_ice1712_restore_gpio_status(ice);
858 return change;
862 * ADC gain mixer control
864 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
866 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
867 uinfo->count = 2;
868 uinfo->value.integer.min = 0; /* -12dB */
869 uinfo->value.integer.max = 0x1f; /* 19dB */
870 return 0;
873 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
875 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
876 int i, idx;
877 unsigned short vol;
879 mutex_lock(&ice->gpio_mutex);
880 for (i = 0; i < 2; i++) {
881 idx = WM_ADC_GAIN + i;
882 vol = wm_get(ice, idx) & 0x1f;
883 ucontrol->value.integer.value[i] = vol;
885 mutex_unlock(&ice->gpio_mutex);
886 return 0;
889 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
891 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
892 int i, idx;
893 unsigned short ovol, nvol;
894 int change = 0;
896 snd_ice1712_save_gpio_status(ice);
897 for (i = 0; i < 2; i++) {
898 idx = WM_ADC_GAIN + i;
899 nvol = ucontrol->value.integer.value[i];
900 ovol = wm_get(ice, idx);
901 if ((ovol & 0x1f) != nvol) {
902 wm_put(ice, idx, nvol | (ovol & ~0x1f));
903 change = 1;
906 snd_ice1712_restore_gpio_status(ice);
907 return change;
911 * ADC input mux mixer control
913 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
915 static char *texts[] = {
916 "CD", //AIN1
917 "Aux", //AIN2
918 "Line", //AIN3
919 "Mic", //AIN4
920 "AC97" //AIN5
922 static char *universe_texts[] = {
923 "Aux1", //AIN1
924 "CD", //AIN2
925 "Phono", //AIN3
926 "Line", //AIN4
927 "Aux2", //AIN5
928 "Mic", //AIN6
929 "Aux3", //AIN7
930 "AC97" //AIN8
932 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
934 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
935 uinfo->count = 2;
936 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
937 uinfo->value.enumerated.items = 8;
938 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
939 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
940 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
942 else {
943 uinfo->value.enumerated.items = 5;
944 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
945 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
946 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
948 return 0;
951 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
953 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
954 unsigned short val;
956 mutex_lock(&ice->gpio_mutex);
957 val = wm_get(ice, WM_ADC_MUX);
958 ucontrol->value.integer.value[0] = val & 7;
959 ucontrol->value.integer.value[1] = (val >> 4) & 7;
960 mutex_unlock(&ice->gpio_mutex);
961 return 0;
964 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
966 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
967 unsigned short oval, nval;
968 int change;
970 snd_ice1712_save_gpio_status(ice);
971 oval = wm_get(ice, WM_ADC_MUX);
972 nval = oval & ~0x77;
973 nval |= ucontrol->value.integer.value[0] & 7;
974 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
975 change = (oval != nval);
976 if (change)
977 wm_put(ice, WM_ADC_MUX, nval);
978 snd_ice1712_restore_gpio_status(ice);
979 return change;
983 * CS8415 Input mux
985 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
987 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
988 static char *aureon_texts[] = {
989 "CD", //RXP0
990 "Optical" //RXP1
992 static char *prodigy_texts[] = {
993 "CD",
994 "Coax"
996 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
997 uinfo->count = 1;
998 uinfo->value.enumerated.items = 2;
999 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1000 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1001 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1002 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1003 else
1004 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1005 return 0;
1008 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1010 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1012 //snd_ice1712_save_gpio_status(ice);
1013 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1014 ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
1015 //snd_ice1712_restore_gpio_status(ice);
1016 return 0;
1019 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1021 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1022 unsigned short oval, nval;
1023 int change;
1025 snd_ice1712_save_gpio_status(ice);
1026 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1027 nval = oval & ~0x07;
1028 nval |= ucontrol->value.integer.value[0] & 7;
1029 change = (oval != nval);
1030 if (change)
1031 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1032 snd_ice1712_restore_gpio_status(ice);
1033 ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
1034 return change;
1037 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1039 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1040 uinfo->count = 1;
1041 uinfo->value.integer.min = 0;
1042 uinfo->value.integer.max = 192000;
1043 return 0;
1046 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1048 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1049 unsigned char ratio;
1050 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1051 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1052 return 0;
1056 * CS8415A Mute
1058 static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1060 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1061 uinfo->count = 1;
1062 return 0;
1065 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1067 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1068 snd_ice1712_save_gpio_status(ice);
1069 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1070 snd_ice1712_restore_gpio_status(ice);
1071 return 0;
1074 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1076 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1077 unsigned char oval, nval;
1078 int change;
1079 snd_ice1712_save_gpio_status(ice);
1080 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1081 if (ucontrol->value.integer.value[0])
1082 nval = oval & ~0x20;
1083 else
1084 nval = oval | 0x20;
1085 if ((change = (oval != nval)))
1086 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1087 snd_ice1712_restore_gpio_status(ice);
1088 return change;
1092 * CS8415A Q-Sub info
1094 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1095 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1096 uinfo->count = 10;
1097 return 0;
1100 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1101 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1103 snd_ice1712_save_gpio_status(ice);
1104 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1105 snd_ice1712_restore_gpio_status(ice);
1107 return 0;
1110 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1111 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1112 uinfo->count = 1;
1113 return 0;
1116 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1117 memset(ucontrol->value.iec958.status, 0xFF, 24);
1118 return 0;
1121 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1122 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1124 snd_ice1712_save_gpio_status(ice);
1125 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1126 snd_ice1712_restore_gpio_status(ice);
1127 return 0;
1131 * Headphone Amplifier
1133 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1135 unsigned int tmp, tmp2;
1137 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1138 if (enable)
1139 tmp |= AUREON_HP_SEL;
1140 else
1141 tmp &= ~ AUREON_HP_SEL;
1142 if (tmp != tmp2) {
1143 snd_ice1712_gpio_write(ice, tmp);
1144 return 1;
1146 return 0;
1149 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1151 unsigned int tmp = snd_ice1712_gpio_read(ice);
1153 return ( tmp & AUREON_HP_SEL )!= 0;
1156 #define aureon_hpamp_info aureon_mono_bool_info
1158 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1160 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1162 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1163 return 0;
1167 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1169 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1171 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1175 * Deemphasis
1178 #define aureon_deemp_info aureon_mono_bool_info
1180 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1182 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1183 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1184 return 0;
1187 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1189 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1190 int temp, temp2;
1191 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1192 if (ucontrol->value.integer.value[0])
1193 temp |= 0xf;
1194 else
1195 temp &= ~0xf;
1196 if (temp != temp2) {
1197 wm_put(ice, WM_DAC_CTRL2, temp);
1198 return 1;
1200 return 0;
1204 * ADC Oversampling
1206 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1208 static char *texts[2] = { "128x", "64x" };
1210 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1211 uinfo->count = 1;
1212 uinfo->value.enumerated.items = 2;
1214 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1215 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1216 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1218 return 0;
1221 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1223 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1224 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1225 return 0;
1228 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1230 int temp, temp2;
1231 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1233 temp2 = temp = wm_get(ice, WM_MASTER);
1235 if (ucontrol->value.enumerated.item[0])
1236 temp |= 0x8;
1237 else
1238 temp &= ~0x8;
1240 if (temp != temp2) {
1241 wm_put(ice, WM_MASTER, temp);
1242 return 1;
1244 return 0;
1248 * mixers
1251 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1253 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1254 .name = "Master Playback Switch",
1255 .info = wm_master_mute_info,
1256 .get = wm_master_mute_get,
1257 .put = wm_master_mute_put
1260 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1261 .name = "Master Playback Volume",
1262 .info = wm_master_vol_info,
1263 .get = wm_master_vol_get,
1264 .put = wm_master_vol_put
1267 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1268 .name = "Front Playback Switch",
1269 .info = wm_mute_info,
1270 .get = wm_mute_get,
1271 .put = wm_mute_put,
1272 .private_value = (2 << 8) | 0
1275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276 .name = "Front Playback Volume",
1277 .info = wm_vol_info,
1278 .get = wm_vol_get,
1279 .put = wm_vol_put,
1280 .private_value = (2 << 8) | 0
1283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1284 .name = "Rear Playback Switch",
1285 .info = wm_mute_info,
1286 .get = wm_mute_get,
1287 .put = wm_mute_put,
1288 .private_value = (2 << 8) | 2
1291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1292 .name = "Rear Playback Volume",
1293 .info = wm_vol_info,
1294 .get = wm_vol_get,
1295 .put = wm_vol_put,
1296 .private_value = (2 << 8) | 2
1299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1300 .name = "Center Playback Switch",
1301 .info = wm_mute_info,
1302 .get = wm_mute_get,
1303 .put = wm_mute_put,
1304 .private_value = (1 << 8) | 4
1307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308 .name = "Center Playback Volume",
1309 .info = wm_vol_info,
1310 .get = wm_vol_get,
1311 .put = wm_vol_put,
1312 .private_value = (1 << 8) | 4
1315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1316 .name = "LFE Playback Switch",
1317 .info = wm_mute_info,
1318 .get = wm_mute_get,
1319 .put = wm_mute_put,
1320 .private_value = (1 << 8) | 5
1323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1324 .name = "LFE Playback Volume",
1325 .info = wm_vol_info,
1326 .get = wm_vol_get,
1327 .put = wm_vol_put,
1328 .private_value = (1 << 8) | 5
1331 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1332 .name = "Side Playback Switch",
1333 .info = wm_mute_info,
1334 .get = wm_mute_get,
1335 .put = wm_mute_put,
1336 .private_value = (2 << 8) | 6
1339 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1340 .name = "Side Playback Volume",
1341 .info = wm_vol_info,
1342 .get = wm_vol_get,
1343 .put = wm_vol_put,
1344 .private_value = (2 << 8) | 6
1348 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1351 .name = "PCM Playback Switch",
1352 .info = wm_pcm_mute_info,
1353 .get = wm_pcm_mute_get,
1354 .put = wm_pcm_mute_put
1357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1358 .name = "PCM Playback Volume",
1359 .info = wm_pcm_vol_info,
1360 .get = wm_pcm_vol_get,
1361 .put = wm_pcm_vol_put
1364 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1365 .name = "Capture Switch",
1366 .info = wm_adc_mute_info,
1367 .get = wm_adc_mute_get,
1368 .put = wm_adc_mute_put,
1371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1372 .name = "Capture Volume",
1373 .info = wm_adc_vol_info,
1374 .get = wm_adc_vol_get,
1375 .put = wm_adc_vol_put
1378 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1379 .name = "Capture Source",
1380 .info = wm_adc_mux_info,
1381 .get = wm_adc_mux_get,
1382 .put = wm_adc_mux_put,
1383 .private_value = 5
1386 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1387 .name = "External Amplifier",
1388 .info = aureon_hpamp_info,
1389 .get = aureon_hpamp_get,
1390 .put = aureon_hpamp_put
1393 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1394 .name = "DAC Deemphasis Switch",
1395 .info = aureon_deemp_info,
1396 .get = aureon_deemp_get,
1397 .put = aureon_deemp_put
1400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1401 .name = "ADC Oversampling",
1402 .info = aureon_oversampling_info,
1403 .get = aureon_oversampling_get,
1404 .put = aureon_oversampling_put
1408 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1411 .name = "AC97 Playback Switch",
1412 .info = aureon_ac97_mmute_info,
1413 .get = aureon_ac97_mmute_get,
1414 .put = aureon_ac97_mmute_put,
1415 .private_value = AC97_MASTER
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .name = "AC97 Playback Volume",
1420 .info = aureon_ac97_vol_info,
1421 .get = aureon_ac97_vol_get,
1422 .put = aureon_ac97_vol_put,
1423 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1426 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1427 .name = "CD Playback Switch",
1428 .info = aureon_ac97_mute_info,
1429 .get = aureon_ac97_mute_get,
1430 .put = aureon_ac97_mute_put,
1431 .private_value = AC97_CD
1434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1435 .name = "CD Playback Volume",
1436 .info = aureon_ac97_vol_info,
1437 .get = aureon_ac97_vol_get,
1438 .put = aureon_ac97_vol_put,
1439 .private_value = AC97_CD|AUREON_AC97_STEREO
1442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443 .name = "Aux Playback Switch",
1444 .info = aureon_ac97_mute_info,
1445 .get = aureon_ac97_mute_get,
1446 .put = aureon_ac97_mute_put,
1447 .private_value = AC97_AUX,
1450 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451 .name = "Aux Playback Volume",
1452 .info = aureon_ac97_vol_info,
1453 .get = aureon_ac97_vol_get,
1454 .put = aureon_ac97_vol_put,
1455 .private_value = AC97_AUX|AUREON_AC97_STEREO
1458 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1459 .name = "Line Playback Switch",
1460 .info = aureon_ac97_mute_info,
1461 .get = aureon_ac97_mute_get,
1462 .put = aureon_ac97_mute_put,
1463 .private_value = AC97_LINE
1466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467 .name = "Line Playback Volume",
1468 .info = aureon_ac97_vol_info,
1469 .get = aureon_ac97_vol_get,
1470 .put = aureon_ac97_vol_put,
1471 .private_value = AC97_LINE|AUREON_AC97_STEREO
1474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475 .name = "Mic Playback Switch",
1476 .info = aureon_ac97_mute_info,
1477 .get = aureon_ac97_mute_get,
1478 .put = aureon_ac97_mute_put,
1479 .private_value = AC97_MIC
1482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1483 .name = "Mic Playback Volume",
1484 .info = aureon_ac97_vol_info,
1485 .get = aureon_ac97_vol_get,
1486 .put = aureon_ac97_vol_put,
1487 .private_value = AC97_MIC
1490 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1491 .name = "Mic Boost (+20dB)",
1492 .info = aureon_ac97_micboost_info,
1493 .get = aureon_ac97_micboost_get,
1494 .put = aureon_ac97_micboost_put
1498 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1500 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1501 .name = "AC97 Playback Switch",
1502 .info = aureon_ac97_mmute_info,
1503 .get = aureon_ac97_mmute_get,
1504 .put = aureon_ac97_mmute_put,
1505 .private_value = AC97_MASTER
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "AC97 Playback Volume",
1510 .info = aureon_ac97_vol_info,
1511 .get = aureon_ac97_vol_get,
1512 .put = aureon_ac97_vol_put,
1513 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .name = "CD Playback Switch",
1518 .info = aureon_ac97_mute_info,
1519 .get = aureon_ac97_mute_get,
1520 .put = aureon_ac97_mute_put,
1521 .private_value = AC97_AUX
1524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1525 .name = "CD Playback Volume",
1526 .info = aureon_ac97_vol_info,
1527 .get = aureon_ac97_vol_get,
1528 .put = aureon_ac97_vol_put,
1529 .private_value = AC97_AUX|AUREON_AC97_STEREO
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533 .name = "Phono Playback Switch",
1534 .info = aureon_ac97_mute_info,
1535 .get = aureon_ac97_mute_get,
1536 .put = aureon_ac97_mute_put,
1537 .private_value = AC97_CD,
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Phono Playback Volume",
1542 .info = aureon_ac97_vol_info,
1543 .get = aureon_ac97_vol_get,
1544 .put = aureon_ac97_vol_put,
1545 .private_value = AC97_CD|AUREON_AC97_STEREO
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "Line Playback Switch",
1550 .info = aureon_ac97_mute_info,
1551 .get = aureon_ac97_mute_get,
1552 .put = aureon_ac97_mute_put,
1553 .private_value = AC97_LINE
1556 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557 .name = "Line Playback Volume",
1558 .info = aureon_ac97_vol_info,
1559 .get = aureon_ac97_vol_get,
1560 .put = aureon_ac97_vol_put,
1561 .private_value = AC97_LINE|AUREON_AC97_STEREO
1564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1565 .name = "Mic Playback Switch",
1566 .info = aureon_ac97_mute_info,
1567 .get = aureon_ac97_mute_get,
1568 .put = aureon_ac97_mute_put,
1569 .private_value = AC97_MIC
1572 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1573 .name = "Mic Playback Volume",
1574 .info = aureon_ac97_vol_info,
1575 .get = aureon_ac97_vol_get,
1576 .put = aureon_ac97_vol_put,
1577 .private_value = AC97_MIC
1580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1581 .name = "Mic Boost (+20dB)",
1582 .info = aureon_ac97_micboost_info,
1583 .get = aureon_ac97_micboost_get,
1584 .put = aureon_ac97_micboost_put
1587 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1588 .name = "Aux Playback Switch",
1589 .info = aureon_ac97_mute_info,
1590 .get = aureon_ac97_mute_get,
1591 .put = aureon_ac97_mute_put,
1592 .private_value = AC97_VIDEO,
1595 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1596 .name = "Aux Playback Volume",
1597 .info = aureon_ac97_vol_info,
1598 .get = aureon_ac97_vol_get,
1599 .put = aureon_ac97_vol_put,
1600 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1605 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1607 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1608 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1609 .info = aureon_cs8415_mute_info,
1610 .get = aureon_cs8415_mute_get,
1611 .put = aureon_cs8415_mute_put
1614 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1615 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1616 .info = aureon_cs8415_mux_info,
1617 .get = aureon_cs8415_mux_get,
1618 .put = aureon_cs8415_mux_put,
1621 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1622 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1623 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1624 .info = aureon_cs8415_qsub_info,
1625 .get = aureon_cs8415_qsub_get,
1628 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1629 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1630 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1631 .info = aureon_cs8415_spdif_info,
1632 .get = aureon_cs8415_mask_get
1635 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1636 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1637 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1638 .info = aureon_cs8415_spdif_info,
1639 .get = aureon_cs8415_spdif_get
1642 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1643 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1644 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1645 .info = aureon_cs8415_rate_info,
1646 .get = aureon_cs8415_rate_get
1651 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1653 unsigned int i, counts;
1654 int err;
1656 counts = ARRAY_SIZE(aureon_dac_controls);
1657 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1658 counts -= 2; /* no side */
1659 for (i = 0; i < counts; i++) {
1660 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1661 if (err < 0)
1662 return err;
1665 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1666 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1667 if (err < 0)
1668 return err;
1671 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1672 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1673 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1674 if (err < 0)
1675 return err;
1678 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1679 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1680 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1681 if (err < 0)
1682 return err;
1686 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1687 unsigned char id;
1688 snd_ice1712_save_gpio_status(ice);
1689 id = aureon_cs8415_get(ice, CS8415_ID);
1690 if (id != 0x41)
1691 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1692 else if ((id & 0x0F) != 0x01)
1693 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1694 else {
1695 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1696 struct snd_kcontrol *kctl;
1697 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1698 if (err < 0)
1699 return err;
1700 if (i > 1)
1701 kctl->id.device = ice->pcm->device;
1704 snd_ice1712_restore_gpio_status(ice);
1707 return 0;
1712 * initialize the chip
1714 static int __devinit aureon_init(struct snd_ice1712 *ice)
1716 static unsigned short wm_inits_aureon[] = {
1717 /* These come first to reduce init pop noise */
1718 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1719 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1720 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1722 0x18, 0x000, /* All power-up */
1724 0x16, 0x122, /* I2S, normal polarity, 24bit */
1725 0x17, 0x022, /* 256fs, slave mode */
1726 0x00, 0, /* DAC1 analog mute */
1727 0x01, 0, /* DAC2 analog mute */
1728 0x02, 0, /* DAC3 analog mute */
1729 0x03, 0, /* DAC4 analog mute */
1730 0x04, 0, /* DAC5 analog mute */
1731 0x05, 0, /* DAC6 analog mute */
1732 0x06, 0, /* DAC7 analog mute */
1733 0x07, 0, /* DAC8 analog mute */
1734 0x08, 0x100, /* master analog mute */
1735 0x09, 0xff, /* DAC1 digital full */
1736 0x0a, 0xff, /* DAC2 digital full */
1737 0x0b, 0xff, /* DAC3 digital full */
1738 0x0c, 0xff, /* DAC4 digital full */
1739 0x0d, 0xff, /* DAC5 digital full */
1740 0x0e, 0xff, /* DAC6 digital full */
1741 0x0f, 0xff, /* DAC7 digital full */
1742 0x10, 0xff, /* DAC8 digital full */
1743 0x11, 0x1ff, /* master digital full */
1744 0x12, 0x000, /* phase normal */
1745 0x13, 0x090, /* unmute DAC L/R */
1746 0x14, 0x000, /* all unmute */
1747 0x15, 0x000, /* no deemphasis, no ZFLG */
1748 0x19, 0x000, /* -12dB ADC/L */
1749 0x1a, 0x000, /* -12dB ADC/R */
1750 (unsigned short)-1
1752 static unsigned short wm_inits_prodigy[] = {
1754 /* These come first to reduce init pop noise */
1755 0x1b, 0x000, /* ADC Mux */
1756 0x1c, 0x009, /* Out Mux1 */
1757 0x1d, 0x009, /* Out Mux2 */
1759 0x18, 0x000, /* All power-up */
1761 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1762 0x17, 0x006, /* 128fs, slave mode */
1764 0x00, 0, /* DAC1 analog mute */
1765 0x01, 0, /* DAC2 analog mute */
1766 0x02, 0, /* DAC3 analog mute */
1767 0x03, 0, /* DAC4 analog mute */
1768 0x04, 0, /* DAC5 analog mute */
1769 0x05, 0, /* DAC6 analog mute */
1770 0x06, 0, /* DAC7 analog mute */
1771 0x07, 0, /* DAC8 analog mute */
1772 0x08, 0x100, /* master analog mute */
1774 0x09, 0x7f, /* DAC1 digital full */
1775 0x0a, 0x7f, /* DAC2 digital full */
1776 0x0b, 0x7f, /* DAC3 digital full */
1777 0x0c, 0x7f, /* DAC4 digital full */
1778 0x0d, 0x7f, /* DAC5 digital full */
1779 0x0e, 0x7f, /* DAC6 digital full */
1780 0x0f, 0x7f, /* DAC7 digital full */
1781 0x10, 0x7f, /* DAC8 digital full */
1782 0x11, 0x1FF, /* master digital full */
1784 0x12, 0x000, /* phase normal */
1785 0x13, 0x090, /* unmute DAC L/R */
1786 0x14, 0x000, /* all unmute */
1787 0x15, 0x000, /* no deemphasis, no ZFLG */
1789 0x19, 0x000, /* -12dB ADC/L */
1790 0x1a, 0x000, /* -12dB ADC/R */
1791 (unsigned short)-1
1794 static unsigned short cs_inits[] = {
1795 0x0441, /* RUN */
1796 0x0180, /* no mute, OMCK output on RMCK pin */
1797 0x0201, /* S/PDIF source on RXP1 */
1798 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1799 (unsigned short)-1
1801 unsigned int tmp;
1802 unsigned short *p;
1803 int err, i;
1805 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1806 ice->num_total_dacs = 6;
1807 ice->num_total_adcs = 2;
1808 } else {
1809 /* aureon 7.1 and prodigy 7.1 */
1810 ice->num_total_dacs = 8;
1811 ice->num_total_adcs = 2;
1814 /* to remeber the register values of CS8415 */
1815 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1816 if (! ice->akm)
1817 return -ENOMEM;
1818 ice->akm_codecs = 1;
1820 if ((err = aureon_ac97_init(ice)) != 0)
1821 return err;
1823 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1825 /* reset the wm codec as the SPI mode */
1826 snd_ice1712_save_gpio_status(ice);
1827 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1829 tmp = snd_ice1712_gpio_read(ice);
1830 tmp &= ~AUREON_WM_RESET;
1831 snd_ice1712_gpio_write(ice, tmp);
1832 udelay(1);
1833 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1834 snd_ice1712_gpio_write(ice, tmp);
1835 udelay(1);
1836 tmp |= AUREON_WM_RESET;
1837 snd_ice1712_gpio_write(ice, tmp);
1838 udelay(1);
1840 /* initialize WM8770 codec */
1841 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
1842 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT)
1843 p = wm_inits_prodigy;
1844 else
1845 p = wm_inits_aureon;
1846 for (; *p != (unsigned short)-1; p += 2)
1847 wm_put(ice, p[0], p[1]);
1849 /* initialize CS8415A codec */
1850 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1851 for (p = cs_inits; *p != (unsigned short)-1; p++)
1852 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
1853 ice->spec.aureon.cs8415_mux = 1;
1855 aureon_set_headphone_amp(ice, 1);
1858 snd_ice1712_restore_gpio_status(ice);
1860 ice->spec.aureon.master[0] = WM_VOL_MUTE;
1861 ice->spec.aureon.master[1] = WM_VOL_MUTE;
1862 for (i = 0; i < ice->num_total_dacs; i++) {
1863 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1864 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1867 return 0;
1872 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1873 * hence the driver needs to sets up it properly.
1876 static unsigned char aureon51_eeprom[] __devinitdata = {
1877 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1878 0x80, /* ACLINK: I2S */
1879 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1880 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1881 0xff, /* GPIO_DIR */
1882 0xff, /* GPIO_DIR1 */
1883 0x5f, /* GPIO_DIR2 */
1884 0x00, /* GPIO_MASK */
1885 0x00, /* GPIO_MASK1 */
1886 0x00, /* GPIO_MASK2 */
1887 0x00, /* GPIO_STATE */
1888 0x00, /* GPIO_STATE1 */
1889 0x00, /* GPIO_STATE2 */
1892 static unsigned char aureon71_eeprom[] __devinitdata = {
1893 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1894 0x80, /* ACLINK: I2S */
1895 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1896 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1897 0xff, /* GPIO_DIR */
1898 0xff, /* GPIO_DIR1 */
1899 0x5f, /* GPIO_DIR2 */
1900 0x00, /* GPIO_MASK */
1901 0x00, /* GPIO_MASK1 */
1902 0x00, /* GPIO_MASK2 */
1903 0x00, /* GPIO_STATE */
1904 0x00, /* GPIO_STATE1 */
1905 0x00, /* GPIO_STATE2 */
1908 static unsigned char prodigy71_eeprom[] __devinitdata = {
1909 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1910 0x80, /* ACLINK: I2S */
1911 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1912 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1913 0xff, /* GPIO_DIR */
1914 0xff, /* GPIO_DIR1 */
1915 0x5f, /* GPIO_DIR2 */
1916 0x00, /* GPIO_MASK */
1917 0x00, /* GPIO_MASK1 */
1918 0x00, /* GPIO_MASK2 */
1919 0x00, /* GPIO_STATE */
1920 0x00, /* GPIO_STATE1 */
1921 0x00, /* GPIO_STATE2 */
1924 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
1925 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
1926 0x80, /* ACLINK: I2S */
1927 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1928 0xc3, /* SPDUF: out-en, out-int */
1929 0x00, /* GPIO_DIR */
1930 0x07, /* GPIO_DIR1 */
1931 0x00, /* GPIO_DIR2 */
1932 0xff, /* GPIO_MASK */
1933 0xf8, /* GPIO_MASK1 */
1934 0xff, /* GPIO_MASK2 */
1935 0x00, /* GPIO_STATE */
1936 0x00, /* GPIO_STATE1 */
1937 0x00, /* GPIO_STATE2 */
1941 /* entry point */
1942 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1944 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1945 .name = "Terratec Aureon 5.1-Sky",
1946 .model = "aureon51",
1947 .chip_init = aureon_init,
1948 .build_controls = aureon_add_controls,
1949 .eeprom_size = sizeof(aureon51_eeprom),
1950 .eeprom_data = aureon51_eeprom,
1951 .driver = "Aureon51",
1954 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1955 .name = "Terratec Aureon 7.1-Space",
1956 .model = "aureon71",
1957 .chip_init = aureon_init,
1958 .build_controls = aureon_add_controls,
1959 .eeprom_size = sizeof(aureon71_eeprom),
1960 .eeprom_data = aureon71_eeprom,
1961 .driver = "Aureon71",
1964 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1965 .name = "Terratec Aureon 7.1-Universe",
1966 .model = "universe",
1967 .chip_init = aureon_init,
1968 .build_controls = aureon_add_controls,
1969 .eeprom_size = sizeof(aureon71_eeprom),
1970 .eeprom_data = aureon71_eeprom,
1971 .driver = "Aureon71Universe",
1974 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1975 .name = "Audiotrak Prodigy 7.1",
1976 .model = "prodigy71",
1977 .chip_init = aureon_init,
1978 .build_controls = aureon_add_controls,
1979 .eeprom_size = sizeof(prodigy71_eeprom),
1980 .eeprom_data = prodigy71_eeprom,
1981 .driver = "Prodigy71", /* should be identical with Aureon71 */
1984 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
1985 .name = "Audiotrak Prodigy 7.1 LT",
1986 .model = "prodigy71lt",
1987 .chip_init = aureon_init,
1988 .build_controls = aureon_add_controls,
1989 .eeprom_size = sizeof(prodigy71lt_eeprom),
1990 .eeprom_data = prodigy71lt_eeprom,
1991 .driver = "Prodigy71LT",
1993 { } /* terminator */