1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
49struct 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
58#define WM_DAC_ATTEN 0x00
59#define WM_DAC_MASTER_ATTEN 0x08
60#define WM_DAC_DIG_ATTEN 0x09
61#define WM_DAC_DIG_MASTER_ATTEN 0x11
62#define WM_PHASE_SWAP 0x12
63#define WM_DAC_CTRL1 0x13
64#define WM_MUTE 0x14
65#define WM_DAC_CTRL2 0x15
66#define WM_INT_CTRL 0x16
67#define WM_MASTER 0x17
68#define WM_POWERDOWN 0x18
69#define WM_ADC_GAIN 0x19
70#define WM_ADC_MUX 0x1b
71#define WM_OUT_MUX1 0x1c
72#define WM_OUT_MUX2 0x1e
73#define WM_RESET 0x1f
74
75
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
84#define PCA9554_DEV 0x40
85#define PCA9554_IN 0x00
86#define PCA9554_OUT 0x01
87#define PCA9554_INVERT 0x02
88#define PCA9554_DIR 0x03
89
90
91
92
93
94
95
96
97static 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;
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;
112
113 tmp &= ~AUREON_SPI_MOSI;
114 tmp &= ~AUREON_SPI_CLK;
115 snd_ice1712_gpio_write(ice, tmp);
116 udelay(50);
117
118
119
120
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
136
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
188static 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
197static 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
206static 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
229static 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
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
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
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
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
280 spec->stac9744[(reg & 0x7F) >> 1] = val;
281}
282
283static 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
291
292static 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
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
337 aureon_ac97_write(ice, AC97_MASTER, 0x0000);
338
339 return 0;
340}
341
342#define AUREON_AC97_STEREO 0x80
343
344
345
346
347static 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
356static 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 mutex_lock(&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 mutex_unlock(&ice->gpio_mutex);
369 return 0;
370}
371
372static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
373{
374 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
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 change = (ovol != nvol);
387 if (change)
388 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
389
390 snd_ice1712_restore_gpio_status(ice);
391
392 return change;
393}
394
395
396
397
398#define aureon_ac97_mute_info snd_ctl_boolean_mono_info
399
400static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
401{
402 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
403
404 mutex_lock(&ice->gpio_mutex);
405
406 ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
407 kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
408
409 mutex_unlock(&ice->gpio_mutex);
410 return 0;
411}
412
413static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
414{
415 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
416 unsigned short ovol, nvol;
417 int change;
418
419 snd_ice1712_save_gpio_status(ice);
420
421 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
422 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
423
424 change = (ovol != nvol);
425 if (change)
426 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
427
428 snd_ice1712_restore_gpio_status(ice);
429
430 return change;
431}
432
433
434
435
436#define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
437
438static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
439{
440 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
441
442 mutex_lock(&ice->gpio_mutex);
443
444 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
445
446 mutex_unlock(&ice->gpio_mutex);
447 return 0;
448}
449
450static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
451{
452 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
453 unsigned short ovol, nvol;
454 int change;
455
456 snd_ice1712_save_gpio_status(ice);
457
458 ovol = aureon_ac97_read(ice, AC97_MIC);
459 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
460
461 change = (ovol != nvol);
462 if (change)
463 aureon_ac97_write(ice, AC97_MIC, nvol);
464
465 snd_ice1712_restore_gpio_status(ice);
466
467 return change;
468}
469
470
471
472
473static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
474{
475 unsigned int tmp;
476 int i;
477 unsigned int mosi, clk;
478
479 tmp = snd_ice1712_gpio_read(ice);
480
481 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
482 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
483 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
484 mosi = PRODIGY_SPI_MOSI;
485 clk = PRODIGY_SPI_CLK;
486 } else {
487 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
488 AUREON_WM_CS|AUREON_CS8415_CS));
489 mosi = AUREON_SPI_MOSI;
490 clk = AUREON_SPI_CLK;
491
492 tmp |= AUREON_WM_RW;
493 }
494
495 tmp &= ~cs;
496 snd_ice1712_gpio_write(ice, tmp);
497 udelay(1);
498
499 for (i = bits - 1; i >= 0; i--) {
500 tmp &= ~clk;
501 snd_ice1712_gpio_write(ice, tmp);
502 udelay(1);
503 if (data & (1 << i))
504 tmp |= mosi;
505 else
506 tmp &= ~mosi;
507 snd_ice1712_gpio_write(ice, tmp);
508 udelay(1);
509 tmp |= clk;
510 snd_ice1712_gpio_write(ice, tmp);
511 udelay(1);
512 }
513
514 tmp &= ~clk;
515 tmp |= cs;
516 snd_ice1712_gpio_write(ice, tmp);
517 udelay(1);
518 tmp |= clk;
519 snd_ice1712_gpio_write(ice, tmp);
520 udelay(1);
521}
522
523
524
525
526static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
527 unsigned int data, int bits, unsigned char *buffer, int size)
528{
529 int i, j;
530 unsigned int tmp;
531
532 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
533 snd_ice1712_gpio_write(ice, tmp);
534 tmp &= ~cs;
535 snd_ice1712_gpio_write(ice, tmp);
536 udelay(1);
537
538 for (i = bits-1; i >= 0; i--) {
539 if (data & (1 << i))
540 tmp |= AUREON_SPI_MOSI;
541 else
542 tmp &= ~AUREON_SPI_MOSI;
543 snd_ice1712_gpio_write(ice, tmp);
544 udelay(1);
545
546 tmp |= AUREON_SPI_CLK;
547 snd_ice1712_gpio_write(ice, tmp);
548 udelay(1);
549
550 tmp &= ~AUREON_SPI_CLK;
551 snd_ice1712_gpio_write(ice, tmp);
552 udelay(1);
553 }
554
555 for (j = 0; j < size; j++) {
556 unsigned char outdata = 0;
557 for (i = 7; i >= 0; i--) {
558 tmp = snd_ice1712_gpio_read(ice);
559 outdata <<= 1;
560 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
561 udelay(1);
562
563 tmp |= AUREON_SPI_CLK;
564 snd_ice1712_gpio_write(ice, tmp);
565 udelay(1);
566
567 tmp &= ~AUREON_SPI_CLK;
568 snd_ice1712_gpio_write(ice, tmp);
569 udelay(1);
570 }
571 buffer[j] = outdata;
572 }
573
574 tmp |= cs;
575 snd_ice1712_gpio_write(ice, tmp);
576}
577
578static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
579{
580 unsigned char val;
581 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
582 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
583 return val;
584}
585
586static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
587 unsigned char *buffer, int size)
588{
589 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
590 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
591}
592
593static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
594 unsigned char val)
595{
596 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
597}
598
599
600
601
602static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
603{
604 reg <<= 1;
605 return ((unsigned short)ice->akm[0].images[reg] << 8) |
606 ice->akm[0].images[reg + 1];
607}
608
609
610
611
612static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
613{
614 aureon_spi_write(ice,
615 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
616 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
617 PRODIGY_WM_CS : AUREON_WM_CS),
618 (reg << 9) | (val & 0x1ff), 16);
619}
620
621
622
623
624static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
625{
626 wm_put_nocache(ice, reg, val);
627 reg <<= 1;
628 ice->akm[0].images[reg] = val >> 8;
629 ice->akm[0].images[reg + 1] = val;
630}
631
632
633
634#define aureon_mono_bool_info snd_ctl_boolean_mono_info
635
636
637
638
639#define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
640
641static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
642{
643 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
644
645 mutex_lock(&ice->gpio_mutex);
646
647 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
648
649 mutex_unlock(&ice->gpio_mutex);
650 return 0;
651}
652
653static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
654{
655 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
656 unsigned short ovol, nvol;
657 int change;
658
659 snd_ice1712_save_gpio_status(ice);
660
661 ovol = wm_get(ice, WM_OUT_MUX1);
662 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
663 change = (ovol != nvol);
664 if (change)
665 wm_put(ice, WM_OUT_MUX1, nvol);
666
667 snd_ice1712_restore_gpio_status(ice);
668
669 return change;
670}
671
672static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1);
673static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
674static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
675static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
676static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
677
678#define WM_VOL_MAX 100
679#define WM_VOL_CNT 101
680#define WM_VOL_MUTE 0x8000
681
682static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
683{
684 unsigned char nvol;
685
686 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
687 nvol = 0;
688 } else {
689 nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
690 WM_VOL_MAX;
691 nvol += 0x1b;
692 }
693
694 wm_put(ice, index, nvol);
695 wm_put_nocache(ice, index, 0x180 | nvol);
696}
697
698
699
700
701#define wm_pcm_mute_info snd_ctl_boolean_mono_info
702
703static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
704{
705 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
706
707 mutex_lock(&ice->gpio_mutex);
708 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
709 mutex_unlock(&ice->gpio_mutex);
710 return 0;
711}
712
713static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
714{
715 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
716 unsigned short nval, oval;
717 int change;
718
719 snd_ice1712_save_gpio_status(ice);
720 oval = wm_get(ice, WM_MUTE);
721 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
722 change = (oval != nval);
723 if (change)
724 wm_put(ice, WM_MUTE, nval);
725 snd_ice1712_restore_gpio_status(ice);
726
727 return change;
728}
729
730
731
732
733static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
734{
735 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
736 uinfo->count = 2;
737 uinfo->value.integer.min = 0;
738 uinfo->value.integer.max = WM_VOL_MAX;
739 return 0;
740}
741
742static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
743{
744 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
745 struct aureon_spec *spec = ice->spec;
746 int i;
747 for (i = 0; i < 2; i++)
748 ucontrol->value.integer.value[i] =
749 spec->master[i] & ~WM_VOL_MUTE;
750 return 0;
751}
752
753static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
754{
755 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
756 struct aureon_spec *spec = ice->spec;
757 int ch, change = 0;
758
759 snd_ice1712_save_gpio_status(ice);
760 for (ch = 0; ch < 2; ch++) {
761 unsigned int vol = ucontrol->value.integer.value[ch];
762 if (vol > WM_VOL_MAX)
763 vol = WM_VOL_MAX;
764 vol |= spec->master[ch] & WM_VOL_MUTE;
765 if (vol != spec->master[ch]) {
766 int dac;
767 spec->master[ch] = vol;
768 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
769 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
770 spec->vol[dac + ch],
771 spec->master[ch]);
772 change = 1;
773 }
774 }
775 snd_ice1712_restore_gpio_status(ice);
776 return change;
777}
778
779
780
781
782static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
783{
784 int voices = kcontrol->private_value >> 8;
785 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
786 uinfo->count = voices;
787 uinfo->value.integer.min = 0;
788 uinfo->value.integer.max = WM_VOL_MAX;
789 return 0;
790}
791
792static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
793{
794 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
795 struct aureon_spec *spec = ice->spec;
796 int i, ofs, voices;
797
798 voices = kcontrol->private_value >> 8;
799 ofs = kcontrol->private_value & 0xff;
800 for (i = 0; i < voices; i++)
801 ucontrol->value.integer.value[i] =
802 spec->vol[ofs+i] & ~WM_VOL_MUTE;
803 return 0;
804}
805
806static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
807{
808 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
809 struct aureon_spec *spec = ice->spec;
810 int i, idx, ofs, voices;
811 int change = 0;
812
813 voices = kcontrol->private_value >> 8;
814 ofs = kcontrol->private_value & 0xff;
815 snd_ice1712_save_gpio_status(ice);
816 for (i = 0; i < voices; i++) {
817 unsigned int vol = ucontrol->value.integer.value[i];
818 if (vol > WM_VOL_MAX)
819 vol = WM_VOL_MAX;
820 vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
821 if (vol != spec->vol[ofs+i]) {
822 spec->vol[ofs+i] = vol;
823 idx = WM_DAC_ATTEN + ofs + i;
824 wm_set_vol(ice, idx, spec->vol[ofs + i],
825 spec->master[i]);
826 change = 1;
827 }
828 }
829 snd_ice1712_restore_gpio_status(ice);
830 return change;
831}
832
833
834
835
836static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
837{
838 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
839 uinfo->count = kcontrol->private_value >> 8;
840 uinfo->value.integer.min = 0;
841 uinfo->value.integer.max = 1;
842 return 0;
843}
844
845static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
846{
847 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
848 struct aureon_spec *spec = ice->spec;
849 int voices, ofs, i;
850
851 voices = kcontrol->private_value >> 8;
852 ofs = kcontrol->private_value & 0xFF;
853
854 for (i = 0; i < voices; i++)
855 ucontrol->value.integer.value[i] =
856 (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
857 return 0;
858}
859
860static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
861{
862 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
863 struct aureon_spec *spec = ice->spec;
864 int change = 0, voices, ofs, i;
865
866 voices = kcontrol->private_value >> 8;
867 ofs = kcontrol->private_value & 0xFF;
868
869 snd_ice1712_save_gpio_status(ice);
870 for (i = 0; i < voices; i++) {
871 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
872 if (ucontrol->value.integer.value[i] != val) {
873 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
874 spec->vol[ofs + i] |=
875 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
876 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
877 spec->master[i]);
878 change = 1;
879 }
880 }
881 snd_ice1712_restore_gpio_status(ice);
882
883 return change;
884}
885
886
887
888
889#define wm_master_mute_info snd_ctl_boolean_stereo_info
890
891static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
892{
893 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
894 struct aureon_spec *spec = ice->spec;
895
896 ucontrol->value.integer.value[0] =
897 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
898 ucontrol->value.integer.value[1] =
899 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
900 return 0;
901}
902
903static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
904{
905 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
906 struct aureon_spec *spec = ice->spec;
907 int change = 0, i;
908
909 snd_ice1712_save_gpio_status(ice);
910 for (i = 0; i < 2; i++) {
911 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
912 if (ucontrol->value.integer.value[i] != val) {
913 int dac;
914 spec->master[i] &= ~WM_VOL_MUTE;
915 spec->master[i] |=
916 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
917 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
918 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
919 spec->vol[dac + i],
920 spec->master[i]);
921 change = 1;
922 }
923 }
924 snd_ice1712_restore_gpio_status(ice);
925
926 return change;
927}
928
929
930#define PCM_0dB 0xff
931#define PCM_RES 128
932#define PCM_MIN (PCM_0dB - PCM_RES)
933static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
934{
935 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
936 uinfo->count = 1;
937 uinfo->value.integer.min = 0;
938 uinfo->value.integer.max = PCM_RES;
939 return 0;
940}
941
942static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
943{
944 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
945 unsigned short val;
946
947 mutex_lock(&ice->gpio_mutex);
948 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
949 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
950 ucontrol->value.integer.value[0] = val;
951 mutex_unlock(&ice->gpio_mutex);
952 return 0;
953}
954
955static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
956{
957 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
958 unsigned short ovol, nvol;
959 int change = 0;
960
961 nvol = ucontrol->value.integer.value[0];
962 if (nvol > PCM_RES)
963 return -EINVAL;
964 snd_ice1712_save_gpio_status(ice);
965 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
966 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
967 if (ovol != nvol) {
968 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol);
969 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
970 change = 1;
971 }
972 snd_ice1712_restore_gpio_status(ice);
973 return change;
974}
975
976
977
978
979#define wm_adc_mute_info snd_ctl_boolean_stereo_info
980
981static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
982{
983 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
984 unsigned short val;
985 int i;
986
987 mutex_lock(&ice->gpio_mutex);
988 for (i = 0; i < 2; i++) {
989 val = wm_get(ice, WM_ADC_GAIN + i);
990 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
991 }
992 mutex_unlock(&ice->gpio_mutex);
993 return 0;
994}
995
996static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
997{
998 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
999 unsigned short new, old;
1000 int i, change = 0;
1001
1002 snd_ice1712_save_gpio_status(ice);
1003 for (i = 0; i < 2; i++) {
1004 old = wm_get(ice, WM_ADC_GAIN + i);
1005 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1006 if (new != old) {
1007 wm_put(ice, WM_ADC_GAIN + i, new);
1008 change = 1;
1009 }
1010 }
1011 snd_ice1712_restore_gpio_status(ice);
1012
1013 return change;
1014}
1015
1016
1017
1018
1019static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1020{
1021 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1022 uinfo->count = 2;
1023 uinfo->value.integer.min = 0;
1024 uinfo->value.integer.max = 0x1f;
1025 return 0;
1026}
1027
1028static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1029{
1030 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031 int i, idx;
1032 unsigned short vol;
1033
1034 mutex_lock(&ice->gpio_mutex);
1035 for (i = 0; i < 2; i++) {
1036 idx = WM_ADC_GAIN + i;
1037 vol = wm_get(ice, idx) & 0x1f;
1038 ucontrol->value.integer.value[i] = vol;
1039 }
1040 mutex_unlock(&ice->gpio_mutex);
1041 return 0;
1042}
1043
1044static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045{
1046 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1047 int i, idx;
1048 unsigned short ovol, nvol;
1049 int change = 0;
1050
1051 snd_ice1712_save_gpio_status(ice);
1052 for (i = 0; i < 2; i++) {
1053 idx = WM_ADC_GAIN + i;
1054 nvol = ucontrol->value.integer.value[i] & 0x1f;
1055 ovol = wm_get(ice, idx);
1056 if ((ovol & 0x1f) != nvol) {
1057 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058 change = 1;
1059 }
1060 }
1061 snd_ice1712_restore_gpio_status(ice);
1062 return change;
1063}
1064
1065
1066
1067
1068static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1069{
1070 static const char * const texts[] = {
1071 "CD",
1072 "Aux",
1073 "Line",
1074 "Mic",
1075 "AC97"
1076 };
1077 static const char * const universe_texts[] = {
1078 "Aux1",
1079 "CD",
1080 "Phono",
1081 "Line",
1082 "Aux2",
1083 "Mic",
1084 "Aux3",
1085 "AC97"
1086 };
1087 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1088
1089 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE)
1090 return snd_ctl_enum_info(uinfo, 2, 8, universe_texts);
1091 else
1092 return snd_ctl_enum_info(uinfo, 2, 5, texts);
1093}
1094
1095static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1096{
1097 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1098 unsigned short val;
1099
1100 mutex_lock(&ice->gpio_mutex);
1101 val = wm_get(ice, WM_ADC_MUX);
1102 ucontrol->value.enumerated.item[0] = val & 7;
1103 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1104 mutex_unlock(&ice->gpio_mutex);
1105 return 0;
1106}
1107
1108static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1109{
1110 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1111 unsigned short oval, nval;
1112 int change;
1113
1114 snd_ice1712_save_gpio_status(ice);
1115 oval = wm_get(ice, WM_ADC_MUX);
1116 nval = oval & ~0x77;
1117 nval |= ucontrol->value.enumerated.item[0] & 7;
1118 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1119 change = (oval != nval);
1120 if (change)
1121 wm_put(ice, WM_ADC_MUX, nval);
1122 snd_ice1712_restore_gpio_status(ice);
1123 return change;
1124}
1125
1126
1127
1128
1129static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130{
1131 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1132 static const char * const aureon_texts[] = {
1133 "CD",
1134 "Optical"
1135 };
1136 static const char * const prodigy_texts[] = {
1137 "CD",
1138 "Coax"
1139 };
1140 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1141 return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts);
1142 else
1143 return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts);
1144}
1145
1146static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1147{
1148 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1149 struct aureon_spec *spec = ice->spec;
1150
1151
1152
1153 ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1154
1155 return 0;
1156}
1157
1158static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1159{
1160 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1161 struct aureon_spec *spec = ice->spec;
1162 unsigned short oval, nval;
1163 int change;
1164
1165 snd_ice1712_save_gpio_status(ice);
1166 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1167 nval = oval & ~0x07;
1168 nval |= ucontrol->value.enumerated.item[0] & 7;
1169 change = (oval != nval);
1170 if (change)
1171 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1172 snd_ice1712_restore_gpio_status(ice);
1173 spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1174 return change;
1175}
1176
1177static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1178{
1179 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1180 uinfo->count = 1;
1181 uinfo->value.integer.min = 0;
1182 uinfo->value.integer.max = 192000;
1183 return 0;
1184}
1185
1186static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1187{
1188 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1189 unsigned char ratio;
1190 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1191 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1192 return 0;
1193}
1194
1195
1196
1197
1198#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1199
1200static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1201{
1202 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1203 snd_ice1712_save_gpio_status(ice);
1204 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1205 snd_ice1712_restore_gpio_status(ice);
1206 return 0;
1207}
1208
1209static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1210{
1211 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212 unsigned char oval, nval;
1213 int change;
1214 snd_ice1712_save_gpio_status(ice);
1215 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1216 if (ucontrol->value.integer.value[0])
1217 nval = oval & ~0x20;
1218 else
1219 nval = oval | 0x20;
1220 change = (oval != nval);
1221 if (change)
1222 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1223 snd_ice1712_restore_gpio_status(ice);
1224 return change;
1225}
1226
1227
1228
1229
1230static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1231{
1232 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1233 uinfo->count = 10;
1234 return 0;
1235}
1236
1237static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1238{
1239 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240
1241 snd_ice1712_save_gpio_status(ice);
1242 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1243 snd_ice1712_restore_gpio_status(ice);
1244
1245 return 0;
1246}
1247
1248static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1249{
1250 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1251 uinfo->count = 1;
1252 return 0;
1253}
1254
1255static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1256{
1257 memset(ucontrol->value.iec958.status, 0xFF, 24);
1258 return 0;
1259}
1260
1261static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1262{
1263 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1264
1265 snd_ice1712_save_gpio_status(ice);
1266 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1267 snd_ice1712_restore_gpio_status(ice);
1268 return 0;
1269}
1270
1271
1272
1273
1274static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1275{
1276 unsigned int tmp, tmp2;
1277
1278 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1279 if (enable)
1280 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1281 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1282 tmp |= AUREON_HP_SEL;
1283 else
1284 tmp |= PRODIGY_HP_SEL;
1285 else
1286 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1287 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1288 tmp &= ~AUREON_HP_SEL;
1289 else
1290 tmp &= ~PRODIGY_HP_SEL;
1291 if (tmp != tmp2) {
1292 snd_ice1712_gpio_write(ice, tmp);
1293 return 1;
1294 }
1295 return 0;
1296}
1297
1298static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1299{
1300 unsigned int tmp = snd_ice1712_gpio_read(ice);
1301
1302 return (tmp & AUREON_HP_SEL) != 0;
1303}
1304
1305#define aureon_hpamp_info snd_ctl_boolean_mono_info
1306
1307static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1308{
1309 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1310
1311 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1312 return 0;
1313}
1314
1315
1316static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1317{
1318 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1319
1320 return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1321}
1322
1323
1324
1325
1326
1327#define aureon_deemp_info snd_ctl_boolean_mono_info
1328
1329static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1330{
1331 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1332 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1333 return 0;
1334}
1335
1336static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1337{
1338 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1339 int temp, temp2;
1340 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1341 if (ucontrol->value.integer.value[0])
1342 temp |= 0xf;
1343 else
1344 temp &= ~0xf;
1345 if (temp != temp2) {
1346 wm_put(ice, WM_DAC_CTRL2, temp);
1347 return 1;
1348 }
1349 return 0;
1350}
1351
1352
1353
1354
1355static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1356{
1357 static const char * const texts[2] = { "128x", "64x" };
1358
1359 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1360}
1361
1362static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363{
1364 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1365 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1366 return 0;
1367}
1368
1369static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1370{
1371 int temp, temp2;
1372 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1373
1374 temp2 = temp = wm_get(ice, WM_MASTER);
1375
1376 if (ucontrol->value.enumerated.item[0])
1377 temp |= 0x8;
1378 else
1379 temp &= ~0x8;
1380
1381 if (temp != temp2) {
1382 wm_put(ice, WM_MASTER, temp);
1383 return 1;
1384 }
1385 return 0;
1386}
1387
1388
1389
1390
1391
1392static struct snd_kcontrol_new aureon_dac_controls[] = {
1393 {
1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395 .name = "Master Playback Switch",
1396 .info = wm_master_mute_info,
1397 .get = wm_master_mute_get,
1398 .put = wm_master_mute_put
1399 },
1400 {
1401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1402 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1403 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1404 .name = "Master Playback Volume",
1405 .info = wm_master_vol_info,
1406 .get = wm_master_vol_get,
1407 .put = wm_master_vol_put,
1408 .tlv = { .p = db_scale_wm_dac }
1409 },
1410 {
1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412 .name = "Front Playback Switch",
1413 .info = wm_mute_info,
1414 .get = wm_mute_get,
1415 .put = wm_mute_put,
1416 .private_value = (2 << 8) | 0
1417 },
1418 {
1419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1421 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1422 .name = "Front Playback Volume",
1423 .info = wm_vol_info,
1424 .get = wm_vol_get,
1425 .put = wm_vol_put,
1426 .private_value = (2 << 8) | 0,
1427 .tlv = { .p = db_scale_wm_dac }
1428 },
1429 {
1430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1431 .name = "Rear Playback Switch",
1432 .info = wm_mute_info,
1433 .get = wm_mute_get,
1434 .put = wm_mute_put,
1435 .private_value = (2 << 8) | 2
1436 },
1437 {
1438 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1440 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1441 .name = "Rear Playback Volume",
1442 .info = wm_vol_info,
1443 .get = wm_vol_get,
1444 .put = wm_vol_put,
1445 .private_value = (2 << 8) | 2,
1446 .tlv = { .p = db_scale_wm_dac }
1447 },
1448 {
1449 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1450 .name = "Center Playback Switch",
1451 .info = wm_mute_info,
1452 .get = wm_mute_get,
1453 .put = wm_mute_put,
1454 .private_value = (1 << 8) | 4
1455 },
1456 {
1457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1458 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1459 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1460 .name = "Center Playback Volume",
1461 .info = wm_vol_info,
1462 .get = wm_vol_get,
1463 .put = wm_vol_put,
1464 .private_value = (1 << 8) | 4,
1465 .tlv = { .p = db_scale_wm_dac }
1466 },
1467 {
1468 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1469 .name = "LFE Playback Switch",
1470 .info = wm_mute_info,
1471 .get = wm_mute_get,
1472 .put = wm_mute_put,
1473 .private_value = (1 << 8) | 5
1474 },
1475 {
1476 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1477 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1478 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1479 .name = "LFE Playback Volume",
1480 .info = wm_vol_info,
1481 .get = wm_vol_get,
1482 .put = wm_vol_put,
1483 .private_value = (1 << 8) | 5,
1484 .tlv = { .p = db_scale_wm_dac }
1485 },
1486 {
1487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1488 .name = "Side Playback Switch",
1489 .info = wm_mute_info,
1490 .get = wm_mute_get,
1491 .put = wm_mute_put,
1492 .private_value = (2 << 8) | 6
1493 },
1494 {
1495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1496 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1497 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1498 .name = "Side Playback Volume",
1499 .info = wm_vol_info,
1500 .get = wm_vol_get,
1501 .put = wm_vol_put,
1502 .private_value = (2 << 8) | 6,
1503 .tlv = { .p = db_scale_wm_dac }
1504 }
1505};
1506
1507static struct snd_kcontrol_new wm_controls[] = {
1508 {
1509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1510 .name = "PCM Playback Switch",
1511 .info = wm_pcm_mute_info,
1512 .get = wm_pcm_mute_get,
1513 .put = wm_pcm_mute_put
1514 },
1515 {
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1519 .name = "PCM Playback Volume",
1520 .info = wm_pcm_vol_info,
1521 .get = wm_pcm_vol_get,
1522 .put = wm_pcm_vol_put,
1523 .tlv = { .p = db_scale_wm_pcm }
1524 },
1525 {
1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527 .name = "Capture Switch",
1528 .info = wm_adc_mute_info,
1529 .get = wm_adc_mute_get,
1530 .put = wm_adc_mute_put,
1531 },
1532 {
1533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1536 .name = "Capture Volume",
1537 .info = wm_adc_vol_info,
1538 .get = wm_adc_vol_get,
1539 .put = wm_adc_vol_put,
1540 .tlv = { .p = db_scale_wm_adc }
1541 },
1542 {
1543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544 .name = "Capture Source",
1545 .info = wm_adc_mux_info,
1546 .get = wm_adc_mux_get,
1547 .put = wm_adc_mux_put,
1548 .private_value = 5
1549 },
1550 {
1551 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1552 .name = "External Amplifier",
1553 .info = aureon_hpamp_info,
1554 .get = aureon_hpamp_get,
1555 .put = aureon_hpamp_put
1556 },
1557 {
1558 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1559 .name = "DAC Deemphasis Switch",
1560 .info = aureon_deemp_info,
1561 .get = aureon_deemp_get,
1562 .put = aureon_deemp_put
1563 },
1564 {
1565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566 .name = "ADC Oversampling",
1567 .info = aureon_oversampling_info,
1568 .get = aureon_oversampling_get,
1569 .put = aureon_oversampling_put
1570 }
1571};
1572
1573static struct snd_kcontrol_new ac97_controls[] = {
1574 {
1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576 .name = "AC97 Playback Switch",
1577 .info = aureon_ac97_mmute_info,
1578 .get = aureon_ac97_mmute_get,
1579 .put = aureon_ac97_mmute_put,
1580 .private_value = AC97_MASTER
1581 },
1582 {
1583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1585 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1586 .name = "AC97 Playback Volume",
1587 .info = aureon_ac97_vol_info,
1588 .get = aureon_ac97_vol_get,
1589 .put = aureon_ac97_vol_put,
1590 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1591 .tlv = { .p = db_scale_ac97_master }
1592 },
1593 {
1594 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595 .name = "CD Playback Switch",
1596 .info = aureon_ac97_mute_info,
1597 .get = aureon_ac97_mute_get,
1598 .put = aureon_ac97_mute_put,
1599 .private_value = AC97_CD
1600 },
1601 {
1602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1604 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1605 .name = "CD Playback Volume",
1606 .info = aureon_ac97_vol_info,
1607 .get = aureon_ac97_vol_get,
1608 .put = aureon_ac97_vol_put,
1609 .private_value = AC97_CD|AUREON_AC97_STEREO,
1610 .tlv = { .p = db_scale_ac97_gain }
1611 },
1612 {
1613 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1614 .name = "Aux Playback Switch",
1615 .info = aureon_ac97_mute_info,
1616 .get = aureon_ac97_mute_get,
1617 .put = aureon_ac97_mute_put,
1618 .private_value = AC97_AUX,
1619 },
1620 {
1621 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1623 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1624 .name = "Aux Playback Volume",
1625 .info = aureon_ac97_vol_info,
1626 .get = aureon_ac97_vol_get,
1627 .put = aureon_ac97_vol_put,
1628 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1629 .tlv = { .p = db_scale_ac97_gain }
1630 },
1631 {
1632 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1633 .name = "Line Playback Switch",
1634 .info = aureon_ac97_mute_info,
1635 .get = aureon_ac97_mute_get,
1636 .put = aureon_ac97_mute_put,
1637 .private_value = AC97_LINE
1638 },
1639 {
1640 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1641 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1642 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1643 .name = "Line Playback Volume",
1644 .info = aureon_ac97_vol_info,
1645 .get = aureon_ac97_vol_get,
1646 .put = aureon_ac97_vol_put,
1647 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1648 .tlv = { .p = db_scale_ac97_gain }
1649 },
1650 {
1651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1652 .name = "Mic Playback Switch",
1653 .info = aureon_ac97_mute_info,
1654 .get = aureon_ac97_mute_get,
1655 .put = aureon_ac97_mute_put,
1656 .private_value = AC97_MIC
1657 },
1658 {
1659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1661 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1662 .name = "Mic Playback Volume",
1663 .info = aureon_ac97_vol_info,
1664 .get = aureon_ac97_vol_get,
1665 .put = aureon_ac97_vol_put,
1666 .private_value = AC97_MIC,
1667 .tlv = { .p = db_scale_ac97_gain }
1668 },
1669 {
1670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671 .name = "Mic Boost (+20dB)",
1672 .info = aureon_ac97_micboost_info,
1673 .get = aureon_ac97_micboost_get,
1674 .put = aureon_ac97_micboost_put
1675 }
1676};
1677
1678static struct snd_kcontrol_new universe_ac97_controls[] = {
1679 {
1680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681 .name = "AC97 Playback Switch",
1682 .info = aureon_ac97_mmute_info,
1683 .get = aureon_ac97_mmute_get,
1684 .put = aureon_ac97_mmute_put,
1685 .private_value = AC97_MASTER
1686 },
1687 {
1688 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1689 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1690 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1691 .name = "AC97 Playback Volume",
1692 .info = aureon_ac97_vol_info,
1693 .get = aureon_ac97_vol_get,
1694 .put = aureon_ac97_vol_put,
1695 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1696 .tlv = { .p = db_scale_ac97_master }
1697 },
1698 {
1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700 .name = "CD Playback Switch",
1701 .info = aureon_ac97_mute_info,
1702 .get = aureon_ac97_mute_get,
1703 .put = aureon_ac97_mute_put,
1704 .private_value = AC97_AUX
1705 },
1706 {
1707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1709 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1710 .name = "CD Playback Volume",
1711 .info = aureon_ac97_vol_info,
1712 .get = aureon_ac97_vol_get,
1713 .put = aureon_ac97_vol_put,
1714 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1715 .tlv = { .p = db_scale_ac97_gain }
1716 },
1717 {
1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719 .name = "Phono Playback Switch",
1720 .info = aureon_ac97_mute_info,
1721 .get = aureon_ac97_mute_get,
1722 .put = aureon_ac97_mute_put,
1723 .private_value = AC97_CD
1724 },
1725 {
1726 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1727 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1728 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1729 .name = "Phono Playback Volume",
1730 .info = aureon_ac97_vol_info,
1731 .get = aureon_ac97_vol_get,
1732 .put = aureon_ac97_vol_put,
1733 .private_value = AC97_CD|AUREON_AC97_STEREO,
1734 .tlv = { .p = db_scale_ac97_gain }
1735 },
1736 {
1737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1738 .name = "Line Playback Switch",
1739 .info = aureon_ac97_mute_info,
1740 .get = aureon_ac97_mute_get,
1741 .put = aureon_ac97_mute_put,
1742 .private_value = AC97_LINE
1743 },
1744 {
1745 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1747 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1748 .name = "Line Playback Volume",
1749 .info = aureon_ac97_vol_info,
1750 .get = aureon_ac97_vol_get,
1751 .put = aureon_ac97_vol_put,
1752 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1753 .tlv = { .p = db_scale_ac97_gain }
1754 },
1755 {
1756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1757 .name = "Mic Playback Switch",
1758 .info = aureon_ac97_mute_info,
1759 .get = aureon_ac97_mute_get,
1760 .put = aureon_ac97_mute_put,
1761 .private_value = AC97_MIC
1762 },
1763 {
1764 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1766 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1767 .name = "Mic Playback Volume",
1768 .info = aureon_ac97_vol_info,
1769 .get = aureon_ac97_vol_get,
1770 .put = aureon_ac97_vol_put,
1771 .private_value = AC97_MIC,
1772 .tlv = { .p = db_scale_ac97_gain }
1773 },
1774 {
1775 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1776 .name = "Mic Boost (+20dB)",
1777 .info = aureon_ac97_micboost_info,
1778 .get = aureon_ac97_micboost_get,
1779 .put = aureon_ac97_micboost_put
1780 },
1781 {
1782 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1783 .name = "Aux Playback Switch",
1784 .info = aureon_ac97_mute_info,
1785 .get = aureon_ac97_mute_get,
1786 .put = aureon_ac97_mute_put,
1787 .private_value = AC97_VIDEO,
1788 },
1789 {
1790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1792 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1793 .name = "Aux Playback Volume",
1794 .info = aureon_ac97_vol_info,
1795 .get = aureon_ac97_vol_get,
1796 .put = aureon_ac97_vol_put,
1797 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1798 .tlv = { .p = db_scale_ac97_gain }
1799 },
1800 {
1801 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1802 .name = "Aux Source",
1803 .info = aureon_universe_inmux_info,
1804 .get = aureon_universe_inmux_get,
1805 .put = aureon_universe_inmux_put
1806 }
1807
1808};
1809
1810static struct snd_kcontrol_new cs8415_controls[] = {
1811 {
1812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1813 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1814 .info = aureon_cs8415_mute_info,
1815 .get = aureon_cs8415_mute_get,
1816 .put = aureon_cs8415_mute_put
1817 },
1818 {
1819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1820 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1821 .info = aureon_cs8415_mux_info,
1822 .get = aureon_cs8415_mux_get,
1823 .put = aureon_cs8415_mux_put,
1824 },
1825 {
1826 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1827 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1828 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1829 .info = aureon_cs8415_qsub_info,
1830 .get = aureon_cs8415_qsub_get,
1831 },
1832 {
1833 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1834 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1835 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1836 .info = aureon_cs8415_spdif_info,
1837 .get = aureon_cs8415_mask_get
1838 },
1839 {
1840 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1841 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1842 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1843 .info = aureon_cs8415_spdif_info,
1844 .get = aureon_cs8415_spdif_get
1845 },
1846 {
1847 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1848 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1849 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1850 .info = aureon_cs8415_rate_info,
1851 .get = aureon_cs8415_rate_get
1852 }
1853};
1854
1855static int aureon_add_controls(struct snd_ice1712 *ice)
1856{
1857 unsigned int i, counts;
1858 int err;
1859
1860 counts = ARRAY_SIZE(aureon_dac_controls);
1861 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1862 counts -= 2;
1863 for (i = 0; i < counts; i++) {
1864 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1865 if (err < 0)
1866 return err;
1867 }
1868
1869 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1870 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1871 if (err < 0)
1872 return err;
1873 }
1874
1875 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1876 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1877 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1878 if (err < 0)
1879 return err;
1880 }
1881 } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1882 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1883 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1884 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1885 if (err < 0)
1886 return err;
1887 }
1888 }
1889
1890 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1891 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1892 unsigned char id;
1893 snd_ice1712_save_gpio_status(ice);
1894 id = aureon_cs8415_get(ice, CS8415_ID);
1895 if (id != 0x41)
1896 dev_info(ice->card->dev,
1897 "No CS8415 chip. Skipping CS8415 controls.\n");
1898 else if ((id & 0x0F) != 0x01)
1899 dev_info(ice->card->dev,
1900 "Detected unsupported CS8415 rev. (%c)\n",
1901 (char)((id & 0x0F) + 'A' - 1));
1902 else {
1903 for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1904 struct snd_kcontrol *kctl;
1905 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1906 if (err < 0)
1907 return err;
1908 if (i > 1)
1909 kctl->id.device = ice->pcm->device;
1910 }
1911 }
1912 snd_ice1712_restore_gpio_status(ice);
1913 }
1914
1915 return 0;
1916}
1917
1918
1919
1920
1921static int aureon_reset(struct snd_ice1712 *ice)
1922{
1923 static const unsigned short wm_inits_aureon[] = {
1924
1925 0x1b, 0x044,
1926 0x1c, 0x00B,
1927 0x1d, 0x009,
1928
1929 0x18, 0x000,
1930
1931 0x16, 0x122,
1932 0x17, 0x022,
1933 0x00, 0,
1934 0x01, 0,
1935 0x02, 0,
1936 0x03, 0,
1937 0x04, 0,
1938 0x05, 0,
1939 0x06, 0,
1940 0x07, 0,
1941 0x08, 0x100,
1942 0x09, 0xff,
1943 0x0a, 0xff,
1944 0x0b, 0xff,
1945 0x0c, 0xff,
1946 0x0d, 0xff,
1947 0x0e, 0xff,
1948 0x0f, 0xff,
1949 0x10, 0xff,
1950 0x11, 0x1ff,
1951 0x12, 0x000,
1952 0x13, 0x090,
1953 0x14, 0x000,
1954 0x15, 0x000,
1955 0x19, 0x000,
1956 0x1a, 0x000,
1957 (unsigned short)-1
1958 };
1959 static const unsigned short wm_inits_prodigy[] = {
1960
1961
1962 0x1b, 0x000,
1963 0x1c, 0x009,
1964 0x1d, 0x009,
1965
1966 0x18, 0x000,
1967
1968 0x16, 0x022,
1969 0x17, 0x006,
1970
1971 0x00, 0,
1972 0x01, 0,
1973 0x02, 0,
1974 0x03, 0,
1975 0x04, 0,
1976 0x05, 0,
1977 0x06, 0,
1978 0x07, 0,
1979 0x08, 0x100,
1980
1981 0x09, 0x7f,
1982 0x0a, 0x7f,
1983 0x0b, 0x7f,
1984 0x0c, 0x7f,
1985 0x0d, 0x7f,
1986 0x0e, 0x7f,
1987 0x0f, 0x7f,
1988 0x10, 0x7f,
1989 0x11, 0x1FF,
1990
1991 0x12, 0x000,
1992 0x13, 0x090,
1993 0x14, 0x000,
1994 0x15, 0x000,
1995
1996 0x19, 0x000,
1997 0x1a, 0x000,
1998 (unsigned short)-1
1999
2000 };
2001 static const unsigned short cs_inits[] = {
2002 0x0441,
2003 0x0180,
2004 0x0201,
2005 0x0605,
2006 (unsigned short)-1
2007 };
2008 unsigned int tmp;
2009 const unsigned short *p;
2010 int err;
2011 struct aureon_spec *spec = ice->spec;
2012
2013 err = aureon_ac97_init(ice);
2014 if (err != 0)
2015 return err;
2016
2017 snd_ice1712_gpio_set_dir(ice, 0x5fffff);
2018
2019
2020 snd_ice1712_save_gpio_status(ice);
2021 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2022
2023 tmp = snd_ice1712_gpio_read(ice);
2024 tmp &= ~AUREON_WM_RESET;
2025 snd_ice1712_gpio_write(ice, tmp);
2026 udelay(1);
2027 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2028 snd_ice1712_gpio_write(ice, tmp);
2029 udelay(1);
2030 tmp |= AUREON_WM_RESET;
2031 snd_ice1712_gpio_write(ice, tmp);
2032 udelay(1);
2033
2034
2035 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2036 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2037 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2038 p = wm_inits_prodigy;
2039 else
2040 p = wm_inits_aureon;
2041 for (; *p != (unsigned short)-1; p += 2)
2042 wm_put(ice, p[0], p[1]);
2043
2044
2045 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2046 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2047 for (p = cs_inits; *p != (unsigned short)-1; p++)
2048 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2049 spec->cs8415_mux = 1;
2050
2051 aureon_set_headphone_amp(ice, 1);
2052 }
2053
2054 snd_ice1712_restore_gpio_status(ice);
2055
2056
2057 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2058 aureon_pca9554_write(ice, PCA9554_OUT, 0x00);
2059 return 0;
2060}
2061
2062
2063
2064
2065#ifdef CONFIG_PM_SLEEP
2066static int aureon_resume(struct snd_ice1712 *ice)
2067{
2068 struct aureon_spec *spec = ice->spec;
2069 int err, i;
2070
2071 err = aureon_reset(ice);
2072 if (err != 0)
2073 return err;
2074
2075
2076
2077 for (i = 0; i < ice->num_total_dacs; i++)
2078 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2079 return 0;
2080}
2081#endif
2082
2083
2084
2085
2086static int aureon_init(struct snd_ice1712 *ice)
2087{
2088 struct aureon_spec *spec;
2089 int i, err;
2090
2091 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2092 if (!spec)
2093 return -ENOMEM;
2094 ice->spec = spec;
2095
2096 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2097 ice->num_total_dacs = 6;
2098 ice->num_total_adcs = 2;
2099 } else {
2100
2101 ice->num_total_dacs = 8;
2102 ice->num_total_adcs = 2;
2103 }
2104
2105
2106 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2107 if (!ice->akm)
2108 return -ENOMEM;
2109 ice->akm_codecs = 1;
2110
2111 err = aureon_reset(ice);
2112 if (err != 0)
2113 return err;
2114
2115 spec->master[0] = WM_VOL_MUTE;
2116 spec->master[1] = WM_VOL_MUTE;
2117 for (i = 0; i < ice->num_total_dacs; i++) {
2118 spec->vol[i] = WM_VOL_MUTE;
2119 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2120 }
2121
2122#ifdef CONFIG_PM_SLEEP
2123 ice->pm_resume = aureon_resume;
2124 ice->pm_suspend_enabled = 1;
2125#endif
2126
2127 return 0;
2128}
2129
2130
2131
2132
2133
2134
2135
2136static unsigned char aureon51_eeprom[] = {
2137 [ICE_EEP2_SYSCONF] = 0x0a,
2138 [ICE_EEP2_ACLINK] = 0x80,
2139 [ICE_EEP2_I2S] = 0xfc,
2140 [ICE_EEP2_SPDIF] = 0xc3,
2141 [ICE_EEP2_GPIO_DIR] = 0xff,
2142 [ICE_EEP2_GPIO_DIR1] = 0xff,
2143 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2144 [ICE_EEP2_GPIO_MASK] = 0x00,
2145 [ICE_EEP2_GPIO_MASK1] = 0x00,
2146 [ICE_EEP2_GPIO_MASK2] = 0x00,
2147 [ICE_EEP2_GPIO_STATE] = 0x00,
2148 [ICE_EEP2_GPIO_STATE1] = 0x00,
2149 [ICE_EEP2_GPIO_STATE2] = 0x00,
2150};
2151
2152static unsigned char aureon71_eeprom[] = {
2153 [ICE_EEP2_SYSCONF] = 0x0b,
2154 [ICE_EEP2_ACLINK] = 0x80,
2155 [ICE_EEP2_I2S] = 0xfc,
2156 [ICE_EEP2_SPDIF] = 0xc3,
2157 [ICE_EEP2_GPIO_DIR] = 0xff,
2158 [ICE_EEP2_GPIO_DIR1] = 0xff,
2159 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2160 [ICE_EEP2_GPIO_MASK] = 0x00,
2161 [ICE_EEP2_GPIO_MASK1] = 0x00,
2162 [ICE_EEP2_GPIO_MASK2] = 0x00,
2163 [ICE_EEP2_GPIO_STATE] = 0x00,
2164 [ICE_EEP2_GPIO_STATE1] = 0x00,
2165 [ICE_EEP2_GPIO_STATE2] = 0x00,
2166};
2167#define prodigy71_eeprom aureon71_eeprom
2168
2169static unsigned char aureon71_universe_eeprom[] = {
2170 [ICE_EEP2_SYSCONF] = 0x2b,
2171
2172
2173 [ICE_EEP2_ACLINK] = 0x80,
2174 [ICE_EEP2_I2S] = 0xfc,
2175 [ICE_EEP2_SPDIF] = 0xc3,
2176 [ICE_EEP2_GPIO_DIR] = 0xff,
2177 [ICE_EEP2_GPIO_DIR1] = 0xff,
2178 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2179 [ICE_EEP2_GPIO_MASK] = 0x00,
2180 [ICE_EEP2_GPIO_MASK1] = 0x00,
2181 [ICE_EEP2_GPIO_MASK2] = 0x00,
2182 [ICE_EEP2_GPIO_STATE] = 0x00,
2183 [ICE_EEP2_GPIO_STATE1] = 0x00,
2184 [ICE_EEP2_GPIO_STATE2] = 0x00,
2185};
2186
2187static unsigned char prodigy71lt_eeprom[] = {
2188 [ICE_EEP2_SYSCONF] = 0x4b,
2189 [ICE_EEP2_ACLINK] = 0x80,
2190 [ICE_EEP2_I2S] = 0xfc,
2191 [ICE_EEP2_SPDIF] = 0xc3,
2192 [ICE_EEP2_GPIO_DIR] = 0xff,
2193 [ICE_EEP2_GPIO_DIR1] = 0xff,
2194 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2195 [ICE_EEP2_GPIO_MASK] = 0x00,
2196 [ICE_EEP2_GPIO_MASK1] = 0x00,
2197 [ICE_EEP2_GPIO_MASK2] = 0x00,
2198 [ICE_EEP2_GPIO_STATE] = 0x00,
2199 [ICE_EEP2_GPIO_STATE1] = 0x00,
2200 [ICE_EEP2_GPIO_STATE2] = 0x00,
2201};
2202#define prodigy71xt_eeprom prodigy71lt_eeprom
2203
2204
2205struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
2206 {
2207 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2208 .name = "Terratec Aureon 5.1-Sky",
2209 .model = "aureon51",
2210 .chip_init = aureon_init,
2211 .build_controls = aureon_add_controls,
2212 .eeprom_size = sizeof(aureon51_eeprom),
2213 .eeprom_data = aureon51_eeprom,
2214 .driver = "Aureon51",
2215 },
2216 {
2217 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2218 .name = "Terratec Aureon 7.1-Space",
2219 .model = "aureon71",
2220 .chip_init = aureon_init,
2221 .build_controls = aureon_add_controls,
2222 .eeprom_size = sizeof(aureon71_eeprom),
2223 .eeprom_data = aureon71_eeprom,
2224 .driver = "Aureon71",
2225 },
2226 {
2227 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2228 .name = "Terratec Aureon 7.1-Universe",
2229 .model = "universe",
2230 .chip_init = aureon_init,
2231 .build_controls = aureon_add_controls,
2232 .eeprom_size = sizeof(aureon71_universe_eeprom),
2233 .eeprom_data = aureon71_universe_eeprom,
2234 .driver = "Aureon71Univ",
2235 },
2236 {
2237 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2238 .name = "Audiotrak Prodigy 7.1",
2239 .model = "prodigy71",
2240 .chip_init = aureon_init,
2241 .build_controls = aureon_add_controls,
2242 .eeprom_size = sizeof(prodigy71_eeprom),
2243 .eeprom_data = prodigy71_eeprom,
2244 .driver = "Prodigy71",
2245 },
2246 {
2247 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2248 .name = "Audiotrak Prodigy 7.1 LT",
2249 .model = "prodigy71lt",
2250 .chip_init = aureon_init,
2251 .build_controls = aureon_add_controls,
2252 .eeprom_size = sizeof(prodigy71lt_eeprom),
2253 .eeprom_data = prodigy71lt_eeprom,
2254 .driver = "Prodigy71LT",
2255 },
2256 {
2257 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2258 .name = "Audiotrak Prodigy 7.1 XT",
2259 .model = "prodigy71xt",
2260 .chip_init = aureon_init,
2261 .build_controls = aureon_add_controls,
2262 .eeprom_size = sizeof(prodigy71xt_eeprom),
2263 .eeprom_data = prodigy71xt_eeprom,
2264 .driver = "Prodigy71LT",
2265 },
2266 { }
2267};
2268