blob: 2175f6721347bb26fac80681ba5864d0e4607f3e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for Terratec Aureon cards
5 *
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7 *
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.
12 *
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.
17 *
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
21 *
22 *
23 * NOTES:
24 *
Takashi Iwaiab0c7d72005-11-17 15:00:18 +010025 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 * 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.
29 *
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.
33 *
34 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
35 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
36 *
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
41 *
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.
47 *
48 */
49
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>
57
58#include "ice1712.h"
59#include "envy24ht.h"
60#include "aureon.h"
61
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 */
79
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
87
Takashi Iwaiab0c7d72005-11-17 15:00:18 +010088static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 unsigned int tmp;
90
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);
101
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);
113
114 /* Send high-order byte to XILINX chip */
115 tmp &= ~AUREON_AC97_DATA_MASK;
116 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
117
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);
126
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);
134
135 /* Store the data in out private buffer */
136 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
137}
138
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100139static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
141 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
142}
143
144/*
145 * Initialize STAC9744 chip
146 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100147static int aureon_ac97_init (struct snd_ice1712 *ice) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 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
169 };
170 unsigned int tmp;
171
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);
176
177 tmp &= ~AUREON_AC97_RESET;
178 snd_ice1712_gpio_write(ice, tmp);
179 udelay(3);
180
181 tmp |= AUREON_AC97_RESET;
182 snd_ice1712_gpio_write(ice, tmp);
183 udelay(3);
184
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];
188
189 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
190
191 return 0;
192}
193
194#define AUREON_AC97_STEREO 0x80
195
196/*
197 * AC'97 volume controls
198 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100199static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
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;
206}
207
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100208static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100210 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 unsigned short vol;
212
213 down(&ice->gpio_mutex);
214
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);
219
220 up(&ice->gpio_mutex);
221 return 0;
222}
223
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100224static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100226 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 unsigned short ovol, nvol;
228 int change;
229
230 snd_ice1712_save_gpio_status(ice);
231
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;
237
238 if ((change = (ovol != nvol)))
239 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
240
241 snd_ice1712_restore_gpio_status(ice);
242
243 return change;
244}
245
246/*
247 * AC'97 mute controls
248 */
249#define aureon_ac97_mute_info aureon_mono_bool_info
250
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100251static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100253 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 down(&ice->gpio_mutex);
256
257 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
258
259 up(&ice->gpio_mutex);
260 return 0;
261}
262
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100263static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100265 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 unsigned short ovol, nvol;
267 int change;
268
269 snd_ice1712_save_gpio_status(ice);
270
271 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
272 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
273
274 if ((change = (ovol != nvol)))
275 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
276
277 snd_ice1712_restore_gpio_status(ice);
278
279 return change;
280}
281
282/*
283 * AC'97 mute controls
284 */
285#define aureon_ac97_micboost_info aureon_mono_bool_info
286
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100287static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100289 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
291 down(&ice->gpio_mutex);
292
293 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
294
295 up(&ice->gpio_mutex);
296 return 0;
297}
298
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100299static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100301 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 unsigned short ovol, nvol;
303 int change;
304
305 snd_ice1712_save_gpio_status(ice);
306
307 ovol = aureon_ac97_read(ice, AC97_MIC);
308 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
309
310 if ((change = (ovol != nvol)))
311 aureon_ac97_write(ice, AC97_MIC, nvol);
312
313 snd_ice1712_restore_gpio_status(ice);
314
315 return change;
316}
317
318/*
319 * write data in the SPI mode
320 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100321static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
323 unsigned int tmp;
324 int i;
Takashi Iwai45fe7222006-01-13 13:50:16 +0100325 unsigned int mosi, clk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 tmp = snd_ice1712_gpio_read(ice);
328
Takashi Iwai45fe7222006-01-13 13:50:16 +0100329 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) {
330 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
331 mosi = PRODIGY_SPI_MOSI;
332 clk = PRODIGY_SPI_CLK;
333 }
334 else {
335 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
336 AUREON_WM_CS|AUREON_CS8415_CS));
337 mosi = AUREON_SPI_MOSI;
338 clk = AUREON_SPI_CLK;
339
340 tmp |= AUREON_WM_RW;
341 }
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 tmp &= ~cs;
344 snd_ice1712_gpio_write(ice, tmp);
345 udelay(1);
346
347 for (i = bits - 1; i >= 0; i--) {
Takashi Iwai45fe7222006-01-13 13:50:16 +0100348 tmp &= ~clk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 snd_ice1712_gpio_write(ice, tmp);
350 udelay(1);
351 if (data & (1 << i))
Takashi Iwai45fe7222006-01-13 13:50:16 +0100352 tmp |= mosi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 else
Takashi Iwai45fe7222006-01-13 13:50:16 +0100354 tmp &= ~mosi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 snd_ice1712_gpio_write(ice, tmp);
356 udelay(1);
Takashi Iwai45fe7222006-01-13 13:50:16 +0100357 tmp |= clk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 snd_ice1712_gpio_write(ice, tmp);
359 udelay(1);
360 }
361
Takashi Iwai45fe7222006-01-13 13:50:16 +0100362 tmp &= ~clk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 tmp |= cs;
364 snd_ice1712_gpio_write(ice, tmp);
365 udelay(1);
Takashi Iwai45fe7222006-01-13 13:50:16 +0100366 tmp |= clk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 snd_ice1712_gpio_write(ice, tmp);
368 udelay(1);
369}
370
371/*
372 * Read data in SPI mode
373 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100374static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 int i, j;
376 unsigned int tmp;
377
378 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
379 snd_ice1712_gpio_write(ice, tmp);
380 tmp &= ~cs;
381 snd_ice1712_gpio_write(ice, tmp);
382 udelay(1);
383
384 for (i=bits-1; i>=0; i--) {
385 if (data & (1 << i))
386 tmp |= AUREON_SPI_MOSI;
387 else
388 tmp &= ~AUREON_SPI_MOSI;
389 snd_ice1712_gpio_write(ice, tmp);
390 udelay(1);
391
392 tmp |= AUREON_SPI_CLK;
393 snd_ice1712_gpio_write(ice, tmp);
394 udelay(1);
395
396 tmp &= ~AUREON_SPI_CLK;
397 snd_ice1712_gpio_write(ice, tmp);
398 udelay(1);
399 }
400
401 for (j=0; j<size; j++) {
402 unsigned char outdata = 0;
403 for (i=7; i>=0; i--) {
404 tmp = snd_ice1712_gpio_read(ice);
405 outdata <<= 1;
406 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
407 udelay(1);
408
409 tmp |= AUREON_SPI_CLK;
410 snd_ice1712_gpio_write(ice, tmp);
411 udelay(1);
412
413 tmp &= ~AUREON_SPI_CLK;
414 snd_ice1712_gpio_write(ice, tmp);
415 udelay(1);
416 }
417 buffer[j] = outdata;
418 }
419
420 tmp |= cs;
421 snd_ice1712_gpio_write(ice, tmp);
422}
423
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100424static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 unsigned char val;
426 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
427 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
428 return val;
429}
430
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100431static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
433 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
434}
435
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100436static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
438}
439
440/*
441 * get the current register value of WM codec
442 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100443static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
445 reg <<= 1;
446 return ((unsigned short)ice->akm[0].images[reg] << 8) |
447 ice->akm[0].images[reg + 1];
448}
449
450/*
451 * set the register value of WM codec
452 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100453static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
Takashi Iwai45fe7222006-01-13 13:50:16 +0100455 aureon_spi_write(ice,
456 (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS),
457 (reg << 9) | (val & 0x1ff), 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458}
459
460/*
461 * set the register value of WM codec and remember it
462 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100463static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
465 wm_put_nocache(ice, reg, val);
466 reg <<= 1;
467 ice->akm[0].images[reg] = val >> 8;
468 ice->akm[0].images[reg + 1] = val;
469}
470
471/*
472 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100473static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
476 uinfo->count = 1;
477 uinfo->value.integer.min = 0;
478 uinfo->value.integer.max = 1;
479 return 0;
480}
481
482/*
483 * AC'97 master playback mute controls (Mute on WM8770 chip)
484 */
485#define aureon_ac97_mmute_info aureon_mono_bool_info
486
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100487static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100489 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 down(&ice->gpio_mutex);
492
493 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
494
495 up(&ice->gpio_mutex);
496 return 0;
497}
498
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100499static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
500 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 unsigned short ovol, nvol;
502 int change;
503
504 snd_ice1712_save_gpio_status(ice);
505
506 ovol = wm_get(ice, WM_OUT_MUX1);
507 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
508 if ((change = (ovol != nvol)))
509 wm_put(ice, WM_OUT_MUX1, nvol);
510
511 snd_ice1712_restore_gpio_status(ice);
512
513 return change;
514}
515
516/*
517 * Logarithmic volume values for WM8770
518 * Computed as 20 * Log10(255 / x)
519 */
520static unsigned char wm_vol[256] = {
521 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
522 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
523 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
524 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
525 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
526 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,
527 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,
528 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,
529 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,
530 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,
531 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,
532 0, 0
533};
534
535#define WM_VOL_MAX (sizeof(wm_vol) - 1)
536#define WM_VOL_MUTE 0x8000
537
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100538static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
540 unsigned char nvol;
541
542 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
543 nvol = 0;
544 else
545 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
546
547 wm_put(ice, index, nvol);
548 wm_put_nocache(ice, index, 0x180 | nvol);
549}
550
551/*
552 * DAC mute control
553 */
554#define wm_pcm_mute_info aureon_mono_bool_info
555
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100556static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100558 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 down(&ice->gpio_mutex);
561 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
562 up(&ice->gpio_mutex);
563 return 0;
564}
565
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100566static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100568 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 unsigned short nval, oval;
570 int change;
571
572 snd_ice1712_save_gpio_status(ice);
573 oval = wm_get(ice, WM_MUTE);
574 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
575 if ((change = (nval != oval)))
576 wm_put(ice, WM_MUTE, nval);
577 snd_ice1712_restore_gpio_status(ice);
578
579 return change;
580}
581
582/*
583 * Master volume attenuation mixer control
584 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100585static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
588 uinfo->count = 2;
589 uinfo->value.integer.min = 0;
590 uinfo->value.integer.max = WM_VOL_MAX;
591 return 0;
592}
593
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100594static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100596 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 int i;
598 for (i=0; i<2; i++)
599 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
600 return 0;
601}
602
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100603static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100605 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 int ch, change = 0;
607
608 snd_ice1712_save_gpio_status(ice);
609 for (ch = 0; ch < 2; ch++) {
610 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
611 int dac;
612 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
613 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
614 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
615 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
616 ice->spec.aureon.vol[dac + ch],
617 ice->spec.aureon.master[ch]);
618 change = 1;
619 }
620 }
621 snd_ice1712_restore_gpio_status(ice);
622 return change;
623}
624
625/*
626 * DAC volume attenuation mixer control
627 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100628static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
630 int voices = kcontrol->private_value >> 8;
631 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
632 uinfo->count = voices;
633 uinfo->value.integer.min = 0; /* mute (-101dB) */
634 uinfo->value.integer.max = 0x7F; /* 0dB */
635 return 0;
636}
637
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100638static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100640 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 int i, ofs, voices;
642
643 voices = kcontrol->private_value >> 8;
644 ofs = kcontrol->private_value & 0xff;
645 for (i = 0; i < voices; i++)
646 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
647 return 0;
648}
649
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100650static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100652 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 int i, idx, ofs, voices;
654 int change = 0;
655
656 voices = kcontrol->private_value >> 8;
657 ofs = kcontrol->private_value & 0xff;
658 snd_ice1712_save_gpio_status(ice);
659 for (i = 0; i < voices; i++) {
660 idx = WM_DAC_ATTEN + ofs + i;
661 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
662 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
663 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
664 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
665 ice->spec.aureon.master[i]);
666 change = 1;
667 }
668 }
669 snd_ice1712_restore_gpio_status(ice);
670 return change;
671}
672
673/*
674 * WM8770 mute control
675 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100676static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
678 uinfo->count = kcontrol->private_value >> 8;
679 uinfo->value.integer.min = 0;
680 uinfo->value.integer.max = 1;
681 return 0;
682}
683
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100684static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100686 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 int voices, ofs, i;
688
689 voices = kcontrol->private_value >> 8;
690 ofs = kcontrol->private_value & 0xFF;
691
692 for (i = 0; i < voices; i++)
693 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
694 return 0;
695}
696
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100697static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100699 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 int change = 0, voices, ofs, i;
701
702 voices = kcontrol->private_value >> 8;
703 ofs = kcontrol->private_value & 0xFF;
704
705 snd_ice1712_save_gpio_status(ice);
706 for (i = 0; i < voices; i++) {
707 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
708 if (ucontrol->value.integer.value[i] != val) {
709 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
710 ice->spec.aureon.vol[ofs + i] |=
711 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
712 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
713 ice->spec.aureon.master[i]);
714 change = 1;
715 }
716 }
717 snd_ice1712_restore_gpio_status(ice);
718
719 return change;
720}
721
722/*
723 * WM8770 master mute control
724 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100725static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
727 uinfo->count = 2;
728 uinfo->value.integer.min = 0;
729 uinfo->value.integer.max = 1;
730 return 0;
731}
732
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100733static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100735 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
738 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
739 return 0;
740}
741
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100742static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100744 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 int change = 0, i;
746
747 snd_ice1712_save_gpio_status(ice);
748 for (i = 0; i < 2; i++) {
749 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
750 if (ucontrol->value.integer.value[i] != val) {
751 int dac;
752 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
753 ice->spec.aureon.master[i] |=
754 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
755 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
756 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
757 ice->spec.aureon.vol[dac + i],
758 ice->spec.aureon.master[i]);
759 change = 1;
760 }
761 }
762 snd_ice1712_restore_gpio_status(ice);
763
764 return change;
765}
766
767/* digital master volume */
768#define PCM_0dB 0xff
769#define PCM_RES 128 /* -64dB */
770#define PCM_MIN (PCM_0dB - PCM_RES)
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100771static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
774 uinfo->count = 1;
775 uinfo->value.integer.min = 0; /* mute (-64dB) */
776 uinfo->value.integer.max = PCM_RES; /* 0dB */
777 return 0;
778}
779
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100780static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100782 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 unsigned short val;
784
785 down(&ice->gpio_mutex);
786 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
787 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
788 ucontrol->value.integer.value[0] = val;
789 up(&ice->gpio_mutex);
790 return 0;
791}
792
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100793static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100795 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 unsigned short ovol, nvol;
797 int change = 0;
798
799 snd_ice1712_save_gpio_status(ice);
800 nvol = ucontrol->value.integer.value[0];
801 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
802 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
803 if (ovol != nvol) {
804 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
805 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
806 change = 1;
807 }
808 snd_ice1712_restore_gpio_status(ice);
809 return change;
810}
811
812/*
813 * ADC mute control
814 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100815static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
817 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
818 uinfo->count = 2;
819 uinfo->value.integer.min = 0;
820 uinfo->value.integer.max = 1;
821 return 0;
822}
823
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100824static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100826 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 unsigned short val;
828 int i;
829
830 down(&ice->gpio_mutex);
831 for (i = 0; i < 2; i++) {
832 val = wm_get(ice, WM_ADC_GAIN + i);
833 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
834 }
835 up(&ice->gpio_mutex);
836 return 0;
837}
838
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100839static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100841 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 unsigned short new, old;
843 int i, change = 0;
844
845 snd_ice1712_save_gpio_status(ice);
846 for (i = 0; i < 2; i++) {
847 old = wm_get(ice, WM_ADC_GAIN + i);
848 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
849 if (new != old) {
850 wm_put(ice, WM_ADC_GAIN + i, new);
851 change = 1;
852 }
853 }
854 snd_ice1712_restore_gpio_status(ice);
855
856 return change;
857}
858
859/*
860 * ADC gain mixer control
861 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100862static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
864 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
865 uinfo->count = 2;
866 uinfo->value.integer.min = 0; /* -12dB */
867 uinfo->value.integer.max = 0x1f; /* 19dB */
868 return 0;
869}
870
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100871static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100873 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 int i, idx;
875 unsigned short vol;
876
877 down(&ice->gpio_mutex);
878 for (i = 0; i < 2; i++) {
879 idx = WM_ADC_GAIN + i;
880 vol = wm_get(ice, idx) & 0x1f;
881 ucontrol->value.integer.value[i] = vol;
882 }
883 up(&ice->gpio_mutex);
884 return 0;
885}
886
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100887static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100889 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 int i, idx;
891 unsigned short ovol, nvol;
892 int change = 0;
893
894 snd_ice1712_save_gpio_status(ice);
895 for (i = 0; i < 2; i++) {
896 idx = WM_ADC_GAIN + i;
897 nvol = ucontrol->value.integer.value[i];
898 ovol = wm_get(ice, idx);
899 if ((ovol & 0x1f) != nvol) {
900 wm_put(ice, idx, nvol | (ovol & ~0x1f));
901 change = 1;
902 }
903 }
904 snd_ice1712_restore_gpio_status(ice);
905 return change;
906}
907
908/*
909 * ADC input mux mixer control
910 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100911static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
913 static char *texts[] = {
914 "CD", //AIN1
915 "Aux", //AIN2
916 "Line", //AIN3
917 "Mic", //AIN4
918 "AC97" //AIN5
919 };
920 static char *universe_texts[] = {
921 "Aux1", //AIN1
922 "CD", //AIN2
923 "Phono", //AIN3
924 "Line", //AIN4
925 "Aux2", //AIN5
926 "Mic", //AIN6
927 "Aux3", //AIN7
928 "AC97" //AIN8
929 };
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100930 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
932 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
933 uinfo->count = 2;
934 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
935 uinfo->value.enumerated.items = 8;
936 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
937 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
938 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
939 }
940 else {
941 uinfo->value.enumerated.items = 5;
942 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
943 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
944 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
945 }
946 return 0;
947}
948
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100949static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100951 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 unsigned short val;
953
954 down(&ice->gpio_mutex);
955 val = wm_get(ice, WM_ADC_MUX);
956 ucontrol->value.integer.value[0] = val & 7;
957 ucontrol->value.integer.value[1] = (val >> 4) & 7;
958 up(&ice->gpio_mutex);
959 return 0;
960}
961
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100962static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100964 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 unsigned short oval, nval;
966 int change;
967
968 snd_ice1712_save_gpio_status(ice);
969 oval = wm_get(ice, WM_ADC_MUX);
970 nval = oval & ~0x77;
971 nval |= ucontrol->value.integer.value[0] & 7;
972 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
973 change = (oval != nval);
974 if (change)
975 wm_put(ice, WM_ADC_MUX, nval);
976 snd_ice1712_restore_gpio_status(ice);
Takashi Iwai63786d02005-11-04 13:58:11 +0100977 return change;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978}
979
980/*
981 * CS8415 Input mux
982 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100983static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +0100985 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 static char *aureon_texts[] = {
987 "CD", //RXP0
988 "Optical" //RXP1
989 };
990 static char *prodigy_texts[] = {
991 "CD",
992 "Coax"
993 };
994 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
995 uinfo->count = 1;
996 uinfo->value.enumerated.items = 2;
997 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
998 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
999 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1000 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1001 else
1002 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1003 return 0;
1004}
1005
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001006static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001008 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
1010 //snd_ice1712_save_gpio_status(ice);
1011 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1012 ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
1013 //snd_ice1712_restore_gpio_status(ice);
1014 return 0;
1015}
1016
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001017static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001019 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 unsigned short oval, nval;
1021 int change;
1022
1023 snd_ice1712_save_gpio_status(ice);
1024 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1025 nval = oval & ~0x07;
1026 nval |= ucontrol->value.integer.value[0] & 7;
1027 change = (oval != nval);
1028 if (change)
1029 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1030 snd_ice1712_restore_gpio_status(ice);
1031 ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
1032 return change;
1033}
1034
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001035static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036{
1037 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1038 uinfo->count = 1;
1039 uinfo->value.integer.min = 0;
1040 uinfo->value.integer.max = 192000;
1041 return 0;
1042}
1043
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001044static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001046 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 unsigned char ratio;
1048 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1049 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1050 return 0;
1051}
1052
1053/*
1054 * CS8415A Mute
1055 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001056static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057{
1058 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1059 uinfo->count = 1;
1060 return 0;
1061}
1062
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001063static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001065 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 snd_ice1712_save_gpio_status(ice);
1067 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1068 snd_ice1712_restore_gpio_status(ice);
1069 return 0;
1070}
1071
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001072static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001074 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 unsigned char oval, nval;
1076 int change;
1077 snd_ice1712_save_gpio_status(ice);
1078 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1079 if (ucontrol->value.integer.value[0])
1080 nval = oval & ~0x20;
1081 else
1082 nval = oval | 0x20;
1083 if ((change = (oval != nval)))
1084 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1085 snd_ice1712_restore_gpio_status(ice);
1086 return change;
1087}
1088
1089/*
1090 * CS8415A Q-Sub info
1091 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001092static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1094 uinfo->count = 10;
1095 return 0;
1096}
1097
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001098static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1099 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 snd_ice1712_save_gpio_status(ice);
1102 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1103 snd_ice1712_restore_gpio_status(ice);
1104
1105 return 0;
1106}
1107
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001108static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1110 uinfo->count = 1;
1111 return 0;
1112}
1113
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001114static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 memset(ucontrol->value.iec958.status, 0xFF, 24);
1116 return 0;
1117}
1118
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001119static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1120 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 snd_ice1712_save_gpio_status(ice);
1123 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1124 snd_ice1712_restore_gpio_status(ice);
1125 return 0;
1126}
1127
1128/*
1129 * Headphone Amplifier
1130 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001131static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 unsigned int tmp, tmp2;
1134
1135 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1136 if (enable)
1137 tmp |= AUREON_HP_SEL;
1138 else
1139 tmp &= ~ AUREON_HP_SEL;
1140 if (tmp != tmp2) {
1141 snd_ice1712_gpio_write(ice, tmp);
1142 return 1;
1143 }
1144 return 0;
1145}
1146
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001147static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
1149 unsigned int tmp = snd_ice1712_gpio_read(ice);
1150
1151 return ( tmp & AUREON_HP_SEL )!= 0;
1152}
1153
1154#define aureon_hpamp_info aureon_mono_bool_info
1155
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001156static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001158 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
1160 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1161 return 0;
1162}
1163
1164
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001165static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001167 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
1169 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1170}
1171
1172/*
1173 * Deemphasis
1174 */
1175
1176#define aureon_deemp_info aureon_mono_bool_info
1177
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001178static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001180 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1182 return 0;
1183}
1184
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001185static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001187 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 int temp, temp2;
1189 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1190 if (ucontrol->value.integer.value[0])
1191 temp |= 0xf;
1192 else
1193 temp &= ~0xf;
1194 if (temp != temp2) {
1195 wm_put(ice, WM_DAC_CTRL2, temp);
1196 return 1;
1197 }
1198 return 0;
1199}
1200
1201/*
1202 * ADC Oversampling
1203 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001204static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
1206 static char *texts[2] = { "128x", "64x" };
1207
1208 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1209 uinfo->count = 1;
1210 uinfo->value.enumerated.items = 2;
1211
1212 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1213 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1214 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1215
1216 return 0;
1217}
1218
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001219static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220{
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001221 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1223 return 0;
1224}
1225
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001226static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227{
1228 int temp, temp2;
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001229 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 temp2 = temp = wm_get(ice, WM_MASTER);
1232
1233 if (ucontrol->value.enumerated.item[0])
1234 temp |= 0x8;
1235 else
1236 temp &= ~0x8;
1237
1238 if (temp != temp2) {
1239 wm_put(ice, WM_MASTER, temp);
1240 return 1;
1241 }
1242 return 0;
1243}
1244
1245/*
1246 * mixers
1247 */
1248
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001249static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 {
1251 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1252 .name = "Master Playback Switch",
1253 .info = wm_master_mute_info,
1254 .get = wm_master_mute_get,
1255 .put = wm_master_mute_put
1256 },
1257 {
1258 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1259 .name = "Master Playback Volume",
1260 .info = wm_master_vol_info,
1261 .get = wm_master_vol_get,
1262 .put = wm_master_vol_put
1263 },
1264 {
1265 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1266 .name = "Front Playback Switch",
1267 .info = wm_mute_info,
1268 .get = wm_mute_get,
1269 .put = wm_mute_put,
1270 .private_value = (2 << 8) | 0
1271 },
1272 {
1273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1274 .name = "Front Playback Volume",
1275 .info = wm_vol_info,
1276 .get = wm_vol_get,
1277 .put = wm_vol_put,
1278 .private_value = (2 << 8) | 0
1279 },
1280 {
1281 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1282 .name = "Rear Playback Switch",
1283 .info = wm_mute_info,
1284 .get = wm_mute_get,
1285 .put = wm_mute_put,
1286 .private_value = (2 << 8) | 2
1287 },
1288 {
1289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1290 .name = "Rear Playback Volume",
1291 .info = wm_vol_info,
1292 .get = wm_vol_get,
1293 .put = wm_vol_put,
1294 .private_value = (2 << 8) | 2
1295 },
1296 {
1297 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1298 .name = "Center Playback Switch",
1299 .info = wm_mute_info,
1300 .get = wm_mute_get,
1301 .put = wm_mute_put,
1302 .private_value = (1 << 8) | 4
1303 },
1304 {
1305 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1306 .name = "Center Playback Volume",
1307 .info = wm_vol_info,
1308 .get = wm_vol_get,
1309 .put = wm_vol_put,
1310 .private_value = (1 << 8) | 4
1311 },
1312 {
1313 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1314 .name = "LFE Playback Switch",
1315 .info = wm_mute_info,
1316 .get = wm_mute_get,
1317 .put = wm_mute_put,
1318 .private_value = (1 << 8) | 5
1319 },
1320 {
1321 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1322 .name = "LFE Playback Volume",
1323 .info = wm_vol_info,
1324 .get = wm_vol_get,
1325 .put = wm_vol_put,
1326 .private_value = (1 << 8) | 5
1327 },
1328 {
1329 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1330 .name = "Side Playback Switch",
1331 .info = wm_mute_info,
1332 .get = wm_mute_get,
1333 .put = wm_mute_put,
1334 .private_value = (2 << 8) | 6
1335 },
1336 {
1337 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1338 .name = "Side Playback Volume",
1339 .info = wm_vol_info,
1340 .get = wm_vol_get,
1341 .put = wm_vol_put,
1342 .private_value = (2 << 8) | 6
1343 }
1344};
1345
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001346static struct snd_kcontrol_new wm_controls[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 {
1348 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1349 .name = "PCM Playback Switch",
1350 .info = wm_pcm_mute_info,
1351 .get = wm_pcm_mute_get,
1352 .put = wm_pcm_mute_put
1353 },
1354 {
1355 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1356 .name = "PCM Playback Volume",
1357 .info = wm_pcm_vol_info,
1358 .get = wm_pcm_vol_get,
1359 .put = wm_pcm_vol_put
1360 },
1361 {
1362 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1363 .name = "Capture Switch",
1364 .info = wm_adc_mute_info,
1365 .get = wm_adc_mute_get,
1366 .put = wm_adc_mute_put,
1367 },
1368 {
1369 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1370 .name = "Capture Volume",
1371 .info = wm_adc_vol_info,
1372 .get = wm_adc_vol_get,
1373 .put = wm_adc_vol_put
1374 },
1375 {
1376 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1377 .name = "Capture Source",
1378 .info = wm_adc_mux_info,
1379 .get = wm_adc_mux_get,
1380 .put = wm_adc_mux_put,
1381 .private_value = 5
1382 },
1383 {
1384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1385 .name = "External Amplifier",
1386 .info = aureon_hpamp_info,
1387 .get = aureon_hpamp_get,
1388 .put = aureon_hpamp_put
1389 },
1390 {
1391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1392 .name = "DAC Deemphasis Switch",
1393 .info = aureon_deemp_info,
1394 .get = aureon_deemp_get,
1395 .put = aureon_deemp_put
1396 },
1397 {
1398 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1399 .name = "ADC Oversampling",
1400 .info = aureon_oversampling_info,
1401 .get = aureon_oversampling_get,
1402 .put = aureon_oversampling_put
1403 }
1404};
1405
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001406static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 {
1408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1409 .name = "AC97 Playback Switch",
1410 .info = aureon_ac97_mmute_info,
1411 .get = aureon_ac97_mmute_get,
1412 .put = aureon_ac97_mmute_put,
1413 .private_value = AC97_MASTER
1414 },
1415 {
1416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1417 .name = "AC97 Playback Volume",
1418 .info = aureon_ac97_vol_info,
1419 .get = aureon_ac97_vol_get,
1420 .put = aureon_ac97_vol_put,
1421 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1422 },
1423 {
1424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1425 .name = "CD Playback Switch",
1426 .info = aureon_ac97_mute_info,
1427 .get = aureon_ac97_mute_get,
1428 .put = aureon_ac97_mute_put,
1429 .private_value = AC97_CD
1430 },
1431 {
1432 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1433 .name = "CD Playback Volume",
1434 .info = aureon_ac97_vol_info,
1435 .get = aureon_ac97_vol_get,
1436 .put = aureon_ac97_vol_put,
1437 .private_value = AC97_CD|AUREON_AC97_STEREO
1438 },
1439 {
1440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1441 .name = "Aux Playback Switch",
1442 .info = aureon_ac97_mute_info,
1443 .get = aureon_ac97_mute_get,
1444 .put = aureon_ac97_mute_put,
1445 .private_value = AC97_AUX,
1446 },
1447 {
1448 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1449 .name = "Aux Playback Volume",
1450 .info = aureon_ac97_vol_info,
1451 .get = aureon_ac97_vol_get,
1452 .put = aureon_ac97_vol_put,
1453 .private_value = AC97_AUX|AUREON_AC97_STEREO
1454 },
1455 {
1456 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1457 .name = "Line Playback Switch",
1458 .info = aureon_ac97_mute_info,
1459 .get = aureon_ac97_mute_get,
1460 .put = aureon_ac97_mute_put,
1461 .private_value = AC97_LINE
1462 },
1463 {
1464 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1465 .name = "Line Playback Volume",
1466 .info = aureon_ac97_vol_info,
1467 .get = aureon_ac97_vol_get,
1468 .put = aureon_ac97_vol_put,
1469 .private_value = AC97_LINE|AUREON_AC97_STEREO
1470 },
1471 {
1472 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1473 .name = "Mic Playback Switch",
1474 .info = aureon_ac97_mute_info,
1475 .get = aureon_ac97_mute_get,
1476 .put = aureon_ac97_mute_put,
1477 .private_value = AC97_MIC
1478 },
1479 {
1480 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1481 .name = "Mic Playback Volume",
1482 .info = aureon_ac97_vol_info,
1483 .get = aureon_ac97_vol_get,
1484 .put = aureon_ac97_vol_put,
1485 .private_value = AC97_MIC
1486 },
1487 {
1488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1489 .name = "Mic Boost (+20dB)",
1490 .info = aureon_ac97_micboost_info,
1491 .get = aureon_ac97_micboost_get,
1492 .put = aureon_ac97_micboost_put
1493 }
1494};
1495
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001496static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 {
1498 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1499 .name = "AC97 Playback Switch",
1500 .info = aureon_ac97_mmute_info,
1501 .get = aureon_ac97_mmute_get,
1502 .put = aureon_ac97_mmute_put,
1503 .private_value = AC97_MASTER
1504 },
1505 {
1506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1507 .name = "AC97 Playback Volume",
1508 .info = aureon_ac97_vol_info,
1509 .get = aureon_ac97_vol_get,
1510 .put = aureon_ac97_vol_put,
1511 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1512 },
1513 {
1514 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1515 .name = "CD Playback Switch",
1516 .info = aureon_ac97_mute_info,
1517 .get = aureon_ac97_mute_get,
1518 .put = aureon_ac97_mute_put,
1519 .private_value = AC97_AUX
1520 },
1521 {
1522 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1523 .name = "CD Playback Volume",
1524 .info = aureon_ac97_vol_info,
1525 .get = aureon_ac97_vol_get,
1526 .put = aureon_ac97_vol_put,
1527 .private_value = AC97_AUX|AUREON_AC97_STEREO
1528 },
1529 {
1530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1531 .name = "Phono Playback Switch",
1532 .info = aureon_ac97_mute_info,
1533 .get = aureon_ac97_mute_get,
1534 .put = aureon_ac97_mute_put,
1535 .private_value = AC97_CD,
1536 },
1537 {
1538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1539 .name = "Phono Playback Volume",
1540 .info = aureon_ac97_vol_info,
1541 .get = aureon_ac97_vol_get,
1542 .put = aureon_ac97_vol_put,
1543 .private_value = AC97_CD|AUREON_AC97_STEREO
1544 },
1545 {
1546 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1547 .name = "Line Playback Switch",
1548 .info = aureon_ac97_mute_info,
1549 .get = aureon_ac97_mute_get,
1550 .put = aureon_ac97_mute_put,
1551 .private_value = AC97_LINE
1552 },
1553 {
1554 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1555 .name = "Line Playback Volume",
1556 .info = aureon_ac97_vol_info,
1557 .get = aureon_ac97_vol_get,
1558 .put = aureon_ac97_vol_put,
1559 .private_value = AC97_LINE|AUREON_AC97_STEREO
1560 },
1561 {
1562 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1563 .name = "Mic Playback Switch",
1564 .info = aureon_ac97_mute_info,
1565 .get = aureon_ac97_mute_get,
1566 .put = aureon_ac97_mute_put,
1567 .private_value = AC97_MIC
1568 },
1569 {
1570 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1571 .name = "Mic Playback Volume",
1572 .info = aureon_ac97_vol_info,
1573 .get = aureon_ac97_vol_get,
1574 .put = aureon_ac97_vol_put,
1575 .private_value = AC97_MIC
1576 },
1577 {
1578 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1579 .name = "Mic Boost (+20dB)",
1580 .info = aureon_ac97_micboost_info,
1581 .get = aureon_ac97_micboost_get,
1582 .put = aureon_ac97_micboost_put
1583 },
1584 {
1585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586 .name = "Aux Playback Switch",
1587 .info = aureon_ac97_mute_info,
1588 .get = aureon_ac97_mute_get,
1589 .put = aureon_ac97_mute_put,
1590 .private_value = AC97_VIDEO,
1591 },
1592 {
1593 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1594 .name = "Aux Playback Volume",
1595 .info = aureon_ac97_vol_info,
1596 .get = aureon_ac97_vol_get,
1597 .put = aureon_ac97_vol_put,
1598 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1599 }
1600};
1601
1602
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001603static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 {
1605 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1606 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1607 .info = aureon_cs8415_mute_info,
1608 .get = aureon_cs8415_mute_get,
1609 .put = aureon_cs8415_mute_put
1610 },
1611 {
1612 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1613 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1614 .info = aureon_cs8415_mux_info,
1615 .get = aureon_cs8415_mux_get,
1616 .put = aureon_cs8415_mux_put,
1617 },
1618 {
1619 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1620 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1621 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1622 .info = aureon_cs8415_qsub_info,
1623 .get = aureon_cs8415_qsub_get,
1624 },
1625 {
1626 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1627 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1628 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1629 .info = aureon_cs8415_spdif_info,
1630 .get = aureon_cs8415_mask_get
1631 },
1632 {
1633 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1634 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1635 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1636 .info = aureon_cs8415_spdif_info,
1637 .get = aureon_cs8415_spdif_get
1638 },
1639 {
1640 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1641 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1642 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1643 .info = aureon_cs8415_rate_info,
1644 .get = aureon_cs8415_rate_get
1645 }
1646};
1647
1648
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001649static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650{
1651 unsigned int i, counts;
1652 int err;
1653
1654 counts = ARRAY_SIZE(aureon_dac_controls);
1655 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1656 counts -= 2; /* no side */
1657 for (i = 0; i < counts; i++) {
1658 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1659 if (err < 0)
1660 return err;
1661 }
1662
1663 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1664 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1665 if (err < 0)
1666 return err;
1667 }
1668
1669 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1670 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1671 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1672 if (err < 0)
1673 return err;
1674 }
1675 }
Takashi Iwai45fe7222006-01-13 13:50:16 +01001676 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1678 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1679 if (err < 0)
1680 return err;
1681 }
1682 }
1683
Takashi Iwai45fe7222006-01-13 13:50:16 +01001684 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 unsigned char id;
1686 snd_ice1712_save_gpio_status(ice);
1687 id = aureon_cs8415_get(ice, CS8415_ID);
1688 if (id != 0x41)
Takashi Iwai99b359b2005-10-20 18:26:44 +02001689 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 else if ((id & 0x0F) != 0x01)
Takashi Iwai99b359b2005-10-20 18:26:44 +02001691 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 else {
1693 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001694 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1696 if (err < 0)
1697 return err;
1698 if (i > 1)
1699 kctl->id.device = ice->pcm->device;
1700 }
1701 }
1702 snd_ice1712_restore_gpio_status(ice);
1703 }
1704
1705 return 0;
1706}
1707
1708
1709/*
1710 * initialize the chip
1711 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001712static int __devinit aureon_init(struct snd_ice1712 *ice)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
1714 static unsigned short wm_inits_aureon[] = {
1715 /* These come first to reduce init pop noise */
1716 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1717 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1718 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1719
1720 0x18, 0x000, /* All power-up */
1721
1722 0x16, 0x122, /* I2S, normal polarity, 24bit */
1723 0x17, 0x022, /* 256fs, slave mode */
1724 0x00, 0, /* DAC1 analog mute */
1725 0x01, 0, /* DAC2 analog mute */
1726 0x02, 0, /* DAC3 analog mute */
1727 0x03, 0, /* DAC4 analog mute */
1728 0x04, 0, /* DAC5 analog mute */
1729 0x05, 0, /* DAC6 analog mute */
1730 0x06, 0, /* DAC7 analog mute */
1731 0x07, 0, /* DAC8 analog mute */
1732 0x08, 0x100, /* master analog mute */
1733 0x09, 0xff, /* DAC1 digital full */
1734 0x0a, 0xff, /* DAC2 digital full */
1735 0x0b, 0xff, /* DAC3 digital full */
1736 0x0c, 0xff, /* DAC4 digital full */
1737 0x0d, 0xff, /* DAC5 digital full */
1738 0x0e, 0xff, /* DAC6 digital full */
1739 0x0f, 0xff, /* DAC7 digital full */
1740 0x10, 0xff, /* DAC8 digital full */
1741 0x11, 0x1ff, /* master digital full */
1742 0x12, 0x000, /* phase normal */
1743 0x13, 0x090, /* unmute DAC L/R */
1744 0x14, 0x000, /* all unmute */
1745 0x15, 0x000, /* no deemphasis, no ZFLG */
1746 0x19, 0x000, /* -12dB ADC/L */
1747 0x1a, 0x000, /* -12dB ADC/R */
1748 (unsigned short)-1
1749 };
1750 static unsigned short wm_inits_prodigy[] = {
1751
1752 /* These come first to reduce init pop noise */
1753 0x1b, 0x000, /* ADC Mux */
1754 0x1c, 0x009, /* Out Mux1 */
1755 0x1d, 0x009, /* Out Mux2 */
1756
1757 0x18, 0x000, /* All power-up */
1758
1759 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1760 0x17, 0x006, /* 128fs, slave mode */
1761
1762 0x00, 0, /* DAC1 analog mute */
1763 0x01, 0, /* DAC2 analog mute */
1764 0x02, 0, /* DAC3 analog mute */
1765 0x03, 0, /* DAC4 analog mute */
1766 0x04, 0, /* DAC5 analog mute */
1767 0x05, 0, /* DAC6 analog mute */
1768 0x06, 0, /* DAC7 analog mute */
1769 0x07, 0, /* DAC8 analog mute */
1770 0x08, 0x100, /* master analog mute */
1771
1772 0x09, 0x7f, /* DAC1 digital full */
1773 0x0a, 0x7f, /* DAC2 digital full */
1774 0x0b, 0x7f, /* DAC3 digital full */
1775 0x0c, 0x7f, /* DAC4 digital full */
1776 0x0d, 0x7f, /* DAC5 digital full */
1777 0x0e, 0x7f, /* DAC6 digital full */
1778 0x0f, 0x7f, /* DAC7 digital full */
1779 0x10, 0x7f, /* DAC8 digital full */
1780 0x11, 0x1FF, /* master digital full */
1781
1782 0x12, 0x000, /* phase normal */
1783 0x13, 0x090, /* unmute DAC L/R */
1784 0x14, 0x000, /* all unmute */
1785 0x15, 0x000, /* no deemphasis, no ZFLG */
1786
1787 0x19, 0x000, /* -12dB ADC/L */
1788 0x1a, 0x000, /* -12dB ADC/R */
1789 (unsigned short)-1
1790
1791 };
1792 static unsigned short cs_inits[] = {
1793 0x0441, /* RUN */
1794 0x0180, /* no mute, OMCK output on RMCK pin */
1795 0x0201, /* S/PDIF source on RXP1 */
1796 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1797 (unsigned short)-1
1798 };
1799 unsigned int tmp;
1800 unsigned short *p;
1801 int err, i;
1802
1803 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1804 ice->num_total_dacs = 6;
1805 ice->num_total_adcs = 2;
1806 } else {
1807 /* aureon 7.1 and prodigy 7.1 */
1808 ice->num_total_dacs = 8;
1809 ice->num_total_adcs = 2;
1810 }
1811
1812 /* to remeber the register values of CS8415 */
Takashi Iwaiab0c7d72005-11-17 15:00:18 +01001813 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 if (! ice->akm)
1815 return -ENOMEM;
1816 ice->akm_codecs = 1;
1817
1818 if ((err = aureon_ac97_init(ice)) != 0)
1819 return err;
1820
1821 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1822
1823 /* reset the wm codec as the SPI mode */
1824 snd_ice1712_save_gpio_status(ice);
1825 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1826
1827 tmp = snd_ice1712_gpio_read(ice);
1828 tmp &= ~AUREON_WM_RESET;
1829 snd_ice1712_gpio_write(ice, tmp);
1830 udelay(1);
1831 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1832 snd_ice1712_gpio_write(ice, tmp);
1833 udelay(1);
1834 tmp |= AUREON_WM_RESET;
1835 snd_ice1712_gpio_write(ice, tmp);
1836 udelay(1);
1837
1838 /* initialize WM8770 codec */
Takashi Iwai45fe7222006-01-13 13:50:16 +01001839 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
1840 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 p = wm_inits_prodigy;
1842 else
1843 p = wm_inits_aureon;
1844 for (; *p != (unsigned short)-1; p += 2)
1845 wm_put(ice, p[0], p[1]);
1846
1847 /* initialize CS8415A codec */
Takashi Iwai45fe7222006-01-13 13:50:16 +01001848 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
1849 for (p = cs_inits; *p != (unsigned short)-1; p++)
1850 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
1851 ice->spec.aureon.cs8415_mux = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Takashi Iwai45fe7222006-01-13 13:50:16 +01001853 aureon_set_headphone_amp(ice, 1);
1854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855
1856 snd_ice1712_restore_gpio_status(ice);
1857
1858 ice->spec.aureon.master[0] = WM_VOL_MUTE;
1859 ice->spec.aureon.master[1] = WM_VOL_MUTE;
1860 for (i = 0; i < ice->num_total_dacs; i++) {
1861 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1862 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1863 }
1864
1865 return 0;
1866}
1867
1868
1869/*
1870 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1871 * hence the driver needs to sets up it properly.
1872 */
1873
1874static unsigned char aureon51_eeprom[] __devinitdata = {
1875 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1876 0x80, /* ACLINK: I2S */
1877 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1878 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1879 0xff, /* GPIO_DIR */
1880 0xff, /* GPIO_DIR1 */
1881 0x5f, /* GPIO_DIR2 */
1882 0x00, /* GPIO_MASK */
1883 0x00, /* GPIO_MASK1 */
1884 0x00, /* GPIO_MASK2 */
1885 0x00, /* GPIO_STATE */
1886 0x00, /* GPIO_STATE1 */
1887 0x00, /* GPIO_STATE2 */
1888};
1889
1890static unsigned char aureon71_eeprom[] __devinitdata = {
1891 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1892 0x80, /* ACLINK: I2S */
1893 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1894 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1895 0xff, /* GPIO_DIR */
1896 0xff, /* GPIO_DIR1 */
1897 0x5f, /* GPIO_DIR2 */
1898 0x00, /* GPIO_MASK */
1899 0x00, /* GPIO_MASK1 */
1900 0x00, /* GPIO_MASK2 */
1901 0x00, /* GPIO_STATE */
1902 0x00, /* GPIO_STATE1 */
1903 0x00, /* GPIO_STATE2 */
1904};
1905
1906static unsigned char prodigy71_eeprom[] __devinitdata = {
1907 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1908 0x80, /* ACLINK: I2S */
1909 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1910 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1911 0xff, /* GPIO_DIR */
1912 0xff, /* GPIO_DIR1 */
1913 0x5f, /* GPIO_DIR2 */
1914 0x00, /* GPIO_MASK */
1915 0x00, /* GPIO_MASK1 */
1916 0x00, /* GPIO_MASK2 */
1917 0x00, /* GPIO_STATE */
1918 0x00, /* GPIO_STATE1 */
1919 0x00, /* GPIO_STATE2 */
1920};
1921
Takashi Iwai45fe7222006-01-13 13:50:16 +01001922static unsigned char prodigy71lt_eeprom[] __devinitdata = {
1923 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
1924 0x80, /* ACLINK: I2S */
1925 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1926 0xc3, /* SPDUF: out-en, out-int */
1927 0x00, /* GPIO_DIR */
1928 0x07, /* GPIO_DIR1 */
1929 0x00, /* GPIO_DIR2 */
1930 0xff, /* GPIO_MASK */
1931 0xf8, /* GPIO_MASK1 */
1932 0xff, /* GPIO_MASK2 */
1933 0x00, /* GPIO_STATE */
1934 0x00, /* GPIO_STATE1 */
1935 0x00, /* GPIO_STATE2 */
1936};
1937
1938
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939/* entry point */
1940struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1941 {
1942 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1943 .name = "Terratec Aureon 5.1-Sky",
1944 .model = "aureon51",
1945 .chip_init = aureon_init,
1946 .build_controls = aureon_add_controls,
1947 .eeprom_size = sizeof(aureon51_eeprom),
1948 .eeprom_data = aureon51_eeprom,
1949 .driver = "Aureon51",
1950 },
1951 {
1952 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1953 .name = "Terratec Aureon 7.1-Space",
1954 .model = "aureon71",
1955 .chip_init = aureon_init,
1956 .build_controls = aureon_add_controls,
1957 .eeprom_size = sizeof(aureon71_eeprom),
1958 .eeprom_data = aureon71_eeprom,
1959 .driver = "Aureon71",
1960 },
1961 {
1962 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1963 .name = "Terratec Aureon 7.1-Universe",
1964 .model = "universe",
1965 .chip_init = aureon_init,
1966 .build_controls = aureon_add_controls,
1967 .eeprom_size = sizeof(aureon71_eeprom),
1968 .eeprom_data = aureon71_eeprom,
1969 .driver = "Aureon71Universe",
1970 },
1971 {
1972 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1973 .name = "Audiotrak Prodigy 7.1",
1974 .model = "prodigy71",
1975 .chip_init = aureon_init,
1976 .build_controls = aureon_add_controls,
1977 .eeprom_size = sizeof(prodigy71_eeprom),
1978 .eeprom_data = prodigy71_eeprom,
1979 .driver = "Prodigy71", /* should be identical with Aureon71 */
1980 },
Takashi Iwai45fe7222006-01-13 13:50:16 +01001981 {
1982 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
1983 .name = "Audiotrak Prodigy 7.1 LT",
1984 .model = "prodigy71lt",
1985 .chip_init = aureon_init,
1986 .build_controls = aureon_add_controls,
1987 .eeprom_size = sizeof(prodigy71lt_eeprom),
1988 .eeprom_data = prodigy71lt_eeprom,
1989 .driver = "Prodigy71LT",
1990 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 { } /* terminator */
1992};