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