]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - sound/pci/ice1712/se.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / sound / pci / ice1712 / se.c
CommitLineData
1a59d1b8 1// SPDX-License-Identifier: GPL-2.0-or-later
f31639b8
SO
2/*
3 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 *
5 * Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI
6 *
7 * Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp
8 * (at) -> @
f31639b8
SO
9 */
10
f31639b8
SO
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
7cda8ba9
TI
22struct se_spec {
23 struct {
24 unsigned char ch1, ch2;
25 } vol[8];
26};
f31639b8
SO
27
28/****************************************************************************/
29/* ONKYO WAVIO SE-200PCI */
30/****************************************************************************/
31/*
32 * system configuration ICE_EEP2_SYSCONF=0x4b
33 * XIN1 49.152MHz
34 * not have UART
35 * one stereo ADC and a S/PDIF receiver connected
36 * four stereo DACs connected
37 *
38 * AC-Link configuration ICE_EEP2_ACLINK=0x80
39 * use I2C, not use AC97
40 *
41 * I2S converters feature ICE_EEP2_I2S=0x78
42 * I2S codec has no volume/mute control feature
43 * I2S codec supports 96KHz and 192KHz
44 * I2S codec 24bits
45 *
46 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
47 * Enable integrated S/PDIF transmitter
48 * internal S/PDIF out implemented
49 * S/PDIF is stereo
50 * External S/PDIF out implemented
51 *
52 *
53 * ** connected chips **
54 *
55 * WM8740
56 * A 2ch-DAC of main outputs.
57 * It setuped as I2S mode by wire, so no way to setup from software.
58 * The sample-rate are automatically changed.
59 * ML/I2S (28pin) --------+
60 * MC/DM1 (27pin) -- 5V |
61 * MD/DM0 (26pin) -- GND |
62 * MUTEB (25pin) -- NC |
63 * MODE (24pin) -- GND |
64 * CSBIW (23pin) --------+
65 * |
66 * RSTB (22pin) --R(1K)-+
67 * Probably it reduce the noise from the control line.
68 *
69 * WM8766
70 * A 6ch-DAC for surrounds.
71 * It's control wire was connected to GPIOxx (3-wire serial interface)
72 * ML/I2S (11pin) -- GPIO18
73 * MC/IWL (12pin) -- GPIO17
74 * MD/DM (13pin) -- GPIO16
75 * MUTE (14pin) -- GPIO01
76 *
77 * WM8776
78 * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
79 * It's control wire was connected to SDA/SCLK (2-wire serial interface)
80 * MODE (16pin) -- R(1K) -- GND
81 * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34)
82 * DI (18pin) -- SDA
83 * CL (19pin) -- SCLK
84 *
85 *
86 * ** output pins and device names **
87 *
88 * 7.1ch name -- output connector color -- device (-D option)
89 *
90 * FRONT 2ch -- green -- plughw:0,0
91 * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0
92 * SURROUND 2ch -- orange -- plughw:0,2,1
93 * SURROUND BACK 2ch -- white -- plughw:0,2,2
94 *
95 */
96
97
98/****************************************************************************/
99/* WM8740 interface */
100/****************************************************************************/
101
e23e7a14 102static void se200pci_WM8740_init(struct snd_ice1712 *ice)
f31639b8
SO
103{
104 /* nothing to do */
105}
106
107
108static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
109 unsigned int rate)
110{
111 /* nothing to do */
112}
113
114
115/****************************************************************************/
116/* WM8766 interface */
117/****************************************************************************/
118
119static 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
165static 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
e23e7a14 184static void se200pci_WM8766_init(struct snd_ice1712 *ice)
f31639b8
SO
185{
186 se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
187 udelay(10);
188
189 se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
190 se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
191 se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
192
193 se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
194 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
195 se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
196 se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
197 se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
198
199 se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
200 se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
201}
202
203static 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); /* MCLK=128fs */
208 else
209 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
210}
211
212
213/****************************************************************************/
214/* WM8776 interface */
215/****************************************************************************/
216
217static 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
227static 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
234static 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
a2af050f 241static const char * const se200pci_sel[] = {
f31639b8
SO
242 "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
243};
244
245static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
246 unsigned int sel)
247{
248 static unsigned char vals[] = {
249 /* LINE, CD, MIC, ALL, GND */
250 0x10, 0x04, 0x08, 0x1c, 0x03
251 };
252 if (sel > 4)
253 sel = 4;
254 se200pci_WM8776_write(ice, 0x15, vals[sel]);
255}
256
257static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
258{
259 /* AFL -- After Fader Listening */
260 if (afl)
261 se200pci_WM8776_write(ice, 0x16, 0x005);
262 else
263 se200pci_WM8776_write(ice, 0x16, 0x001);
264}
265
a2af050f 266static const char * const se200pci_agc[] = {
f31639b8
SO
267 "Off", "LimiterMode", "ALCMode", NULL
268};
269
270static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
271{
272 /* AGC -- Auto Gain Control of the input */
273 switch (agc) {
274 case 0:
275 se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
276 break;
277 case 1:
278 se200pci_WM8776_write(ice, 0x10, 0x07b);
279 se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
280 break;
281 case 2:
282 se200pci_WM8776_write(ice, 0x10, 0x1fb);
283 se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
284 break;
285 }
286}
287
e23e7a14 288static void se200pci_WM8776_init(struct snd_ice1712 *ice)
f31639b8
SO
289{
290 int i;
e23e7a14 291 static unsigned short default_values[] = {
f31639b8
SO
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); /* reset all */
301 /* ADC and DAC interface is I2S 24bits mode */
302 /* The sample-rate are automatically changed */
303 udelay(10);
304 /* BUT my board can not do reset all, so I load all by manually. */
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 /* head phone mute and power down */
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
321static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
322 unsigned int rate)
323{
324 /* nothing to do */
325}
326
327
328/****************************************************************************/
329/* runtime interface */
330/****************************************************************************/
331
332static 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
339struct se200pci_control {
a2af050f 340 const char *name;
f31639b8
SO
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;
a2af050f 351 const char * const *member;
f31639b8
SO
352 const char *comment;
353};
354
355static 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
9c45ba10 407static int se200pci_get_enum_count(int n)
f31639b8 408{
a2af050f 409 const char * const *member;
9c45ba10 410 int c;
f31639b8 411
9c45ba10
TI
412 member = se200pci_cont[n].member;
413 if (!member)
414 return 0;
415 for (c = 0; member[c]; c++)
416 ;
417 return c;
418}
f31639b8 419
9c45ba10
TI
420static 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; /* mute */
426 uinfo->value.integer.max = 0xff; /* 0dB */
f31639b8
SO
427 return 0;
428}
429
9c45ba10
TI
430#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info
431
432static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
433 struct snd_ctl_elem_info *uinfo)
f31639b8 434{
9c45ba10 435 int n, c;
f31639b8 436
f31639b8 437 n = kc->private_value;
9c45ba10
TI
438 c = se200pci_get_enum_count(n);
439 if (!c)
440 return -EINVAL;
597da2e4 441 return snd_ctl_enum_info(uinfo, 1, c, se200pci_cont[n].member);
f31639b8
SO
442}
443
9c45ba10
TI
444static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
445 struct snd_ctl_elem_value *uc)
f31639b8 446{
9c45ba10 447 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 448 struct se_spec *spec = ice->spec;
9c45ba10 449 int n = kc->private_value;
7cda8ba9
TI
450 uc->value.integer.value[0] = spec->vol[n].ch1;
451 uc->value.integer.value[1] = spec->vol[n].ch2;
9c45ba10
TI
452 return 0;
453}
f31639b8 454
9c45ba10
TI
455static 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);
7cda8ba9 459 struct se_spec *spec = ice->spec;
9c45ba10 460 int n = kc->private_value;
7cda8ba9 461 uc->value.integer.value[0] = spec->vol[n].ch1;
9c45ba10
TI
462 return 0;
463}
f31639b8 464
9c45ba10
TI
465static 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);
7cda8ba9 469 struct se_spec *spec = ice->spec;
9c45ba10 470 int n = kc->private_value;
7cda8ba9 471 uc->value.enumerated.item[0] = spec->vol[n].ch1;
9c45ba10
TI
472 return 0;
473}
f31639b8 474
9c45ba10
TI
475static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
476{
7cda8ba9 477 struct se_spec *spec = ice->spec;
f31639b8
SO
478 switch (se200pci_cont[n].target) {
479 case WM8766:
480 se200pci_WM8766_set_volume(ice,
9c45ba10 481 se200pci_cont[n].ch,
7cda8ba9
TI
482 spec->vol[n].ch1,
483 spec->vol[n].ch2);
f31639b8
SO
484 break;
485
486 case WM8776in:
9c45ba10 487 se200pci_WM8776_set_input_volume(ice,
7cda8ba9
TI
488 spec->vol[n].ch1,
489 spec->vol[n].ch2);
f31639b8
SO
490 break;
491
492 case WM8776out:
9c45ba10 493 se200pci_WM8776_set_output_volume(ice,
7cda8ba9
TI
494 spec->vol[n].ch1,
495 spec->vol[n].ch2);
f31639b8
SO
496 break;
497
498 case WM8776sel:
9c45ba10 499 se200pci_WM8776_set_input_selector(ice,
7cda8ba9 500 spec->vol[n].ch1);
f31639b8
SO
501 break;
502
503 case WM8776agc:
7cda8ba9 504 se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
f31639b8
SO
505 break;
506
507 case WM8776afl:
7cda8ba9 508 se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
f31639b8
SO
509 break;
510
511 default:
512 break;
513 }
9c45ba10
TI
514}
515
516static 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);
7cda8ba9 520 struct se_spec *spec = ice->spec;
9c45ba10
TI
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;
7cda8ba9
TI
528 if (spec->vol[n].ch1 != vol1) {
529 spec->vol[n].ch1 = vol1;
9c45ba10
TI
530 changed = 1;
531 }
7cda8ba9
TI
532 if (spec->vol[n].ch2 != vol2) {
533 spec->vol[n].ch2 = vol2;
9c45ba10
TI
534 changed = 1;
535 }
536 if (changed)
537 se200pci_cont_update(ice, n);
f31639b8
SO
538
539 return changed;
540}
541
9c45ba10
TI
542static 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);
7cda8ba9 546 struct se_spec *spec = ice->spec;
9c45ba10
TI
547 int n = kc->private_value;
548 unsigned int vol1;
549
550 vol1 = !!uc->value.integer.value[0];
7cda8ba9
TI
551 if (spec->vol[n].ch1 != vol1) {
552 spec->vol[n].ch1 = vol1;
9c45ba10
TI
553 se200pci_cont_update(ice, n);
554 return 1;
555 }
556 return 0;
557}
558
559static 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);
7cda8ba9 563 struct se_spec *spec = ice->spec;
9c45ba10
TI
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;
7cda8ba9
TI
570 if (spec->vol[n].ch1 != vol1) {
571 spec->vol[n].ch1 = vol1;
9c45ba10
TI
572 se200pci_cont_update(ice, n);
573 return 1;
574 }
575 return 0;
576}
577
f31639b8
SO
578static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
579static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
580
e23e7a14 581static int se200pci_add_controls(struct snd_ice1712 *ice)
f31639b8
SO
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;
f31639b8
SO
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;
9c45ba10
TI
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;
f31639b8 600 cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
f31639b8
SO
601 if (se200pci_cont[i].type == VOLUME1)
602 cont.tlv.p = db_scale_gain1;
603 else
604 cont.tlv.p = db_scale_gain2;
9c45ba10
TI
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;
f31639b8
SO
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/* ONKYO WAVIO SE-90PCI */
631/****************************************************************************/
632/*
633 * system configuration ICE_EEP2_SYSCONF=0x4b
634 * AC-Link configuration ICE_EEP2_ACLINK=0x80
635 * I2S converters feature ICE_EEP2_I2S=0x78
636 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
637 *
638 * ** connected chip **
639 *
640 * WM8716
641 * A 2ch-DAC of main outputs.
642 * It setuped as I2S mode by wire, so no way to setup from software.
643 * ML/I2S (28pin) -- +5V
644 * MC/DM1 (27pin) -- GND
645 * MC/DM0 (26pin) -- GND
646 * MUTEB (25pin) -- open (internal pull-up)
647 * MODE (24pin) -- GND
648 * CSBIWO (23pin) -- +5V
649 *
650 */
651
652 /* Nothing to do for this chip. */
653
654
655/****************************************************************************/
656/* probe/initialize/setup */
657/****************************************************************************/
658
e23e7a14 659static int se_init(struct snd_ice1712 *ice)
f31639b8 660{
7cda8ba9
TI
661 struct se_spec *spec;
662
663 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
664 if (!spec)
665 return -ENOMEM;
666 ice->spec = spec;
667
f31639b8
SO
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
e23e7a14 687static int se_add_controls(struct snd_ice1712 *ice)
f31639b8
SO
688{
689 int err;
690
691 err = 0;
692 /* nothing to do for VT1724_SUBDEVICE_SE90PCI */
693 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
694 err = se200pci_add_controls(ice);
695
696 return err;
697}
698
699
700/****************************************************************************/
701/* entry point */
702/****************************************************************************/
703
e23e7a14 704static unsigned char se200pci_eeprom[] = {
f31639b8
SO
705 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
706 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
707 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
708 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
709
710 [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */
711 [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */
712 [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */
713
714 [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */
715 [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */
716 [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */
717
718 [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */
719 [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */
720 [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */
721};
722
e23e7a14 723static unsigned char se90pci_eeprom[] = {
f31639b8
SO
724 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
725 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
726 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
727 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
728
729 /* ALL GPIO bits are in input mode */
730};
731
e23e7a14 732struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
f31639b8
SO
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 {} /*terminator*/
752};