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#include <asm/io.h>
26#include <linux/delay.h>
27#include <linux/interrupt.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <sound/core.h>
31#include <sound/tlv.h>
32
33#include "ice1712.h"
34#include "envy24ht.h"
35#include "se.h"
36
37struct se_spec {
38 struct {
39 unsigned char ch1, ch2;
40 } vol[8];
41};
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
118{
119
120}
121
122
123static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
124 unsigned int rate)
125{
126
127}
128
129
130
131
132
133
134static void se200pci_WM8766_write(struct snd_ice1712 *ice,
135 unsigned int addr, unsigned int data)
136{
137 unsigned int st;
138 unsigned int bits;
139 int i;
140 const unsigned int DATA = 0x010000;
141 const unsigned int CLOCK = 0x020000;
142 const unsigned int LOAD = 0x040000;
143 const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
144
145 snd_ice1712_save_gpio_status(ice);
146
147 st = ((addr & 0x7f) << 9) | (data & 0x1ff);
148 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
149 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
150 bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
151
152 snd_ice1712_gpio_write(ice, bits);
153 for (i = 0; i < 16; i++) {
154 udelay(1);
155 bits &= ~CLOCK;
156 st = (st << 1);
157 if (st & 0x10000)
158 bits |= DATA;
159 else
160 bits &= ~DATA;
161
162 snd_ice1712_gpio_write(ice, bits);
163
164 udelay(1);
165 bits |= CLOCK;
166 snd_ice1712_gpio_write(ice, bits);
167 }
168
169 udelay(1);
170 bits |= LOAD;
171 snd_ice1712_gpio_write(ice, bits);
172
173 udelay(1);
174 bits |= (DATA | CLOCK);
175 snd_ice1712_gpio_write(ice, bits);
176
177 snd_ice1712_restore_gpio_status(ice);
178}
179
180static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
181 unsigned int vol1, unsigned int vol2)
182{
183 switch (ch) {
184 case 0:
185 se200pci_WM8766_write(ice, 0x000, vol1);
186 se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
187 break;
188 case 1:
189 se200pci_WM8766_write(ice, 0x004, vol1);
190 se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
191 break;
192 case 2:
193 se200pci_WM8766_write(ice, 0x006, vol1);
194 se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
195 break;
196 }
197}
198
199static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
200{
201 se200pci_WM8766_write(ice, 0x1f, 0x000);
202 udelay(10);
203
204 se200pci_WM8766_set_volume(ice, 0, 0, 0);
205 se200pci_WM8766_set_volume(ice, 1, 0, 0);
206 se200pci_WM8766_set_volume(ice, 2, 0, 0);
207
208 se200pci_WM8766_write(ice, 0x03, 0x022);
209 se200pci_WM8766_write(ice, 0x0a, 0x080);
210 se200pci_WM8766_write(ice, 0x12, 0x000);
211 se200pci_WM8766_write(ice, 0x15, 0x000);
212 se200pci_WM8766_write(ice, 0x09, 0x000);
213
214 se200pci_WM8766_write(ice, 0x02, 0x124);
215 se200pci_WM8766_write(ice, 0x02, 0x120);
216}
217
218static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
219 unsigned int rate)
220{
221 if (rate > 96000)
222 se200pci_WM8766_write(ice, 0x0a, 0x000);
223 else
224 se200pci_WM8766_write(ice, 0x0a, 0x080);
225}
226
227
228
229
230
231
232static void se200pci_WM8776_write(struct snd_ice1712 *ice,
233 unsigned int addr, unsigned int data)
234{
235 unsigned int val;
236
237 val = (addr << 9) | data;
238 snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
239}
240
241
242static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
243 unsigned int vol1, unsigned int vol2)
244{
245 se200pci_WM8776_write(ice, 0x03, vol1);
246 se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
247}
248
249static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
250 unsigned int vol1, unsigned int vol2)
251{
252 se200pci_WM8776_write(ice, 0x0e, vol1);
253 se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
254}
255
256static const char *se200pci_sel[] = {
257 "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
258};
259
260static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
261 unsigned int sel)
262{
263 static unsigned char vals[] = {
264
265 0x10, 0x04, 0x08, 0x1c, 0x03
266 };
267 if (sel > 4)
268 sel = 4;
269 se200pci_WM8776_write(ice, 0x15, vals[sel]);
270}
271
272static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
273{
274
275 if (afl)
276 se200pci_WM8776_write(ice, 0x16, 0x005);
277 else
278 se200pci_WM8776_write(ice, 0x16, 0x001);
279}
280
281static const char *se200pci_agc[] = {
282 "Off", "LimiterMode", "ALCMode", NULL
283};
284
285static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
286{
287
288 switch (agc) {
289 case 0:
290 se200pci_WM8776_write(ice, 0x11, 0x000);
291 break;
292 case 1:
293 se200pci_WM8776_write(ice, 0x10, 0x07b);
294 se200pci_WM8776_write(ice, 0x11, 0x100);
295 break;
296 case 2:
297 se200pci_WM8776_write(ice, 0x10, 0x1fb);
298 se200pci_WM8776_write(ice, 0x11, 0x100);
299 break;
300 }
301}
302
303static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
304{
305 int i;
306 static unsigned short __devinitdata default_values[] = {
307 0x100, 0x100, 0x100,
308 0x100, 0x100, 0x100,
309 0x000, 0x090, 0x000, 0x000,
310 0x022, 0x022, 0x022,
311 0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
312 0x032, 0x000, 0x0a6, 0x001, 0x001
313 };
314
315 se200pci_WM8776_write(ice, 0x17, 0x000);
316
317
318 udelay(10);
319
320 for (i = 0; i < ARRAY_SIZE(default_values); i++)
321 se200pci_WM8776_write(ice, i, default_values[i]);
322
323 se200pci_WM8776_set_input_selector(ice, 0);
324 se200pci_WM8776_set_afl(ice, 0);
325 se200pci_WM8776_set_agc(ice, 0);
326 se200pci_WM8776_set_input_volume(ice, 0, 0);
327 se200pci_WM8776_set_output_volume(ice, 0, 0);
328
329
330 se200pci_WM8776_write(ice, 0x00, 0);
331 se200pci_WM8776_write(ice, 0x01, 0);
332 se200pci_WM8776_write(ice, 0x02, 0x100);
333 se200pci_WM8776_write(ice, 0x0d, 0x080);
334}
335
336static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
337 unsigned int rate)
338{
339
340}
341
342
343
344
345
346
347static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
348{
349 se200pci_WM8740_set_pro_rate(ice, rate);
350 se200pci_WM8766_set_pro_rate(ice, rate);
351 se200pci_WM8776_set_pro_rate(ice, rate);
352}
353
354struct se200pci_control {
355 char *name;
356 enum {
357 WM8766,
358 WM8776in,
359 WM8776out,
360 WM8776sel,
361 WM8776agc,
362 WM8776afl
363 } target;
364 enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
365 int ch;
366 const char **member;
367 const char *comment;
368};
369
370static const struct se200pci_control se200pci_cont[] = {
371 {
372 .name = "Front Playback Volume",
373 .target = WM8776out,
374 .type = VOLUME1,
375 .comment = "Front(green)"
376 },
377 {
378 .name = "Side Playback Volume",
379 .target = WM8766,
380 .type = VOLUME1,
381 .ch = 1,
382 .comment = "Surround(orange)"
383 },
384 {
385 .name = "Surround Playback Volume",
386 .target = WM8766,
387 .type = VOLUME1,
388 .ch = 2,
389 .comment = "SurroundBack(white)"
390 },
391 {
392 .name = "CLFE Playback Volume",
393 .target = WM8766,
394 .type = VOLUME1,
395 .ch = 0,
396 .comment = "Center(Lch)&SubWoofer(Rch)(black)"
397 },
398 {
399 .name = "Capture Volume",
400 .target = WM8776in,
401 .type = VOLUME2
402 },
403 {
404 .name = "Capture Select",
405 .target = WM8776sel,
406 .type = ENUM,
407 .member = se200pci_sel
408 },
409 {
410 .name = "AGC Capture Mode",
411 .target = WM8776agc,
412 .type = ENUM,
413 .member = se200pci_agc
414 },
415 {
416 .name = "AFL Bypass Playback Switch",
417 .target = WM8776afl,
418 .type = BOOLEAN
419 }
420};
421
422static int se200pci_get_enum_count(int n)
423{
424 const char **member;
425 int c;
426
427 member = se200pci_cont[n].member;
428 if (!member)
429 return 0;
430 for (c = 0; member[c]; c++)
431 ;
432 return c;
433}
434
435static int se200pci_cont_volume_info(struct snd_kcontrol *kc,
436 struct snd_ctl_elem_info *uinfo)
437{
438 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
439 uinfo->count = 2;
440 uinfo->value.integer.min = 0;
441 uinfo->value.integer.max = 0xff;
442 return 0;
443}
444
445#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info
446
447static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
448 struct snd_ctl_elem_info *uinfo)
449{
450 int n, c;
451
452 n = kc->private_value;
453 c = se200pci_get_enum_count(n);
454 if (!c)
455 return -EINVAL;
456 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
457 uinfo->count = 1;
458 uinfo->value.enumerated.items = c;
459 if (uinfo->value.enumerated.item >= c)
460 uinfo->value.enumerated.item = c - 1;
461 strcpy(uinfo->value.enumerated.name,
462 se200pci_cont[n].member[uinfo->value.enumerated.item]);
463 return 0;
464}
465
466static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
467 struct snd_ctl_elem_value *uc)
468{
469 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
470 struct se_spec *spec = ice->spec;
471 int n = kc->private_value;
472 uc->value.integer.value[0] = spec->vol[n].ch1;
473 uc->value.integer.value[1] = spec->vol[n].ch2;
474 return 0;
475}
476
477static int se200pci_cont_boolean_get(struct snd_kcontrol *kc,
478 struct snd_ctl_elem_value *uc)
479{
480 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
481 struct se_spec *spec = ice->spec;
482 int n = kc->private_value;
483 uc->value.integer.value[0] = spec->vol[n].ch1;
484 return 0;
485}
486
487static int se200pci_cont_enum_get(struct snd_kcontrol *kc,
488 struct snd_ctl_elem_value *uc)
489{
490 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
491 struct se_spec *spec = ice->spec;
492 int n = kc->private_value;
493 uc->value.enumerated.item[0] = spec->vol[n].ch1;
494 return 0;
495}
496
497static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
498{
499 struct se_spec *spec = ice->spec;
500 switch (se200pci_cont[n].target) {
501 case WM8766:
502 se200pci_WM8766_set_volume(ice,
503 se200pci_cont[n].ch,
504 spec->vol[n].ch1,
505 spec->vol[n].ch2);
506 break;
507
508 case WM8776in:
509 se200pci_WM8776_set_input_volume(ice,
510 spec->vol[n].ch1,
511 spec->vol[n].ch2);
512 break;
513
514 case WM8776out:
515 se200pci_WM8776_set_output_volume(ice,
516 spec->vol[n].ch1,
517 spec->vol[n].ch2);
518 break;
519
520 case WM8776sel:
521 se200pci_WM8776_set_input_selector(ice,
522 spec->vol[n].ch1);
523 break;
524
525 case WM8776agc:
526 se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
527 break;
528
529 case WM8776afl:
530 se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
531 break;
532
533 default:
534 break;
535 }
536}
537
538static int se200pci_cont_volume_put(struct snd_kcontrol *kc,
539 struct snd_ctl_elem_value *uc)
540{
541 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
542 struct se_spec *spec = ice->spec;
543 int n = kc->private_value;
544 unsigned int vol1, vol2;
545 int changed;
546
547 changed = 0;
548 vol1 = uc->value.integer.value[0] & 0xff;
549 vol2 = uc->value.integer.value[1] & 0xff;
550 if (spec->vol[n].ch1 != vol1) {
551 spec->vol[n].ch1 = vol1;
552 changed = 1;
553 }
554 if (spec->vol[n].ch2 != vol2) {
555 spec->vol[n].ch2 = vol2;
556 changed = 1;
557 }
558 if (changed)
559 se200pci_cont_update(ice, n);
560
561 return changed;
562}
563
564static int se200pci_cont_boolean_put(struct snd_kcontrol *kc,
565 struct snd_ctl_elem_value *uc)
566{
567 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
568 struct se_spec *spec = ice->spec;
569 int n = kc->private_value;
570 unsigned int vol1;
571
572 vol1 = !!uc->value.integer.value[0];
573 if (spec->vol[n].ch1 != vol1) {
574 spec->vol[n].ch1 = vol1;
575 se200pci_cont_update(ice, n);
576 return 1;
577 }
578 return 0;
579}
580
581static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
582 struct snd_ctl_elem_value *uc)
583{
584 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
585 struct se_spec *spec = ice->spec;
586 int n = kc->private_value;
587 unsigned int vol1;
588
589 vol1 = uc->value.enumerated.item[0];
590 if (vol1 >= se200pci_get_enum_count(n))
591 return -EINVAL;
592 if (spec->vol[n].ch1 != vol1) {
593 spec->vol[n].ch1 = vol1;
594 se200pci_cont_update(ice, n);
595 return 1;
596 }
597 return 0;
598}
599
600static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
601static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
602
603static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
604{
605 int i;
606 struct snd_kcontrol_new cont;
607 int err;
608
609 memset(&cont, 0, sizeof(cont));
610 cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
611 for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
612 cont.private_value = i;
613 cont.name = se200pci_cont[i].name;
614 cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
615 cont.tlv.p = NULL;
616 switch (se200pci_cont[i].type) {
617 case VOLUME1:
618 case VOLUME2:
619 cont.info = se200pci_cont_volume_info;
620 cont.get = se200pci_cont_volume_get;
621 cont.put = se200pci_cont_volume_put;
622 cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
623 if (se200pci_cont[i].type == VOLUME1)
624 cont.tlv.p = db_scale_gain1;
625 else
626 cont.tlv.p = db_scale_gain2;
627 break;
628 case BOOLEAN:
629 cont.info = se200pci_cont_boolean_info;
630 cont.get = se200pci_cont_boolean_get;
631 cont.put = se200pci_cont_boolean_put;
632 break;
633 case ENUM:
634 cont.info = se200pci_cont_enum_info;
635 cont.get = se200pci_cont_enum_get;
636 cont.put = se200pci_cont_enum_put;
637 break;
638 default:
639 snd_BUG();
640 return -EINVAL;
641 }
642 err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
643 if (err < 0)
644 return err;
645 }
646
647 return 0;
648}
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681static int __devinit se_init(struct snd_ice1712 *ice)
682{
683 struct se_spec *spec;
684
685 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
686 if (!spec)
687 return -ENOMEM;
688 ice->spec = spec;
689
690 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
691 ice->num_total_dacs = 2;
692 ice->num_total_adcs = 0;
693 ice->vt1720 = 1;
694 return 0;
695
696 } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
697 ice->num_total_dacs = 8;
698 ice->num_total_adcs = 2;
699 se200pci_WM8740_init(ice);
700 se200pci_WM8766_init(ice);
701 se200pci_WM8776_init(ice);
702 ice->gpio.set_pro_rate = se200pci_set_pro_rate;
703 return 0;
704 }
705
706 return -ENOENT;
707}
708
709static int __devinit se_add_controls(struct snd_ice1712 *ice)
710{
711 int err;
712
713 err = 0;
714
715 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
716 err = se200pci_add_controls(ice);
717
718 return err;
719}
720
721
722
723
724
725
726static unsigned char se200pci_eeprom[] __devinitdata = {
727 [ICE_EEP2_SYSCONF] = 0x4b,
728 [ICE_EEP2_ACLINK] = 0x80,
729 [ICE_EEP2_I2S] = 0x78,
730 [ICE_EEP2_SPDIF] = 0xc3,
731
732 [ICE_EEP2_GPIO_DIR] = 0x02,
733 [ICE_EEP2_GPIO_DIR1] = 0x00,
734 [ICE_EEP2_GPIO_DIR2] = 0x07,
735
736 [ICE_EEP2_GPIO_MASK] = 0x00,
737 [ICE_EEP2_GPIO_MASK1] = 0x00,
738 [ICE_EEP2_GPIO_MASK2] = 0x00,
739
740 [ICE_EEP2_GPIO_STATE] = 0x00,
741 [ICE_EEP2_GPIO_STATE1] = 0x00,
742 [ICE_EEP2_GPIO_STATE2] = 0x07,
743};
744
745static unsigned char se90pci_eeprom[] __devinitdata = {
746 [ICE_EEP2_SYSCONF] = 0x4b,
747 [ICE_EEP2_ACLINK] = 0x80,
748 [ICE_EEP2_I2S] = 0x78,
749 [ICE_EEP2_SPDIF] = 0xc3,
750
751
752};
753
754struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
755 {
756 .subvendor = VT1724_SUBDEVICE_SE200PCI,
757 .name = "ONKYO SE200PCI",
758 .model = "se200pci",
759 .chip_init = se_init,
760 .build_controls = se_add_controls,
761 .eeprom_size = sizeof(se200pci_eeprom),
762 .eeprom_data = se200pci_eeprom,
763 },
764 {
765 .subvendor = VT1724_SUBDEVICE_SE90PCI,
766 .name = "ONKYO SE90PCI",
767 .model = "se90pci",
768 .chip_init = se_init,
769 .build_controls = se_add_controls,
770 .eeprom_size = sizeof(se90pci_eeprom),
771 .eeprom_data = se90pci_eeprom,
772 },
773 {}
774};
775