drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / sound / pci / ice1712 / se.c
CommitLineData
f31639b8
SO
1/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI
5 *
6 * Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp
7 * (at) -> @
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
f31639b8
SO
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <sound/core.h>
30#include <sound/tlv.h>
31
32#include "ice1712.h"
33#include "envy24ht.h"
34#include "se.h"
35
7cda8ba9
TI
36struct se_spec {
37 struct {
38 unsigned char ch1, ch2;
39 } vol[8];
40};
f31639b8
SO
41
42/****************************************************************************/
43/* ONKYO WAVIO SE-200PCI */
44/****************************************************************************/
45/*
46 * system configuration ICE_EEP2_SYSCONF=0x4b
47 * XIN1 49.152MHz
48 * not have UART
49 * one stereo ADC and a S/PDIF receiver connected
50 * four stereo DACs connected
51 *
52 * AC-Link configuration ICE_EEP2_ACLINK=0x80
53 * use I2C, not use AC97
54 *
55 * I2S converters feature ICE_EEP2_I2S=0x78
56 * I2S codec has no volume/mute control feature
57 * I2S codec supports 96KHz and 192KHz
58 * I2S codec 24bits
59 *
60 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
61 * Enable integrated S/PDIF transmitter
62 * internal S/PDIF out implemented
63 * S/PDIF is stereo
64 * External S/PDIF out implemented
65 *
66 *
67 * ** connected chips **
68 *
69 * WM8740
70 * A 2ch-DAC of main outputs.
71 * It setuped as I2S mode by wire, so no way to setup from software.
72 * The sample-rate are automatically changed.
73 * ML/I2S (28pin) --------+
74 * MC/DM1 (27pin) -- 5V |
75 * MD/DM0 (26pin) -- GND |
76 * MUTEB (25pin) -- NC |
77 * MODE (24pin) -- GND |
78 * CSBIW (23pin) --------+
79 * |
80 * RSTB (22pin) --R(1K)-+
81 * Probably it reduce the noise from the control line.
82 *
83 * WM8766
84 * A 6ch-DAC for surrounds.
85 * It's control wire was connected to GPIOxx (3-wire serial interface)
86 * ML/I2S (11pin) -- GPIO18
87 * MC/IWL (12pin) -- GPIO17
88 * MD/DM (13pin) -- GPIO16
89 * MUTE (14pin) -- GPIO01
90 *
91 * WM8776
92 * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
93 * It's control wire was connected to SDA/SCLK (2-wire serial interface)
94 * MODE (16pin) -- R(1K) -- GND
95 * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34)
96 * DI (18pin) -- SDA
97 * CL (19pin) -- SCLK
98 *
99 *
100 * ** output pins and device names **
101 *
102 * 7.1ch name -- output connector color -- device (-D option)
103 *
104 * FRONT 2ch -- green -- plughw:0,0
105 * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0
106 * SURROUND 2ch -- orange -- plughw:0,2,1
107 * SURROUND BACK 2ch -- white -- plughw:0,2,2
108 *
109 */
110
111
112/****************************************************************************/
113/* WM8740 interface */
114/****************************************************************************/
115
e23e7a14 116static void se200pci_WM8740_init(struct snd_ice1712 *ice)
f31639b8
SO
117{
118 /* nothing to do */
119}
120
121
122static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
123 unsigned int rate)
124{
125 /* nothing to do */
126}
127
128
129/****************************************************************************/
130/* WM8766 interface */
131/****************************************************************************/
132
133static void se200pci_WM8766_write(struct snd_ice1712 *ice,
134 unsigned int addr, unsigned int data)
135{
136 unsigned int st;
137 unsigned int bits;
138 int i;
139 const unsigned int DATA = 0x010000;
140 const unsigned int CLOCK = 0x020000;
141 const unsigned int LOAD = 0x040000;
142 const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
143
144 snd_ice1712_save_gpio_status(ice);
145
146 st = ((addr & 0x7f) << 9) | (data & 0x1ff);
147 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
148 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
149 bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
150
151 snd_ice1712_gpio_write(ice, bits);
152 for (i = 0; i < 16; i++) {
153 udelay(1);
154 bits &= ~CLOCK;
155 st = (st << 1);
156 if (st & 0x10000)
157 bits |= DATA;
158 else
159 bits &= ~DATA;
160
161 snd_ice1712_gpio_write(ice, bits);
162
163 udelay(1);
164 bits |= CLOCK;
165 snd_ice1712_gpio_write(ice, bits);
166 }
167
168 udelay(1);
169 bits |= LOAD;
170 snd_ice1712_gpio_write(ice, bits);
171
172 udelay(1);
173 bits |= (DATA | CLOCK);
174 snd_ice1712_gpio_write(ice, bits);
175
176 snd_ice1712_restore_gpio_status(ice);
177}
178
179static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
180 unsigned int vol1, unsigned int vol2)
181{
182 switch (ch) {
183 case 0:
184 se200pci_WM8766_write(ice, 0x000, vol1);
185 se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
186 break;
187 case 1:
188 se200pci_WM8766_write(ice, 0x004, vol1);
189 se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
190 break;
191 case 2:
192 se200pci_WM8766_write(ice, 0x006, vol1);
193 se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
194 break;
195 }
196}
197
e23e7a14 198static void se200pci_WM8766_init(struct snd_ice1712 *ice)
f31639b8
SO
199{
200 se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
201 udelay(10);
202
203 se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
204 se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
205 se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
206
207 se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
208 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
209 se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
210 se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
211 se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
212
213 se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
214 se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
215}
216
217static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
218 unsigned int rate)
219{
220 if (rate > 96000)
221 se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */
222 else
223 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
224}
225
226
227/****************************************************************************/
228/* WM8776 interface */
229/****************************************************************************/
230
231static void se200pci_WM8776_write(struct snd_ice1712 *ice,
232 unsigned int addr, unsigned int data)
233{
234 unsigned int val;
235
236 val = (addr << 9) | data;
237 snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
238}
239
240
241static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
242 unsigned int vol1, unsigned int vol2)
243{
244 se200pci_WM8776_write(ice, 0x03, vol1);
245 se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
246}
247
248static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
249 unsigned int vol1, unsigned int vol2)
250{
251 se200pci_WM8776_write(ice, 0x0e, vol1);
252 se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
253}
254
a2af050f 255static const char * const se200pci_sel[] = {
f31639b8
SO
256 "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
257};
258
259static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
260 unsigned int sel)
261{
262 static unsigned char vals[] = {
263 /* LINE, CD, MIC, ALL, GND */
264 0x10, 0x04, 0x08, 0x1c, 0x03
265 };
266 if (sel > 4)
267 sel = 4;
268 se200pci_WM8776_write(ice, 0x15, vals[sel]);
269}
270
271static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
272{
273 /* AFL -- After Fader Listening */
274 if (afl)
275 se200pci_WM8776_write(ice, 0x16, 0x005);
276 else
277 se200pci_WM8776_write(ice, 0x16, 0x001);
278}
279
a2af050f 280static const char * const se200pci_agc[] = {
f31639b8
SO
281 "Off", "LimiterMode", "ALCMode", NULL
282};
283
284static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
285{
286 /* AGC -- Auto Gain Control of the input */
287 switch (agc) {
288 case 0:
289 se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
290 break;
291 case 1:
292 se200pci_WM8776_write(ice, 0x10, 0x07b);
293 se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
294 break;
295 case 2:
296 se200pci_WM8776_write(ice, 0x10, 0x1fb);
297 se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
298 break;
299 }
300}
301
e23e7a14 302static void se200pci_WM8776_init(struct snd_ice1712 *ice)
f31639b8
SO
303{
304 int i;
e23e7a14 305 static unsigned short default_values[] = {
f31639b8
SO
306 0x100, 0x100, 0x100,
307 0x100, 0x100, 0x100,
308 0x000, 0x090, 0x000, 0x000,
309 0x022, 0x022, 0x022,
310 0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
311 0x032, 0x000, 0x0a6, 0x001, 0x001
312 };
313
314 se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */
315 /* ADC and DAC interface is I2S 24bits mode */
316 /* The sample-rate are automatically changed */
317 udelay(10);
318 /* BUT my board can not do reset all, so I load all by manually. */
319 for (i = 0; i < ARRAY_SIZE(default_values); i++)
320 se200pci_WM8776_write(ice, i, default_values[i]);
321
322 se200pci_WM8776_set_input_selector(ice, 0);
323 se200pci_WM8776_set_afl(ice, 0);
324 se200pci_WM8776_set_agc(ice, 0);
325 se200pci_WM8776_set_input_volume(ice, 0, 0);
326 se200pci_WM8776_set_output_volume(ice, 0, 0);
327
328 /* head phone mute and power down */
329 se200pci_WM8776_write(ice, 0x00, 0);
330 se200pci_WM8776_write(ice, 0x01, 0);
331 se200pci_WM8776_write(ice, 0x02, 0x100);
332 se200pci_WM8776_write(ice, 0x0d, 0x080);
333}
334
335static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
336 unsigned int rate)
337{
338 /* nothing to do */
339}
340
341
342/****************************************************************************/
343/* runtime interface */
344/****************************************************************************/
345
346static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
347{
348 se200pci_WM8740_set_pro_rate(ice, rate);
349 se200pci_WM8766_set_pro_rate(ice, rate);
350 se200pci_WM8776_set_pro_rate(ice, rate);
351}
352
353struct se200pci_control {
a2af050f 354 const char *name;
f31639b8
SO
355 enum {
356 WM8766,
357 WM8776in,
358 WM8776out,
359 WM8776sel,
360 WM8776agc,
361 WM8776afl
362 } target;
363 enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
364 int ch;
a2af050f 365 const char * const *member;
f31639b8
SO
366 const char *comment;
367};
368
369static const struct se200pci_control se200pci_cont[] = {
370 {
371 .name = "Front Playback Volume",
372 .target = WM8776out,
373 .type = VOLUME1,
374 .comment = "Front(green)"
375 },
376 {
377 .name = "Side Playback Volume",
378 .target = WM8766,
379 .type = VOLUME1,
380 .ch = 1,
381 .comment = "Surround(orange)"
382 },
383 {
384 .name = "Surround Playback Volume",
385 .target = WM8766,
386 .type = VOLUME1,
387 .ch = 2,
388 .comment = "SurroundBack(white)"
389 },
390 {
391 .name = "CLFE Playback Volume",
392 .target = WM8766,
393 .type = VOLUME1,
394 .ch = 0,
395 .comment = "Center(Lch)&SubWoofer(Rch)(black)"
396 },
397 {
398 .name = "Capture Volume",
399 .target = WM8776in,
400 .type = VOLUME2
401 },
402 {
403 .name = "Capture Select",
404 .target = WM8776sel,
405 .type = ENUM,
406 .member = se200pci_sel
407 },
408 {
409 .name = "AGC Capture Mode",
410 .target = WM8776agc,
411 .type = ENUM,
412 .member = se200pci_agc
413 },
414 {
415 .name = "AFL Bypass Playback Switch",
416 .target = WM8776afl,
417 .type = BOOLEAN
418 }
419};
420
9c45ba10 421static int se200pci_get_enum_count(int n)
f31639b8 422{
a2af050f 423 const char * const *member;
9c45ba10 424 int c;
f31639b8 425
9c45ba10
TI
426 member = se200pci_cont[n].member;
427 if (!member)
428 return 0;
429 for (c = 0; member[c]; c++)
430 ;
431 return c;
432}
f31639b8 433
9c45ba10
TI
434static int se200pci_cont_volume_info(struct snd_kcontrol *kc,
435 struct snd_ctl_elem_info *uinfo)
436{
437 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
438 uinfo->count = 2;
439 uinfo->value.integer.min = 0; /* mute */
440 uinfo->value.integer.max = 0xff; /* 0dB */
f31639b8
SO
441 return 0;
442}
443
9c45ba10
TI
444#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info
445
446static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
447 struct snd_ctl_elem_info *uinfo)
f31639b8 448{
9c45ba10 449 int n, c;
f31639b8 450
f31639b8 451 n = kc->private_value;
9c45ba10
TI
452 c = se200pci_get_enum_count(n);
453 if (!c)
454 return -EINVAL;
455 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
456 uinfo->count = 1;
457 uinfo->value.enumerated.items = c;
458 if (uinfo->value.enumerated.item >= c)
459 uinfo->value.enumerated.item = c - 1;
460 strcpy(uinfo->value.enumerated.name,
461 se200pci_cont[n].member[uinfo->value.enumerated.item]);
f31639b8
SO
462 return 0;
463}
464
9c45ba10
TI
465static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
466 struct snd_ctl_elem_value *uc)
f31639b8 467{
9c45ba10 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
TI
471 uc->value.integer.value[0] = spec->vol[n].ch1;
472 uc->value.integer.value[1] = spec->vol[n].ch2;
9c45ba10
TI
473 return 0;
474}
f31639b8 475
9c45ba10
TI
476static int se200pci_cont_boolean_get(struct snd_kcontrol *kc,
477 struct snd_ctl_elem_value *uc)
478{
479 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 480 struct se_spec *spec = ice->spec;
9c45ba10 481 int n = kc->private_value;
7cda8ba9 482 uc->value.integer.value[0] = spec->vol[n].ch1;
9c45ba10
TI
483 return 0;
484}
f31639b8 485
9c45ba10
TI
486static int se200pci_cont_enum_get(struct snd_kcontrol *kc,
487 struct snd_ctl_elem_value *uc)
488{
489 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 490 struct se_spec *spec = ice->spec;
9c45ba10 491 int n = kc->private_value;
7cda8ba9 492 uc->value.enumerated.item[0] = spec->vol[n].ch1;
9c45ba10
TI
493 return 0;
494}
f31639b8 495
9c45ba10
TI
496static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
497{
7cda8ba9 498 struct se_spec *spec = ice->spec;
f31639b8
SO
499 switch (se200pci_cont[n].target) {
500 case WM8766:
501 se200pci_WM8766_set_volume(ice,
9c45ba10 502 se200pci_cont[n].ch,
7cda8ba9
TI
503 spec->vol[n].ch1,
504 spec->vol[n].ch2);
f31639b8
SO
505 break;
506
507 case WM8776in:
9c45ba10 508 se200pci_WM8776_set_input_volume(ice,
7cda8ba9
TI
509 spec->vol[n].ch1,
510 spec->vol[n].ch2);
f31639b8
SO
511 break;
512
513 case WM8776out:
9c45ba10 514 se200pci_WM8776_set_output_volume(ice,
7cda8ba9
TI
515 spec->vol[n].ch1,
516 spec->vol[n].ch2);
f31639b8
SO
517 break;
518
519 case WM8776sel:
9c45ba10 520 se200pci_WM8776_set_input_selector(ice,
7cda8ba9 521 spec->vol[n].ch1);
f31639b8
SO
522 break;
523
524 case WM8776agc:
7cda8ba9 525 se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
f31639b8
SO
526 break;
527
528 case WM8776afl:
7cda8ba9 529 se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
f31639b8
SO
530 break;
531
532 default:
533 break;
534 }
9c45ba10
TI
535}
536
537static int se200pci_cont_volume_put(struct snd_kcontrol *kc,
538 struct snd_ctl_elem_value *uc)
539{
540 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 541 struct se_spec *spec = ice->spec;
9c45ba10
TI
542 int n = kc->private_value;
543 unsigned int vol1, vol2;
544 int changed;
545
546 changed = 0;
547 vol1 = uc->value.integer.value[0] & 0xff;
548 vol2 = uc->value.integer.value[1] & 0xff;
7cda8ba9
TI
549 if (spec->vol[n].ch1 != vol1) {
550 spec->vol[n].ch1 = vol1;
9c45ba10
TI
551 changed = 1;
552 }
7cda8ba9
TI
553 if (spec->vol[n].ch2 != vol2) {
554 spec->vol[n].ch2 = vol2;
9c45ba10
TI
555 changed = 1;
556 }
557 if (changed)
558 se200pci_cont_update(ice, n);
f31639b8
SO
559
560 return changed;
561}
562
9c45ba10
TI
563static int se200pci_cont_boolean_put(struct snd_kcontrol *kc,
564 struct snd_ctl_elem_value *uc)
565{
566 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 567 struct se_spec *spec = ice->spec;
9c45ba10
TI
568 int n = kc->private_value;
569 unsigned int vol1;
570
571 vol1 = !!uc->value.integer.value[0];
7cda8ba9
TI
572 if (spec->vol[n].ch1 != vol1) {
573 spec->vol[n].ch1 = vol1;
9c45ba10
TI
574 se200pci_cont_update(ice, n);
575 return 1;
576 }
577 return 0;
578}
579
580static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
581 struct snd_ctl_elem_value *uc)
582{
583 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
7cda8ba9 584 struct se_spec *spec = ice->spec;
9c45ba10
TI
585 int n = kc->private_value;
586 unsigned int vol1;
587
588 vol1 = uc->value.enumerated.item[0];
589 if (vol1 >= se200pci_get_enum_count(n))
590 return -EINVAL;
7cda8ba9
TI
591 if (spec->vol[n].ch1 != vol1) {
592 spec->vol[n].ch1 = vol1;
9c45ba10
TI
593 se200pci_cont_update(ice, n);
594 return 1;
595 }
596 return 0;
597}
598
f31639b8
SO
599static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
600static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
601
e23e7a14 602static int se200pci_add_controls(struct snd_ice1712 *ice)
f31639b8
SO
603{
604 int i;
605 struct snd_kcontrol_new cont;
606 int err;
607
608 memset(&cont, 0, sizeof(cont));
609 cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
f31639b8
SO
610 for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
611 cont.private_value = i;
612 cont.name = se200pci_cont[i].name;
613 cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
614 cont.tlv.p = NULL;
9c45ba10
TI
615 switch (se200pci_cont[i].type) {
616 case VOLUME1:
617 case VOLUME2:
618 cont.info = se200pci_cont_volume_info;
619 cont.get = se200pci_cont_volume_get;
620 cont.put = se200pci_cont_volume_put;
f31639b8 621 cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
f31639b8
SO
622 if (se200pci_cont[i].type == VOLUME1)
623 cont.tlv.p = db_scale_gain1;
624 else
625 cont.tlv.p = db_scale_gain2;
9c45ba10
TI
626 break;
627 case BOOLEAN:
628 cont.info = se200pci_cont_boolean_info;
629 cont.get = se200pci_cont_boolean_get;
630 cont.put = se200pci_cont_boolean_put;
631 break;
632 case ENUM:
633 cont.info = se200pci_cont_enum_info;
634 cont.get = se200pci_cont_enum_get;
635 cont.put = se200pci_cont_enum_put;
636 break;
637 default:
638 snd_BUG();
639 return -EINVAL;
f31639b8
SO
640 }
641 err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
642 if (err < 0)
643 return err;
644 }
645
646 return 0;
647}
648
649
650/****************************************************************************/
651/* ONKYO WAVIO SE-90PCI */
652/****************************************************************************/
653/*
654 * system configuration ICE_EEP2_SYSCONF=0x4b
655 * AC-Link configuration ICE_EEP2_ACLINK=0x80
656 * I2S converters feature ICE_EEP2_I2S=0x78
657 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
658 *
659 * ** connected chip **
660 *
661 * WM8716
662 * A 2ch-DAC of main outputs.
663 * It setuped as I2S mode by wire, so no way to setup from software.
664 * ML/I2S (28pin) -- +5V
665 * MC/DM1 (27pin) -- GND
666 * MC/DM0 (26pin) -- GND
667 * MUTEB (25pin) -- open (internal pull-up)
668 * MODE (24pin) -- GND
669 * CSBIWO (23pin) -- +5V
670 *
671 */
672
673 /* Nothing to do for this chip. */
674
675
676/****************************************************************************/
677/* probe/initialize/setup */
678/****************************************************************************/
679
e23e7a14 680static int se_init(struct snd_ice1712 *ice)
f31639b8 681{
7cda8ba9
TI
682 struct se_spec *spec;
683
684 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
685 if (!spec)
686 return -ENOMEM;
687 ice->spec = spec;
688
f31639b8
SO
689 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
690 ice->num_total_dacs = 2;
691 ice->num_total_adcs = 0;
692 ice->vt1720 = 1;
693 return 0;
694
695 } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
696 ice->num_total_dacs = 8;
697 ice->num_total_adcs = 2;
698 se200pci_WM8740_init(ice);
699 se200pci_WM8766_init(ice);
700 se200pci_WM8776_init(ice);
701 ice->gpio.set_pro_rate = se200pci_set_pro_rate;
702 return 0;
703 }
704
705 return -ENOENT;
706}
707
e23e7a14 708static int se_add_controls(struct snd_ice1712 *ice)
f31639b8
SO
709{
710 int err;
711
712 err = 0;
713 /* nothing to do for VT1724_SUBDEVICE_SE90PCI */
714 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
715 err = se200pci_add_controls(ice);
716
717 return err;
718}
719
720
721/****************************************************************************/
722/* entry point */
723/****************************************************************************/
724
e23e7a14 725static unsigned char se200pci_eeprom[] = {
f31639b8
SO
726 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
727 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
728 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
729 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
730
731 [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */
732 [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */
733 [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */
734
735 [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */
736 [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */
737 [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */
738
739 [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */
740 [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */
741 [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */
742};
743
e23e7a14 744static unsigned char se90pci_eeprom[] = {
f31639b8
SO
745 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
746 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
747 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
748 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
749
750 /* ALL GPIO bits are in input mode */
751};
752
e23e7a14 753struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
f31639b8
SO
754 {
755 .subvendor = VT1724_SUBDEVICE_SE200PCI,
756 .name = "ONKYO SE200PCI",
757 .model = "se200pci",
758 .chip_init = se_init,
759 .build_controls = se_add_controls,
760 .eeprom_size = sizeof(se200pci_eeprom),
761 .eeprom_data = se200pci_eeprom,
762 },
763 {
764 .subvendor = VT1724_SUBDEVICE_SE90PCI,
765 .name = "ONKYO SE90PCI",
766 .model = "se90pci",
767 .chip_init = se_init,
768 .build_controls = se_add_controls,
769 .eeprom_size = sizeof(se90pci_eeprom),
770 .eeprom_data = se90pci_eeprom,
771 },
772 {} /*terminator*/
773};