[ALSA] hda-codec - Check value range in ctl callbacks
[deliverable/linux.git] / sound / pci / ice1712 / aureon.c
CommitLineData
1da177e4
LT
1/*
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 *
ab0c7d72 25 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
1da177e4
LT
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.
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>
62932df8
IM
56#include <linux/mutex.h>
57
1da177e4
LT
58#include <sound/core.h>
59
60#include "ice1712.h"
61#include "envy24ht.h"
62#include "aureon.h"
f640c320 63#include <sound/tlv.h>
1da177e4
LT
64
65/* WM8770 registers */
66#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
67#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
68#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
69#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
70#define WM_PHASE_SWAP 0x12 /* DAC phase */
71#define WM_DAC_CTRL1 0x13 /* DAC control bits */
72#define WM_MUTE 0x14 /* mute controls */
73#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
74#define WM_INT_CTRL 0x16 /* interface control */
75#define WM_MASTER 0x17 /* master clock and mode */
76#define WM_POWERDOWN 0x18 /* power-down controls */
77#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
78#define WM_ADC_MUX 0x1b /* input MUX */
79#define WM_OUT_MUX1 0x1c /* output MUX */
80#define WM_OUT_MUX2 0x1e /* output MUX */
81#define WM_RESET 0x1f /* software reset */
82
83/* CS8415A registers */
84#define CS8415_CTRL1 0x01
85#define CS8415_CTRL2 0x02
86#define CS8415_QSUB 0x14
87#define CS8415_RATIO 0x1E
88#define CS8415_C_BUFFER 0x20
89#define CS8415_ID 0x7F
90
af9b70ac
MR
91/* PCA9554 registers */
92#define PCA9554_DEV 0x40 /* I2C device address */
93#define PCA9554_IN 0x00 /* input port */
94#define PCA9554_OUT 0x01 /* output port */
95#define PCA9554_INVERT 0x02 /* input invert */
96#define PCA9554_DIR 0x03 /* port directions */
97
98/*
99 * Aureon Universe additional controls using PCA9554
100 */
101
102/*
103 * Send data to pca9554
104 */
105static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
106 unsigned char data)
107{
108 unsigned int tmp;
109 int i, j;
110 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
111 unsigned char val = 0;
112
113 tmp = snd_ice1712_gpio_read(ice);
114
115 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
116 AUREON_WM_RW|AUREON_WM_CS|
117 AUREON_CS8415_CS));
118 tmp |= AUREON_WM_RW;
119 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
120
121 tmp &= ~AUREON_SPI_MOSI;
122 tmp &= ~AUREON_SPI_CLK;
123 snd_ice1712_gpio_write(ice, tmp);
124 udelay(50);
125
126 /*
127 * send i2c stop condition and start condition
128 * to obtain sane state
129 */
130 tmp |= AUREON_SPI_CLK;
131 snd_ice1712_gpio_write(ice, tmp);
132 udelay(50);
133 tmp |= AUREON_SPI_MOSI;
134 snd_ice1712_gpio_write(ice, tmp);
135 udelay(100);
136 tmp &= ~AUREON_SPI_MOSI;
137 snd_ice1712_gpio_write(ice, tmp);
138 udelay(50);
139 tmp &= ~AUREON_SPI_CLK;
140 snd_ice1712_gpio_write(ice, tmp);
141 udelay(100);
142 /*
143 * send device address, command and value,
144 * skipping ack cycles inbetween
145 */
146 for (j = 0; j < 3; j++) {
147 switch(j) {
148 case 0: val = dev; break;
149 case 1: val = reg; break;
150 case 2: val = data; break;
151 }
152 for (i = 7; i >= 0; i--) {
153 tmp &= ~AUREON_SPI_CLK;
154 snd_ice1712_gpio_write(ice, tmp);
155 udelay(40);
156 if (val & (1 << i))
157 tmp |= AUREON_SPI_MOSI;
158 else
159 tmp &= ~AUREON_SPI_MOSI;
160 snd_ice1712_gpio_write(ice, tmp);
161 udelay(40);
162 tmp |= AUREON_SPI_CLK;
163 snd_ice1712_gpio_write(ice, tmp);
164 udelay(40);
165 }
166 tmp &= ~AUREON_SPI_CLK;
167 snd_ice1712_gpio_write(ice, tmp);
168 udelay(40);
169 tmp |= AUREON_SPI_CLK;
170 snd_ice1712_gpio_write(ice, tmp);
171 udelay(40);
172 tmp &= ~AUREON_SPI_CLK;
173 snd_ice1712_gpio_write(ice, tmp);
174 udelay(40);
175 }
176 tmp &= ~AUREON_SPI_CLK;
177 snd_ice1712_gpio_write(ice, tmp);
178 udelay(40);
179 tmp &= ~AUREON_SPI_MOSI;
180 snd_ice1712_gpio_write(ice, tmp);
181 udelay(40);
182 tmp |= AUREON_SPI_CLK;
183 snd_ice1712_gpio_write(ice, tmp);
184 udelay(50);
185 tmp |= AUREON_SPI_MOSI;
186 snd_ice1712_gpio_write(ice, tmp);
187 udelay(100);
188}
189
190static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_info *uinfo)
192{
193 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
194
195 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
196 uinfo->count = 1;
197 uinfo->value.enumerated.items = 3;
198 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
199 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
201 return 0;
202}
203
204static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
205 struct snd_ctl_elem_value *ucontrol)
206{
207 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
208 ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
209 return 0;
210}
211
212static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
214{
215 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216 unsigned char oval, nval;
217 int change;
218
219 snd_ice1712_save_gpio_status(ice);
220
221 oval = ice->spec.aureon.pca9554_out;
222 nval = ucontrol->value.integer.value[0];
223 if ((change = (oval != nval))) {
224 aureon_pca9554_write(ice, PCA9554_OUT, nval);
225 ice->spec.aureon.pca9554_out = nval;
226 }
227 snd_ice1712_restore_gpio_status(ice);
228
229 return change;
230}
231
232
233static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
234 unsigned short val)
235{
1da177e4
LT
236 unsigned int tmp;
237
238 /* Send address to XILINX chip */
239 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
240 snd_ice1712_gpio_write(ice, tmp);
241 udelay(10);
242 tmp |= AUREON_AC97_ADDR;
243 snd_ice1712_gpio_write(ice, tmp);
244 udelay(10);
245 tmp &= ~AUREON_AC97_ADDR;
246 snd_ice1712_gpio_write(ice, tmp);
247 udelay(10);
248
249 /* Send low-order byte to XILINX chip */
250 tmp &= ~AUREON_AC97_DATA_MASK;
251 tmp |= val & AUREON_AC97_DATA_MASK;
252 snd_ice1712_gpio_write(ice, tmp);
253 udelay(10);
254 tmp |= AUREON_AC97_DATA_LOW;
255 snd_ice1712_gpio_write(ice, tmp);
256 udelay(10);
257 tmp &= ~AUREON_AC97_DATA_LOW;
258 snd_ice1712_gpio_write(ice, tmp);
259 udelay(10);
260
261 /* Send high-order byte to XILINX chip */
262 tmp &= ~AUREON_AC97_DATA_MASK;
263 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
264
265 snd_ice1712_gpio_write(ice, tmp);
266 udelay(10);
267 tmp |= AUREON_AC97_DATA_HIGH;
268 snd_ice1712_gpio_write(ice, tmp);
269 udelay(10);
270 tmp &= ~AUREON_AC97_DATA_HIGH;
271 snd_ice1712_gpio_write(ice, tmp);
272 udelay(10);
273
274 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
275 tmp |= AUREON_AC97_COMMIT;
276 snd_ice1712_gpio_write(ice, tmp);
277 udelay(10);
278 tmp &= ~AUREON_AC97_COMMIT;
279 snd_ice1712_gpio_write(ice, tmp);
280 udelay(10);
281
282 /* Store the data in out private buffer */
283 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
284}
285
ab0c7d72 286static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
1da177e4
LT
287{
288 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
289}
290
291/*
292 * Initialize STAC9744 chip
293 */
af9b70ac
MR
294static int aureon_ac97_init (struct snd_ice1712 *ice)
295{
1da177e4 296 int i;
32b47da0 297 static const unsigned short ac97_defaults[] = {
1da177e4
LT
298 0x00, 0x9640,
299 0x02, 0x8000,
300 0x04, 0x8000,
301 0x06, 0x8000,
302 0x0C, 0x8008,
303 0x0E, 0x8008,
304 0x10, 0x8808,
305 0x12, 0x8808,
306 0x14, 0x8808,
307 0x16, 0x8808,
308 0x18, 0x8808,
309 0x1C, 0x8000,
310 0x26, 0x000F,
311 0x28, 0x0201,
312 0x2C, 0xBB80,
313 0x32, 0xBB80,
314 0x7C, 0x8384,
315 0x7E, 0x7644,
316 (unsigned short)-1
317 };
318 unsigned int tmp;
319
320 /* Cold reset */
321 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
322 snd_ice1712_gpio_write(ice, tmp);
323 udelay(3);
324
325 tmp &= ~AUREON_AC97_RESET;
326 snd_ice1712_gpio_write(ice, tmp);
327 udelay(3);
328
329 tmp |= AUREON_AC97_RESET;
330 snd_ice1712_gpio_write(ice, tmp);
331 udelay(3);
332
333 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
334 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
335 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
336
337 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
338
339 return 0;
340}
341
342#define AUREON_AC97_STEREO 0x80
343
344/*
345 * AC'97 volume controls
346 */
ab0c7d72 347static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
348{
349 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
350 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
351 uinfo->value.integer.min = 0;
352 uinfo->value.integer.max = 31;
353 return 0;
354}
355
ab0c7d72 356static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 357{
ab0c7d72 358 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
359 unsigned short vol;
360
62932df8 361 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
362
363 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
364 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
365 if (kcontrol->private_value & AUREON_AC97_STEREO)
366 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
367
62932df8 368 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
369 return 0;
370}
371
ab0c7d72 372static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 373{
ab0c7d72 374 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
375 unsigned short ovol, nvol;
376 int change;
377
378 snd_ice1712_save_gpio_status(ice);
379
380 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
381 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
382 if (kcontrol->private_value & AUREON_AC97_STEREO)
383 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
384 nvol |= ovol & ~0x1F1F;
385
386 if ((change = (ovol != nvol)))
387 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
388
389 snd_ice1712_restore_gpio_status(ice);
390
391 return change;
392}
393
394/*
395 * AC'97 mute controls
396 */
a5ce8890 397#define aureon_ac97_mute_info snd_ctl_boolean_mono_info
1da177e4 398
ab0c7d72 399static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 400{
ab0c7d72 401 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 402
62932df8 403 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
404
405 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
406
62932df8 407 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
408 return 0;
409}
410
ab0c7d72 411static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 412{
ab0c7d72 413 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
414 unsigned short ovol, nvol;
415 int change;
416
417 snd_ice1712_save_gpio_status(ice);
418
419 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
420 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
421
422 if ((change = (ovol != nvol)))
423 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
424
425 snd_ice1712_restore_gpio_status(ice);
426
427 return change;
428}
429
430/*
431 * AC'97 mute controls
432 */
a5ce8890 433#define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
1da177e4 434
ab0c7d72 435static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 436{
ab0c7d72 437 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 438
62932df8 439 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
440
441 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
442
62932df8 443 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
444 return 0;
445}
446
ab0c7d72 447static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 448{
ab0c7d72 449 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
450 unsigned short ovol, nvol;
451 int change;
452
453 snd_ice1712_save_gpio_status(ice);
454
455 ovol = aureon_ac97_read(ice, AC97_MIC);
456 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
457
458 if ((change = (ovol != nvol)))
459 aureon_ac97_write(ice, AC97_MIC, nvol);
460
461 snd_ice1712_restore_gpio_status(ice);
462
463 return change;
464}
465
466/*
467 * write data in the SPI mode
468 */
ab0c7d72 469static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
1da177e4
LT
470{
471 unsigned int tmp;
472 int i;
45fe722b 473 unsigned int mosi, clk;
1da177e4
LT
474
475 tmp = snd_ice1712_gpio_read(ice);
476
cdf88efa
TK
477 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
478 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
45fe722b
TI
479 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
480 mosi = PRODIGY_SPI_MOSI;
481 clk = PRODIGY_SPI_CLK;
482 }
483 else {
484 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
485 AUREON_WM_CS|AUREON_CS8415_CS));
486 mosi = AUREON_SPI_MOSI;
487 clk = AUREON_SPI_CLK;
488
489 tmp |= AUREON_WM_RW;
490 }
491
1da177e4
LT
492 tmp &= ~cs;
493 snd_ice1712_gpio_write(ice, tmp);
494 udelay(1);
495
496 for (i = bits - 1; i >= 0; i--) {
45fe722b 497 tmp &= ~clk;
1da177e4
LT
498 snd_ice1712_gpio_write(ice, tmp);
499 udelay(1);
500 if (data & (1 << i))
45fe722b 501 tmp |= mosi;
1da177e4 502 else
45fe722b 503 tmp &= ~mosi;
1da177e4
LT
504 snd_ice1712_gpio_write(ice, tmp);
505 udelay(1);
45fe722b 506 tmp |= clk;
1da177e4
LT
507 snd_ice1712_gpio_write(ice, tmp);
508 udelay(1);
509 }
510
45fe722b 511 tmp &= ~clk;
1da177e4
LT
512 tmp |= cs;
513 snd_ice1712_gpio_write(ice, tmp);
514 udelay(1);
45fe722b 515 tmp |= clk;
1da177e4
LT
516 snd_ice1712_gpio_write(ice, tmp);
517 udelay(1);
518}
519
520/*
521 * Read data in SPI mode
522 */
ab0c7d72 523static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
1da177e4
LT
524 int i, j;
525 unsigned int tmp;
526
527 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
528 snd_ice1712_gpio_write(ice, tmp);
529 tmp &= ~cs;
530 snd_ice1712_gpio_write(ice, tmp);
531 udelay(1);
532
533 for (i=bits-1; i>=0; i--) {
534 if (data & (1 << i))
535 tmp |= AUREON_SPI_MOSI;
536 else
537 tmp &= ~AUREON_SPI_MOSI;
538 snd_ice1712_gpio_write(ice, tmp);
539 udelay(1);
540
541 tmp |= AUREON_SPI_CLK;
542 snd_ice1712_gpio_write(ice, tmp);
543 udelay(1);
544
545 tmp &= ~AUREON_SPI_CLK;
546 snd_ice1712_gpio_write(ice, tmp);
547 udelay(1);
548 }
549
550 for (j=0; j<size; j++) {
551 unsigned char outdata = 0;
552 for (i=7; i>=0; i--) {
553 tmp = snd_ice1712_gpio_read(ice);
554 outdata <<= 1;
555 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
556 udelay(1);
557
558 tmp |= AUREON_SPI_CLK;
559 snd_ice1712_gpio_write(ice, tmp);
560 udelay(1);
561
562 tmp &= ~AUREON_SPI_CLK;
563 snd_ice1712_gpio_write(ice, tmp);
564 udelay(1);
565 }
566 buffer[j] = outdata;
567 }
568
569 tmp |= cs;
570 snd_ice1712_gpio_write(ice, tmp);
571}
572
ab0c7d72 573static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
1da177e4
LT
574 unsigned char val;
575 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
576 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
577 return val;
578}
579
ab0c7d72 580static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
1da177e4
LT
581 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
582 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
583}
584
ab0c7d72 585static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
1da177e4
LT
586 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
587}
588
589/*
590 * get the current register value of WM codec
591 */
ab0c7d72 592static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
1da177e4
LT
593{
594 reg <<= 1;
595 return ((unsigned short)ice->akm[0].images[reg] << 8) |
596 ice->akm[0].images[reg + 1];
597}
598
599/*
600 * set the register value of WM codec
601 */
ab0c7d72 602static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
1da177e4 603{
45fe722b 604 aureon_spi_write(ice,
cdf88efa
TK
605 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
606 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
607 PRODIGY_WM_CS : AUREON_WM_CS),
45fe722b 608 (reg << 9) | (val & 0x1ff), 16);
1da177e4
LT
609}
610
611/*
612 * set the register value of WM codec and remember it
613 */
ab0c7d72 614static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
1da177e4
LT
615{
616 wm_put_nocache(ice, reg, val);
617 reg <<= 1;
618 ice->akm[0].images[reg] = val >> 8;
619 ice->akm[0].images[reg + 1] = val;
620}
621
622/*
623 */
a5ce8890 624#define aureon_mono_bool_info snd_ctl_boolean_mono_info
1da177e4
LT
625
626/*
627 * AC'97 master playback mute controls (Mute on WM8770 chip)
628 */
a5ce8890 629#define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
1da177e4 630
ab0c7d72 631static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 632{
ab0c7d72 633 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 634
62932df8 635 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
636
637 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
638
62932df8 639 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
640 return 0;
641}
642
ab0c7d72
TI
643static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
644 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
645 unsigned short ovol, nvol;
646 int change;
647
648 snd_ice1712_save_gpio_status(ice);
649
650 ovol = wm_get(ice, WM_OUT_MUX1);
651 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
652 if ((change = (ovol != nvol)))
653 wm_put(ice, WM_OUT_MUX1, nvol);
654
655 snd_ice1712_restore_gpio_status(ice);
656
657 return change;
658}
659
0cb29ea0
TI
660static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
661static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
662static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
663static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
664static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
f640c320 665
1da177e4
LT
666/*
667 * Logarithmic volume values for WM8770
668 * Computed as 20 * Log10(255 / x)
669 */
32b47da0 670static const unsigned char wm_vol[256] = {
1da177e4
LT
671 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
672 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
673 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
674 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
675 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
676 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,
677 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,
678 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,
679 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,
680 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,
681 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,
682 0, 0
683};
684
685#define WM_VOL_MAX (sizeof(wm_vol) - 1)
686#define WM_VOL_MUTE 0x8000
687
ab0c7d72 688static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
1da177e4
LT
689{
690 unsigned char nvol;
691
692 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
693 nvol = 0;
694 else
695 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
696
697 wm_put(ice, index, nvol);
698 wm_put_nocache(ice, index, 0x180 | nvol);
699}
700
701/*
702 * DAC mute control
703 */
a5ce8890 704#define wm_pcm_mute_info snd_ctl_boolean_mono_info
1da177e4 705
ab0c7d72 706static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 707{
ab0c7d72 708 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 709
62932df8 710 mutex_lock(&ice->gpio_mutex);
1da177e4 711 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
62932df8 712 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
713 return 0;
714}
715
ab0c7d72 716static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 717{
ab0c7d72 718 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
719 unsigned short nval, oval;
720 int change;
721
722 snd_ice1712_save_gpio_status(ice);
723 oval = wm_get(ice, WM_MUTE);
724 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
725 if ((change = (nval != oval)))
726 wm_put(ice, WM_MUTE, nval);
727 snd_ice1712_restore_gpio_status(ice);
728
729 return change;
730}
731
732/*
733 * Master volume attenuation mixer control
734 */
ab0c7d72 735static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
736{
737 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
738 uinfo->count = 2;
739 uinfo->value.integer.min = 0;
740 uinfo->value.integer.max = WM_VOL_MAX;
741 return 0;
742}
743
ab0c7d72 744static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 745{
ab0c7d72 746 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
747 int i;
748 for (i=0; i<2; i++)
749 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
750 return 0;
751}
752
ab0c7d72 753static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 754{
ab0c7d72 755 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
756 int ch, change = 0;
757
758 snd_ice1712_save_gpio_status(ice);
759 for (ch = 0; ch < 2; ch++) {
760 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
761 int dac;
762 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
763 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
764 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
765 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
766 ice->spec.aureon.vol[dac + ch],
767 ice->spec.aureon.master[ch]);
768 change = 1;
769 }
770 }
771 snd_ice1712_restore_gpio_status(ice);
772 return change;
773}
774
775/*
776 * DAC volume attenuation mixer control
777 */
ab0c7d72 778static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
779{
780 int voices = kcontrol->private_value >> 8;
781 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
782 uinfo->count = voices;
783 uinfo->value.integer.min = 0; /* mute (-101dB) */
784 uinfo->value.integer.max = 0x7F; /* 0dB */
785 return 0;
786}
787
ab0c7d72 788static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 789{
ab0c7d72 790 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
791 int i, ofs, voices;
792
793 voices = kcontrol->private_value >> 8;
794 ofs = kcontrol->private_value & 0xff;
795 for (i = 0; i < voices; i++)
796 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
797 return 0;
798}
799
ab0c7d72 800static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 801{
ab0c7d72 802 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
803 int i, idx, ofs, voices;
804 int change = 0;
805
806 voices = kcontrol->private_value >> 8;
807 ofs = kcontrol->private_value & 0xff;
808 snd_ice1712_save_gpio_status(ice);
809 for (i = 0; i < voices; i++) {
810 idx = WM_DAC_ATTEN + ofs + i;
811 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
812 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
813 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
814 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
815 ice->spec.aureon.master[i]);
816 change = 1;
817 }
818 }
819 snd_ice1712_restore_gpio_status(ice);
820 return change;
821}
822
823/*
824 * WM8770 mute control
825 */
ab0c7d72 826static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1da177e4
LT
827 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
828 uinfo->count = kcontrol->private_value >> 8;
829 uinfo->value.integer.min = 0;
830 uinfo->value.integer.max = 1;
831 return 0;
832}
833
ab0c7d72 834static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 835{
ab0c7d72 836 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
837 int voices, ofs, i;
838
839 voices = kcontrol->private_value >> 8;
840 ofs = kcontrol->private_value & 0xFF;
841
842 for (i = 0; i < voices; i++)
843 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
844 return 0;
845}
846
ab0c7d72 847static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 848{
ab0c7d72 849 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
850 int change = 0, voices, ofs, i;
851
852 voices = kcontrol->private_value >> 8;
853 ofs = kcontrol->private_value & 0xFF;
854
855 snd_ice1712_save_gpio_status(ice);
856 for (i = 0; i < voices; i++) {
857 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
858 if (ucontrol->value.integer.value[i] != val) {
859 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
860 ice->spec.aureon.vol[ofs + i] |=
861 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
862 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
863 ice->spec.aureon.master[i]);
864 change = 1;
865 }
866 }
867 snd_ice1712_restore_gpio_status(ice);
868
869 return change;
870}
871
872/*
873 * WM8770 master mute control
874 */
a5ce8890 875#define wm_master_mute_info snd_ctl_boolean_stereo_info
1da177e4 876
ab0c7d72 877static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 878{
ab0c7d72 879 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
880
881 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
882 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
883 return 0;
884}
885
ab0c7d72 886static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 887{
ab0c7d72 888 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
889 int change = 0, i;
890
891 snd_ice1712_save_gpio_status(ice);
892 for (i = 0; i < 2; i++) {
893 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
894 if (ucontrol->value.integer.value[i] != val) {
895 int dac;
896 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
897 ice->spec.aureon.master[i] |=
898 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
899 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
900 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
901 ice->spec.aureon.vol[dac + i],
902 ice->spec.aureon.master[i]);
903 change = 1;
904 }
905 }
906 snd_ice1712_restore_gpio_status(ice);
907
908 return change;
909}
910
911/* digital master volume */
912#define PCM_0dB 0xff
913#define PCM_RES 128 /* -64dB */
914#define PCM_MIN (PCM_0dB - PCM_RES)
ab0c7d72 915static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
916{
917 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
918 uinfo->count = 1;
919 uinfo->value.integer.min = 0; /* mute (-64dB) */
920 uinfo->value.integer.max = PCM_RES; /* 0dB */
921 return 0;
922}
923
ab0c7d72 924static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 925{
ab0c7d72 926 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
927 unsigned short val;
928
62932df8 929 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
930 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
931 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
932 ucontrol->value.integer.value[0] = val;
62932df8 933 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
934 return 0;
935}
936
ab0c7d72 937static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 938{
ab0c7d72 939 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
940 unsigned short ovol, nvol;
941 int change = 0;
942
943 snd_ice1712_save_gpio_status(ice);
944 nvol = ucontrol->value.integer.value[0];
945 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
946 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
947 if (ovol != nvol) {
948 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
949 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
950 change = 1;
951 }
952 snd_ice1712_restore_gpio_status(ice);
953 return change;
954}
955
956/*
957 * ADC mute control
958 */
a5ce8890 959#define wm_adc_mute_info snd_ctl_boolean_stereo_info
1da177e4 960
ab0c7d72 961static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 962{
ab0c7d72 963 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
964 unsigned short val;
965 int i;
966
62932df8 967 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
968 for (i = 0; i < 2; i++) {
969 val = wm_get(ice, WM_ADC_GAIN + i);
970 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
971 }
62932df8 972 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
973 return 0;
974}
975
ab0c7d72 976static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 977{
ab0c7d72 978 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
979 unsigned short new, old;
980 int i, change = 0;
981
982 snd_ice1712_save_gpio_status(ice);
983 for (i = 0; i < 2; i++) {
984 old = wm_get(ice, WM_ADC_GAIN + i);
985 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
986 if (new != old) {
987 wm_put(ice, WM_ADC_GAIN + i, new);
988 change = 1;
989 }
990 }
991 snd_ice1712_restore_gpio_status(ice);
992
993 return change;
994}
995
996/*
997 * ADC gain mixer control
998 */
ab0c7d72 999static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
1000{
1001 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1002 uinfo->count = 2;
1003 uinfo->value.integer.min = 0; /* -12dB */
1004 uinfo->value.integer.max = 0x1f; /* 19dB */
1005 return 0;
1006}
1007
ab0c7d72 1008static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1009{
ab0c7d72 1010 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1011 int i, idx;
1012 unsigned short vol;
1013
62932df8 1014 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
1015 for (i = 0; i < 2; i++) {
1016 idx = WM_ADC_GAIN + i;
1017 vol = wm_get(ice, idx) & 0x1f;
1018 ucontrol->value.integer.value[i] = vol;
1019 }
62932df8 1020 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
1021 return 0;
1022}
1023
ab0c7d72 1024static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1025{
ab0c7d72 1026 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1027 int i, idx;
1028 unsigned short ovol, nvol;
1029 int change = 0;
1030
1031 snd_ice1712_save_gpio_status(ice);
1032 for (i = 0; i < 2; i++) {
1033 idx = WM_ADC_GAIN + i;
1034 nvol = ucontrol->value.integer.value[i];
1035 ovol = wm_get(ice, idx);
1036 if ((ovol & 0x1f) != nvol) {
1037 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1038 change = 1;
1039 }
1040 }
1041 snd_ice1712_restore_gpio_status(ice);
1042 return change;
1043}
1044
1045/*
1046 * ADC input mux mixer control
1047 */
ab0c7d72 1048static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1049{
32b47da0 1050 static const char * const texts[] = {
1da177e4
LT
1051 "CD", //AIN1
1052 "Aux", //AIN2
1053 "Line", //AIN3
1054 "Mic", //AIN4
1055 "AC97" //AIN5
1056 };
32b47da0 1057 static const char * const universe_texts[] = {
1da177e4
LT
1058 "Aux1", //AIN1
1059 "CD", //AIN2
1060 "Phono", //AIN3
1061 "Line", //AIN4
1062 "Aux2", //AIN5
1063 "Mic", //AIN6
1064 "Aux3", //AIN7
1065 "AC97" //AIN8
1066 };
ab0c7d72 1067 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1068
1069 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1070 uinfo->count = 2;
1071 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1072 uinfo->value.enumerated.items = 8;
1073 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1074 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1075 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1076 }
1077 else {
1078 uinfo->value.enumerated.items = 5;
1079 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1080 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1081 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1082 }
1083 return 0;
1084}
1085
ab0c7d72 1086static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1087{
ab0c7d72 1088 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1089 unsigned short val;
1090
62932df8 1091 mutex_lock(&ice->gpio_mutex);
1da177e4 1092 val = wm_get(ice, WM_ADC_MUX);
6682025e
TI
1093 ucontrol->value.enumerated.item[0] = val & 7;
1094 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
62932df8 1095 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
1096 return 0;
1097}
1098
ab0c7d72 1099static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1100{
ab0c7d72 1101 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1102 unsigned short oval, nval;
1103 int change;
1104
1105 snd_ice1712_save_gpio_status(ice);
1106 oval = wm_get(ice, WM_ADC_MUX);
1107 nval = oval & ~0x77;
6682025e
TI
1108 nval |= ucontrol->value.enumerated.item[0] & 7;
1109 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1da177e4
LT
1110 change = (oval != nval);
1111 if (change)
1112 wm_put(ice, WM_ADC_MUX, nval);
1113 snd_ice1712_restore_gpio_status(ice);
63786d06 1114 return change;
1da177e4
LT
1115}
1116
1117/*
1118 * CS8415 Input mux
1119 */
ab0c7d72 1120static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1121{
ab0c7d72 1122 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
32b47da0 1123 static const char * const aureon_texts[] = {
1da177e4
LT
1124 "CD", //RXP0
1125 "Optical" //RXP1
1126 };
32b47da0 1127 static const char * const prodigy_texts[] = {
1da177e4
LT
1128 "CD",
1129 "Coax"
1130 };
1131 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1132 uinfo->count = 1;
1133 uinfo->value.enumerated.items = 2;
1134 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1135 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1136 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1137 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1138 else
1139 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1140 return 0;
1141}
1142
ab0c7d72 1143static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1144{
ab0c7d72 1145 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1146
1147 //snd_ice1712_save_gpio_status(ice);
1148 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
6682025e 1149 ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux;
1da177e4
LT
1150 //snd_ice1712_restore_gpio_status(ice);
1151 return 0;
1152}
1153
ab0c7d72 1154static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1155{
ab0c7d72 1156 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1157 unsigned short oval, nval;
1158 int change;
1159
1160 snd_ice1712_save_gpio_status(ice);
1161 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1162 nval = oval & ~0x07;
6682025e 1163 nval |= ucontrol->value.enumerated.item[0] & 7;
1da177e4
LT
1164 change = (oval != nval);
1165 if (change)
1166 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1167 snd_ice1712_restore_gpio_status(ice);
6682025e 1168 ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0];
1da177e4
LT
1169 return change;
1170}
1171
ab0c7d72 1172static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
1173{
1174 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1175 uinfo->count = 1;
1176 uinfo->value.integer.min = 0;
1177 uinfo->value.integer.max = 192000;
1178 return 0;
1179}
1180
ab0c7d72 1181static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1182{
ab0c7d72 1183 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1184 unsigned char ratio;
1185 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1186 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1187 return 0;
1188}
1189
1190/*
1191 * CS8415A Mute
1192 */
a5ce8890 1193#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1da177e4 1194
ab0c7d72 1195static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1196{
ab0c7d72 1197 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1198 snd_ice1712_save_gpio_status(ice);
1199 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1200 snd_ice1712_restore_gpio_status(ice);
1201 return 0;
1202}
1203
ab0c7d72 1204static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1205{
ab0c7d72 1206 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1207 unsigned char oval, nval;
1208 int change;
1209 snd_ice1712_save_gpio_status(ice);
1210 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1211 if (ucontrol->value.integer.value[0])
1212 nval = oval & ~0x20;
1213 else
1214 nval = oval | 0x20;
1215 if ((change = (oval != nval)))
1216 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1217 snd_ice1712_restore_gpio_status(ice);
1218 return change;
1219}
1220
1221/*
1222 * CS8415A Q-Sub info
1223 */
ab0c7d72 1224static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1da177e4
LT
1225 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1226 uinfo->count = 10;
1227 return 0;
1228}
1229
ab0c7d72
TI
1230static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1231 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1232
1233 snd_ice1712_save_gpio_status(ice);
1234 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1235 snd_ice1712_restore_gpio_status(ice);
1236
1237 return 0;
1238}
1239
ab0c7d72 1240static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1da177e4
LT
1241 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1242 uinfo->count = 1;
1243 return 0;
1244}
1245
ab0c7d72 1246static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1da177e4
LT
1247 memset(ucontrol->value.iec958.status, 0xFF, 24);
1248 return 0;
1249}
1250
ab0c7d72
TI
1251static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1252 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1253
1254 snd_ice1712_save_gpio_status(ice);
1255 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1256 snd_ice1712_restore_gpio_status(ice);
1257 return 0;
1258}
1259
1260/*
1261 * Headphone Amplifier
1262 */
ab0c7d72 1263static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1da177e4
LT
1264{
1265 unsigned int tmp, tmp2;
1266
1267 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1268 if (enable)
cdf88efa
TK
1269 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1270 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
c5130271
TI
1271 tmp |= AUREON_HP_SEL;
1272 else
1273 tmp |= PRODIGY_HP_SEL;
1da177e4 1274 else
cdf88efa
TK
1275 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1276 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
c5130271
TI
1277 tmp &= ~ AUREON_HP_SEL;
1278 else
1279 tmp &= ~ PRODIGY_HP_SEL;
1da177e4
LT
1280 if (tmp != tmp2) {
1281 snd_ice1712_gpio_write(ice, tmp);
1282 return 1;
1283 }
1284 return 0;
1285}
1286
ab0c7d72 1287static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1da177e4
LT
1288{
1289 unsigned int tmp = snd_ice1712_gpio_read(ice);
1290
1291 return ( tmp & AUREON_HP_SEL )!= 0;
1292}
1293
a5ce8890 1294#define aureon_hpamp_info snd_ctl_boolean_mono_info
1da177e4 1295
ab0c7d72 1296static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1297{
ab0c7d72 1298 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1299
1300 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1301 return 0;
1302}
1303
1304
ab0c7d72 1305static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1306{
ab0c7d72 1307 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1308
1309 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1310}
1311
1312/*
1313 * Deemphasis
1314 */
1315
a5ce8890 1316#define aureon_deemp_info snd_ctl_boolean_mono_info
1da177e4 1317
ab0c7d72 1318static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1319{
ab0c7d72 1320 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1321 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1322 return 0;
1323}
1324
ab0c7d72 1325static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1326{
ab0c7d72 1327 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1328 int temp, temp2;
1329 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1330 if (ucontrol->value.integer.value[0])
1331 temp |= 0xf;
1332 else
1333 temp &= ~0xf;
1334 if (temp != temp2) {
1335 wm_put(ice, WM_DAC_CTRL2, temp);
1336 return 1;
1337 }
1338 return 0;
1339}
1340
1341/*
1342 * ADC Oversampling
1343 */
ab0c7d72 1344static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1da177e4 1345{
32b47da0 1346 static const char * const texts[2] = { "128x", "64x" };
1da177e4
LT
1347
1348 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1349 uinfo->count = 1;
1350 uinfo->value.enumerated.items = 2;
1351
1352 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1353 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1354 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1355
1356 return 0;
1357}
1358
ab0c7d72 1359static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1360{
ab0c7d72 1361 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1362 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1363 return 0;
1364}
1365
ab0c7d72 1366static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
1367{
1368 int temp, temp2;
ab0c7d72 1369 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1370
1371 temp2 = temp = wm_get(ice, WM_MASTER);
1372
1373 if (ucontrol->value.enumerated.item[0])
1374 temp |= 0x8;
1375 else
1376 temp &= ~0x8;
1377
1378 if (temp != temp2) {
1379 wm_put(ice, WM_MASTER, temp);
1380 return 1;
1381 }
1382 return 0;
1383}
1384
1385/*
1386 * mixers
1387 */
1388
1b60f6b0 1389static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1da177e4
LT
1390 {
1391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1392 .name = "Master Playback Switch",
1393 .info = wm_master_mute_info,
1394 .get = wm_master_mute_get,
1395 .put = wm_master_mute_put
1396 },
1397 {
1398 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1399 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1400 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1401 .name = "Master Playback Volume",
1402 .info = wm_master_vol_info,
1403 .get = wm_master_vol_get,
f640c320
TI
1404 .put = wm_master_vol_put,
1405 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1406 },
1407 {
1408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1409 .name = "Front Playback Switch",
1410 .info = wm_mute_info,
1411 .get = wm_mute_get,
1412 .put = wm_mute_put,
1413 .private_value = (2 << 8) | 0
1414 },
1415 {
1416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1417 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1418 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1419 .name = "Front Playback Volume",
1420 .info = wm_vol_info,
1421 .get = wm_vol_get,
1422 .put = wm_vol_put,
f640c320
TI
1423 .private_value = (2 << 8) | 0,
1424 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1425 },
1426 {
1427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1428 .name = "Rear Playback Switch",
1429 .info = wm_mute_info,
1430 .get = wm_mute_get,
1431 .put = wm_mute_put,
1432 .private_value = (2 << 8) | 2
1433 },
1434 {
1435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1436 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1437 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1438 .name = "Rear Playback Volume",
1439 .info = wm_vol_info,
1440 .get = wm_vol_get,
1441 .put = wm_vol_put,
f640c320
TI
1442 .private_value = (2 << 8) | 2,
1443 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1444 },
1445 {
1446 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1447 .name = "Center Playback Switch",
1448 .info = wm_mute_info,
1449 .get = wm_mute_get,
1450 .put = wm_mute_put,
1451 .private_value = (1 << 8) | 4
1452 },
1453 {
1454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1455 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1456 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1457 .name = "Center Playback Volume",
1458 .info = wm_vol_info,
1459 .get = wm_vol_get,
1460 .put = wm_vol_put,
f640c320
TI
1461 .private_value = (1 << 8) | 4,
1462 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1463 },
1464 {
1465 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1466 .name = "LFE Playback Switch",
1467 .info = wm_mute_info,
1468 .get = wm_mute_get,
1469 .put = wm_mute_put,
1470 .private_value = (1 << 8) | 5
1471 },
1472 {
1473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1474 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1475 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1476 .name = "LFE Playback Volume",
1477 .info = wm_vol_info,
1478 .get = wm_vol_get,
1479 .put = wm_vol_put,
f640c320
TI
1480 .private_value = (1 << 8) | 5,
1481 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1482 },
1483 {
1484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485 .name = "Side Playback Switch",
1486 .info = wm_mute_info,
1487 .get = wm_mute_get,
1488 .put = wm_mute_put,
1489 .private_value = (2 << 8) | 6
1490 },
1491 {
1492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1493 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1494 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1495 .name = "Side Playback Volume",
1496 .info = wm_vol_info,
1497 .get = wm_vol_get,
1498 .put = wm_vol_put,
f640c320
TI
1499 .private_value = (2 << 8) | 6,
1500 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1501 }
1502};
1503
1b60f6b0 1504static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1da177e4
LT
1505 {
1506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1507 .name = "PCM Playback Switch",
1508 .info = wm_pcm_mute_info,
1509 .get = wm_pcm_mute_get,
1510 .put = wm_pcm_mute_put
1511 },
1512 {
1513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1514 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1515 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1516 .name = "PCM Playback Volume",
1517 .info = wm_pcm_vol_info,
1518 .get = wm_pcm_vol_get,
f640c320
TI
1519 .put = wm_pcm_vol_put,
1520 .tlv = { .p = db_scale_wm_pcm }
1da177e4
LT
1521 },
1522 {
1523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1524 .name = "Capture Switch",
1525 .info = wm_adc_mute_info,
1526 .get = wm_adc_mute_get,
1527 .put = wm_adc_mute_put,
1528 },
1529 {
1530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1531 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1532 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1533 .name = "Capture Volume",
1534 .info = wm_adc_vol_info,
1535 .get = wm_adc_vol_get,
f640c320
TI
1536 .put = wm_adc_vol_put,
1537 .tlv = { .p = db_scale_wm_adc }
1da177e4
LT
1538 },
1539 {
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Capture Source",
1542 .info = wm_adc_mux_info,
1543 .get = wm_adc_mux_get,
1544 .put = wm_adc_mux_put,
1545 .private_value = 5
1546 },
1547 {
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "External Amplifier",
1550 .info = aureon_hpamp_info,
1551 .get = aureon_hpamp_get,
1552 .put = aureon_hpamp_put
1553 },
1554 {
1555 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1556 .name = "DAC Deemphasis Switch",
1557 .info = aureon_deemp_info,
1558 .get = aureon_deemp_get,
1559 .put = aureon_deemp_put
1560 },
1561 {
1562 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1563 .name = "ADC Oversampling",
1564 .info = aureon_oversampling_info,
1565 .get = aureon_oversampling_get,
1566 .put = aureon_oversampling_put
1567 }
1568};
1569
1b60f6b0 1570static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1da177e4
LT
1571 {
1572 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1573 .name = "AC97 Playback Switch",
1574 .info = aureon_ac97_mmute_info,
1575 .get = aureon_ac97_mmute_get,
1576 .put = aureon_ac97_mmute_put,
1577 .private_value = AC97_MASTER
1578 },
1579 {
1580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1581 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1582 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1583 .name = "AC97 Playback Volume",
1584 .info = aureon_ac97_vol_info,
1585 .get = aureon_ac97_vol_get,
1586 .put = aureon_ac97_vol_put,
f640c320
TI
1587 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1588 .tlv = { .p = db_scale_ac97_master }
1da177e4
LT
1589 },
1590 {
1591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592 .name = "CD Playback Switch",
1593 .info = aureon_ac97_mute_info,
1594 .get = aureon_ac97_mute_get,
1595 .put = aureon_ac97_mute_put,
1596 .private_value = AC97_CD
1597 },
1598 {
1599 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1600 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1601 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1602 .name = "CD Playback Volume",
1603 .info = aureon_ac97_vol_info,
1604 .get = aureon_ac97_vol_get,
1605 .put = aureon_ac97_vol_put,
f640c320
TI
1606 .private_value = AC97_CD|AUREON_AC97_STEREO,
1607 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1608 },
1609 {
1610 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1611 .name = "Aux Playback Switch",
1612 .info = aureon_ac97_mute_info,
1613 .get = aureon_ac97_mute_get,
1614 .put = aureon_ac97_mute_put,
1615 .private_value = AC97_AUX,
1616 },
1617 {
1618 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1619 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1620 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1621 .name = "Aux Playback Volume",
1622 .info = aureon_ac97_vol_info,
1623 .get = aureon_ac97_vol_get,
1624 .put = aureon_ac97_vol_put,
f640c320
TI
1625 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1626 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1627 },
1628 {
1629 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1630 .name = "Line Playback Switch",
1631 .info = aureon_ac97_mute_info,
1632 .get = aureon_ac97_mute_get,
1633 .put = aureon_ac97_mute_put,
1634 .private_value = AC97_LINE
1635 },
1636 {
1637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1638 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1639 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1640 .name = "Line Playback Volume",
1641 .info = aureon_ac97_vol_info,
1642 .get = aureon_ac97_vol_get,
1643 .put = aureon_ac97_vol_put,
f640c320
TI
1644 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1645 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1646 },
1647 {
1648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1649 .name = "Mic Playback Switch",
1650 .info = aureon_ac97_mute_info,
1651 .get = aureon_ac97_mute_get,
1652 .put = aureon_ac97_mute_put,
1653 .private_value = AC97_MIC
1654 },
1655 {
1656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1657 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1658 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1659 .name = "Mic Playback Volume",
1660 .info = aureon_ac97_vol_info,
1661 .get = aureon_ac97_vol_get,
1662 .put = aureon_ac97_vol_put,
f640c320
TI
1663 .private_value = AC97_MIC,
1664 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1665 },
1666 {
1667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1668 .name = "Mic Boost (+20dB)",
1669 .info = aureon_ac97_micboost_info,
1670 .get = aureon_ac97_micboost_get,
1671 .put = aureon_ac97_micboost_put
1672 }
1673};
1674
1b60f6b0 1675static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1da177e4
LT
1676 {
1677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1678 .name = "AC97 Playback Switch",
1679 .info = aureon_ac97_mmute_info,
1680 .get = aureon_ac97_mmute_get,
1681 .put = aureon_ac97_mmute_put,
1682 .private_value = AC97_MASTER
1683 },
1684 {
1685 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1686 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1687 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1688 .name = "AC97 Playback Volume",
1689 .info = aureon_ac97_vol_info,
1690 .get = aureon_ac97_vol_get,
1691 .put = aureon_ac97_vol_put,
f640c320
TI
1692 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1693 .tlv = { .p = db_scale_ac97_master }
1da177e4
LT
1694 },
1695 {
1696 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1697 .name = "CD Playback Switch",
1698 .info = aureon_ac97_mute_info,
1699 .get = aureon_ac97_mute_get,
1700 .put = aureon_ac97_mute_put,
1701 .private_value = AC97_AUX
1702 },
1703 {
1704 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1705 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1706 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1707 .name = "CD Playback Volume",
1708 .info = aureon_ac97_vol_info,
1709 .get = aureon_ac97_vol_get,
1710 .put = aureon_ac97_vol_put,
f640c320
TI
1711 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1712 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1713 },
1714 {
1715 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1716 .name = "Phono Playback Switch",
1717 .info = aureon_ac97_mute_info,
1718 .get = aureon_ac97_mute_get,
1719 .put = aureon_ac97_mute_put,
f640c320 1720 .private_value = AC97_CD
1da177e4
LT
1721 },
1722 {
1723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1724 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1725 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1726 .name = "Phono Playback Volume",
1727 .info = aureon_ac97_vol_info,
1728 .get = aureon_ac97_vol_get,
1729 .put = aureon_ac97_vol_put,
f640c320
TI
1730 .private_value = AC97_CD|AUREON_AC97_STEREO,
1731 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1732 },
1733 {
1734 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1735 .name = "Line Playback Switch",
1736 .info = aureon_ac97_mute_info,
1737 .get = aureon_ac97_mute_get,
1738 .put = aureon_ac97_mute_put,
1739 .private_value = AC97_LINE
1740 },
1741 {
1742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1743 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1744 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1745 .name = "Line Playback Volume",
1746 .info = aureon_ac97_vol_info,
1747 .get = aureon_ac97_vol_get,
1748 .put = aureon_ac97_vol_put,
f640c320
TI
1749 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1750 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1751 },
1752 {
1753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1754 .name = "Mic Playback Switch",
1755 .info = aureon_ac97_mute_info,
1756 .get = aureon_ac97_mute_get,
1757 .put = aureon_ac97_mute_put,
1758 .private_value = AC97_MIC
1759 },
1760 {
1761 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1762 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1763 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1764 .name = "Mic Playback Volume",
1765 .info = aureon_ac97_vol_info,
1766 .get = aureon_ac97_vol_get,
1767 .put = aureon_ac97_vol_put,
f640c320
TI
1768 .private_value = AC97_MIC,
1769 .tlv = { .p = db_scale_ac97_gain }
1da177e4
LT
1770 },
1771 {
1772 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1773 .name = "Mic Boost (+20dB)",
1774 .info = aureon_ac97_micboost_info,
1775 .get = aureon_ac97_micboost_get,
1776 .put = aureon_ac97_micboost_put
1777 },
1778 {
1779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780 .name = "Aux Playback Switch",
1781 .info = aureon_ac97_mute_info,
1782 .get = aureon_ac97_mute_get,
1783 .put = aureon_ac97_mute_put,
1784 .private_value = AC97_VIDEO,
1785 },
1786 {
1787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
1788 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1789 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1790 .name = "Aux Playback Volume",
1791 .info = aureon_ac97_vol_info,
1792 .get = aureon_ac97_vol_get,
1793 .put = aureon_ac97_vol_put,
f640c320
TI
1794 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1795 .tlv = { .p = db_scale_ac97_gain }
af9b70ac
MR
1796 },
1797 {
1798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1799 .name = "Aux Source",
1800 .info = aureon_universe_inmux_info,
1801 .get = aureon_universe_inmux_get,
1802 .put = aureon_universe_inmux_put
1803 }
1804
1da177e4
LT
1805};
1806
1b60f6b0 1807static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1da177e4
LT
1808 {
1809 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1810 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1811 .info = aureon_cs8415_mute_info,
1812 .get = aureon_cs8415_mute_get,
1813 .put = aureon_cs8415_mute_put
1814 },
1815 {
1816 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1817 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1818 .info = aureon_cs8415_mux_info,
1819 .get = aureon_cs8415_mux_get,
1820 .put = aureon_cs8415_mux_put,
1821 },
1822 {
1823 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1824 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1825 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1826 .info = aureon_cs8415_qsub_info,
1827 .get = aureon_cs8415_qsub_get,
1828 },
1829 {
1830 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1831 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1832 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1833 .info = aureon_cs8415_spdif_info,
1834 .get = aureon_cs8415_mask_get
1835 },
1836 {
1837 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1838 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1839 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1840 .info = aureon_cs8415_spdif_info,
1841 .get = aureon_cs8415_spdif_get
1842 },
1843 {
1844 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1845 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1846 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1847 .info = aureon_cs8415_rate_info,
1848 .get = aureon_cs8415_rate_get
1849 }
1850};
1851
ab0c7d72 1852static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1da177e4
LT
1853{
1854 unsigned int i, counts;
1855 int err;
1856
1857 counts = ARRAY_SIZE(aureon_dac_controls);
1858 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1859 counts -= 2; /* no side */
1860 for (i = 0; i < counts; i++) {
1861 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1862 if (err < 0)
1863 return err;
1864 }
1865
1866 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1867 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1868 if (err < 0)
1869 return err;
1870 }
1871
1872 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1873 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1874 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1875 if (err < 0)
1876 return err;
1877 }
1878 }
cdf88efa
TK
1879 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1880 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1da177e4
LT
1881 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1882 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1883 if (err < 0)
1884 return err;
1885 }
1886 }
1887
cdf88efa
TK
1888 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1889 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1da177e4
LT
1890 unsigned char id;
1891 snd_ice1712_save_gpio_status(ice);
1892 id = aureon_cs8415_get(ice, CS8415_ID);
1893 if (id != 0x41)
99b359ba 1894 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1da177e4 1895 else if ((id & 0x0F) != 0x01)
99b359ba 1896 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1da177e4
LT
1897 else {
1898 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
ab0c7d72 1899 struct snd_kcontrol *kctl;
1da177e4
LT
1900 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1901 if (err < 0)
1902 return err;
1903 if (i > 1)
1904 kctl->id.device = ice->pcm->device;
1905 }
1906 }
1907 snd_ice1712_restore_gpio_status(ice);
1908 }
1909
1910 return 0;
1911}
1912
1913
1914/*
1915 * initialize the chip
1916 */
ab0c7d72 1917static int __devinit aureon_init(struct snd_ice1712 *ice)
1da177e4 1918{
32b47da0 1919 static const unsigned short wm_inits_aureon[] = {
1da177e4
LT
1920 /* These come first to reduce init pop noise */
1921 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1922 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1923 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1924
1925 0x18, 0x000, /* All power-up */
1926
1927 0x16, 0x122, /* I2S, normal polarity, 24bit */
1928 0x17, 0x022, /* 256fs, slave mode */
1929 0x00, 0, /* DAC1 analog mute */
1930 0x01, 0, /* DAC2 analog mute */
1931 0x02, 0, /* DAC3 analog mute */
1932 0x03, 0, /* DAC4 analog mute */
1933 0x04, 0, /* DAC5 analog mute */
1934 0x05, 0, /* DAC6 analog mute */
1935 0x06, 0, /* DAC7 analog mute */
1936 0x07, 0, /* DAC8 analog mute */
1937 0x08, 0x100, /* master analog mute */
1938 0x09, 0xff, /* DAC1 digital full */
1939 0x0a, 0xff, /* DAC2 digital full */
1940 0x0b, 0xff, /* DAC3 digital full */
1941 0x0c, 0xff, /* DAC4 digital full */
1942 0x0d, 0xff, /* DAC5 digital full */
1943 0x0e, 0xff, /* DAC6 digital full */
1944 0x0f, 0xff, /* DAC7 digital full */
1945 0x10, 0xff, /* DAC8 digital full */
1946 0x11, 0x1ff, /* master digital full */
1947 0x12, 0x000, /* phase normal */
1948 0x13, 0x090, /* unmute DAC L/R */
1949 0x14, 0x000, /* all unmute */
1950 0x15, 0x000, /* no deemphasis, no ZFLG */
1951 0x19, 0x000, /* -12dB ADC/L */
1952 0x1a, 0x000, /* -12dB ADC/R */
1953 (unsigned short)-1
1954 };
32b47da0 1955 static const unsigned short wm_inits_prodigy[] = {
1da177e4
LT
1956
1957 /* These come first to reduce init pop noise */
1958 0x1b, 0x000, /* ADC Mux */
1959 0x1c, 0x009, /* Out Mux1 */
1960 0x1d, 0x009, /* Out Mux2 */
1961
1962 0x18, 0x000, /* All power-up */
1963
1964 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1965 0x17, 0x006, /* 128fs, slave mode */
1966
1967 0x00, 0, /* DAC1 analog mute */
1968 0x01, 0, /* DAC2 analog mute */
1969 0x02, 0, /* DAC3 analog mute */
1970 0x03, 0, /* DAC4 analog mute */
1971 0x04, 0, /* DAC5 analog mute */
1972 0x05, 0, /* DAC6 analog mute */
1973 0x06, 0, /* DAC7 analog mute */
1974 0x07, 0, /* DAC8 analog mute */
1975 0x08, 0x100, /* master analog mute */
1976
1977 0x09, 0x7f, /* DAC1 digital full */
1978 0x0a, 0x7f, /* DAC2 digital full */
1979 0x0b, 0x7f, /* DAC3 digital full */
1980 0x0c, 0x7f, /* DAC4 digital full */
1981 0x0d, 0x7f, /* DAC5 digital full */
1982 0x0e, 0x7f, /* DAC6 digital full */
1983 0x0f, 0x7f, /* DAC7 digital full */
1984 0x10, 0x7f, /* DAC8 digital full */
1985 0x11, 0x1FF, /* master digital full */
1986
1987 0x12, 0x000, /* phase normal */
1988 0x13, 0x090, /* unmute DAC L/R */
1989 0x14, 0x000, /* all unmute */
1990 0x15, 0x000, /* no deemphasis, no ZFLG */
1991
1992 0x19, 0x000, /* -12dB ADC/L */
1993 0x1a, 0x000, /* -12dB ADC/R */
1994 (unsigned short)-1
1995
1996 };
32b47da0 1997 static const unsigned short cs_inits[] = {
1da177e4
LT
1998 0x0441, /* RUN */
1999 0x0180, /* no mute, OMCK output on RMCK pin */
2000 0x0201, /* S/PDIF source on RXP1 */
2001 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2002 (unsigned short)-1
2003 };
2004 unsigned int tmp;
32b47da0 2005 const unsigned short *p;
1da177e4
LT
2006 int err, i;
2007
2008 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2009 ice->num_total_dacs = 6;
2010 ice->num_total_adcs = 2;
2011 } else {
2012 /* aureon 7.1 and prodigy 7.1 */
2013 ice->num_total_dacs = 8;
2014 ice->num_total_adcs = 2;
2015 }
2016
2017 /* to remeber the register values of CS8415 */
ab0c7d72 2018 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1da177e4
LT
2019 if (! ice->akm)
2020 return -ENOMEM;
2021 ice->akm_codecs = 1;
2022
2023 if ((err = aureon_ac97_init(ice)) != 0)
2024 return err;
2025
2026 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2027
2028 /* reset the wm codec as the SPI mode */
2029 snd_ice1712_save_gpio_status(ice);
2030 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2031
2032 tmp = snd_ice1712_gpio_read(ice);
2033 tmp &= ~AUREON_WM_RESET;
2034 snd_ice1712_gpio_write(ice, tmp);
2035 udelay(1);
2036 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2037 snd_ice1712_gpio_write(ice, tmp);
2038 udelay(1);
2039 tmp |= AUREON_WM_RESET;
2040 snd_ice1712_gpio_write(ice, tmp);
2041 udelay(1);
2042
2043 /* initialize WM8770 codec */
45fe722b 2044 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
cdf88efa
TK
2045 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2046 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
1da177e4
LT
2047 p = wm_inits_prodigy;
2048 else
2049 p = wm_inits_aureon;
2050 for (; *p != (unsigned short)-1; p += 2)
2051 wm_put(ice, p[0], p[1]);
2052
2053 /* initialize CS8415A codec */
cdf88efa
TK
2054 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2055 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
45fe722b
TI
2056 for (p = cs_inits; *p != (unsigned short)-1; p++)
2057 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2058 ice->spec.aureon.cs8415_mux = 1;
1da177e4 2059
45fe722b
TI
2060 aureon_set_headphone_amp(ice, 1);
2061 }
1da177e4
LT
2062
2063 snd_ice1712_restore_gpio_status(ice);
af9b70ac
MR
2064
2065 /* initialize PCA9554 pin directions & set default input*/
2066 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2067 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
1da177e4
LT
2068
2069 ice->spec.aureon.master[0] = WM_VOL_MUTE;
2070 ice->spec.aureon.master[1] = WM_VOL_MUTE;
2071 for (i = 0; i < ice->num_total_dacs; i++) {
2072 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
2073 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
2074 }
2075
2076 return 0;
2077}
2078
2079
2080/*
2081 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2082 * hence the driver needs to sets up it properly.
2083 */
2084
1b60f6b0 2085static unsigned char aureon51_eeprom[] __devinitdata = {
189bc171
TI
2086 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2087 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2088 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2089 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2090 [ICE_EEP2_GPIO_DIR] = 0xff,
2091 [ICE_EEP2_GPIO_DIR1] = 0xff,
2092 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2093 [ICE_EEP2_GPIO_MASK] = 0x00,
2094 [ICE_EEP2_GPIO_MASK1] = 0x00,
2095 [ICE_EEP2_GPIO_MASK2] = 0x00,
2096 [ICE_EEP2_GPIO_STATE] = 0x00,
2097 [ICE_EEP2_GPIO_STATE1] = 0x00,
2098 [ICE_EEP2_GPIO_STATE2] = 0x00,
1da177e4
LT
2099};
2100
1b60f6b0 2101static unsigned char aureon71_eeprom[] __devinitdata = {
189bc171
TI
2102 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2103 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2104 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2105 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2106 [ICE_EEP2_GPIO_DIR] = 0xff,
2107 [ICE_EEP2_GPIO_DIR1] = 0xff,
2108 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2109 [ICE_EEP2_GPIO_MASK] = 0x00,
2110 [ICE_EEP2_GPIO_MASK1] = 0x00,
2111 [ICE_EEP2_GPIO_MASK2] = 0x00,
2112 [ICE_EEP2_GPIO_STATE] = 0x00,
2113 [ICE_EEP2_GPIO_STATE1] = 0x00,
2114 [ICE_EEP2_GPIO_STATE2] = 0x00,
1da177e4 2115};
189bc171 2116#define prodigy71_eeprom aureon71_eeprom
1da177e4 2117
1b60f6b0 2118static unsigned char prodigy71lt_eeprom[] __devinitdata = {
189bc171
TI
2119 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2120 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2121 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2122 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2123 [ICE_EEP2_GPIO_DIR] = 0xff,
2124 [ICE_EEP2_GPIO_DIR1] = 0xff,
2125 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2126 [ICE_EEP2_GPIO_MASK] = 0x00,
2127 [ICE_EEP2_GPIO_MASK1] = 0x00,
2128 [ICE_EEP2_GPIO_MASK2] = 0x00,
2129 [ICE_EEP2_GPIO_STATE] = 0x00,
2130 [ICE_EEP2_GPIO_STATE1] = 0x00,
2131 [ICE_EEP2_GPIO_STATE2] = 0x00,
cdf88efa 2132};
189bc171 2133#define prodigy71xt_eeprom prodigy71lt_eeprom
45fe722b 2134
1da177e4 2135/* entry point */
1b60f6b0 2136struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1da177e4
LT
2137 {
2138 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2139 .name = "Terratec Aureon 5.1-Sky",
2140 .model = "aureon51",
2141 .chip_init = aureon_init,
2142 .build_controls = aureon_add_controls,
2143 .eeprom_size = sizeof(aureon51_eeprom),
2144 .eeprom_data = aureon51_eeprom,
2145 .driver = "Aureon51",
2146 },
2147 {
2148 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2149 .name = "Terratec Aureon 7.1-Space",
2150 .model = "aureon71",
2151 .chip_init = aureon_init,
2152 .build_controls = aureon_add_controls,
2153 .eeprom_size = sizeof(aureon71_eeprom),
2154 .eeprom_data = aureon71_eeprom,
2155 .driver = "Aureon71",
2156 },
2157 {
2158 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2159 .name = "Terratec Aureon 7.1-Universe",
2160 .model = "universe",
2161 .chip_init = aureon_init,
2162 .build_controls = aureon_add_controls,
2163 .eeprom_size = sizeof(aureon71_eeprom),
2164 .eeprom_data = aureon71_eeprom,
9f37c5b3 2165 .driver = "Aureon71Univ", /* keep in 15 letters */
1da177e4
LT
2166 },
2167 {
2168 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2169 .name = "Audiotrak Prodigy 7.1",
2170 .model = "prodigy71",
2171 .chip_init = aureon_init,
2172 .build_controls = aureon_add_controls,
2173 .eeprom_size = sizeof(prodigy71_eeprom),
2174 .eeprom_data = prodigy71_eeprom,
2175 .driver = "Prodigy71", /* should be identical with Aureon71 */
2176 },
45fe722b
TI
2177 {
2178 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2179 .name = "Audiotrak Prodigy 7.1 LT",
2180 .model = "prodigy71lt",
2181 .chip_init = aureon_init,
2182 .build_controls = aureon_add_controls,
2183 .eeprom_size = sizeof(prodigy71lt_eeprom),
2184 .eeprom_data = prodigy71lt_eeprom,
2185 .driver = "Prodigy71LT",
2186 },
cdf88efa
TK
2187 {
2188 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2189 .name = "Audiotrak Prodigy 7.1 XT",
2190 .model = "prodigy71xt",
2191 .chip_init = aureon_init,
2192 .build_controls = aureon_add_controls,
2193 .eeprom_size = sizeof(prodigy71xt_eeprom),
2194 .eeprom_data = prodigy71xt_eeprom,
2195 .driver = "Prodigy71LT",
2196 },
1da177e4
LT
2197 { } /* terminator */
2198};
This page took 0.380073 seconds and 5 git commands to generate.