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