xref: /linux/sound/pci/ice1712/se.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
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 
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 
37 struct se_spec {
38 	struct {
39 		unsigned char ch1, ch2;
40 	} vol[8];
41 };
42 
43 /****************************************************************************/
44 /*  ONKYO WAVIO SE-200PCI                                                   */
45 /****************************************************************************/
46 /*
47  *  system configuration ICE_EEP2_SYSCONF=0x4b
48  *    XIN1 49.152MHz
49  *    not have UART
50  *    one stereo ADC and a S/PDIF receiver connected
51  *    four stereo DACs connected
52  *
53  *  AC-Link configuration ICE_EEP2_ACLINK=0x80
54  *    use I2C, not use AC97
55  *
56  *  I2S converters feature ICE_EEP2_I2S=0x78
57  *    I2S codec has no volume/mute control feature
58  *    I2S codec supports 96KHz and 192KHz
59  *    I2S codec 24bits
60  *
61  *  S/PDIF configuration ICE_EEP2_SPDIF=0xc3
62  *    Enable integrated S/PDIF transmitter
63  *    internal S/PDIF out implemented
64  *    S/PDIF is stereo
65  *    External S/PDIF out implemented
66  *
67  *
68  * ** connected chips **
69  *
70  *  WM8740
71  *      A 2ch-DAC of main outputs.
72  *      It setuped as I2S mode by wire, so no way to setup from software.
73  *      The sample-rate are automatically changed.
74  *          ML/I2S (28pin) --------+
75  *          MC/DM1 (27pin) -- 5V   |
76  *          MD/DM0 (26pin) -- GND  |
77  *          MUTEB  (25pin) -- NC   |
78  *          MODE   (24pin) -- GND  |
79  *          CSBIW  (23pin) --------+
80  *                                 |
81  *          RSTB   (22pin) --R(1K)-+
82  *      Probably it reduce the noise from the control line.
83  *
84  *  WM8766
85  *      A 6ch-DAC for surrounds.
86  *      It's control wire was connected to GPIOxx (3-wire serial interface)
87  *          ML/I2S (11pin) -- GPIO18
88  *          MC/IWL (12pin) -- GPIO17
89  *          MD/DM  (13pin) -- GPIO16
90  *          MUTE   (14pin) -- GPIO01
91  *
92  *  WM8776
93  *     A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
94  *     It's control wire was connected to SDA/SCLK (2-wire serial interface)
95  *          MODE (16pin) -- R(1K) -- GND
96  *          CE   (17pin) -- R(1K) -- GND  2-wire mode (address=0x34)
97  *          DI   (18pin) -- SDA
98  *          CL   (19pin) -- SCLK
99  *
100  *
101  * ** output pins and device names **
102  *
103  *   7.1ch name -- output connector color -- device (-D option)
104  *
105  *      FRONT 2ch                  -- green  -- plughw:0,0
106  *      CENTER(Lch) SUBWOOFER(Rch) -- black  -- plughw:0,2,0
107  *      SURROUND 2ch               -- orange -- plughw:0,2,1
108  *      SURROUND BACK 2ch          -- white  -- plughw:0,2,2
109  *
110  */
111 
112 
113 /****************************************************************************/
114 /*  WM8740 interface                                                        */
115 /****************************************************************************/
116 
117 static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
118 {
119 	/* nothing to do */
120 }
121 
122 
123 static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
124 						unsigned int rate)
125 {
126 	/* nothing to do */
127 }
128 
129 
130 /****************************************************************************/
131 /*  WM8766 interface                                                        */
132 /****************************************************************************/
133 
134 static 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 
180 static 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 
199 static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
200 {
201 	se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
202 	udelay(10);
203 
204 	se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
205 	se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
206 	se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
207 
208 	se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
209 	se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
210 	se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
211 	se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
212 	se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
213 
214 	se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
215 	se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
216 }
217 
218 static 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); /* MCLK=128fs */
223 	else
224 		se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
225 }
226 
227 
228 /****************************************************************************/
229 /*  WM8776 interface                                                        */
230 /****************************************************************************/
231 
232 static 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 
242 static 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 
249 static 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 
256 static const char *se200pci_sel[] = {
257 	"LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
258 };
259 
260 static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
261 					       unsigned int sel)
262 {
263 	static unsigned char vals[] = {
264 		/* LINE, CD, MIC, ALL, GND */
265 		0x10, 0x04, 0x08, 0x1c, 0x03
266 	};
267 	if (sel > 4)
268 		sel = 4;
269 	se200pci_WM8776_write(ice, 0x15, vals[sel]);
270 }
271 
272 static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
273 {
274 	/* AFL -- After Fader Listening */
275 	if (afl)
276 		se200pci_WM8776_write(ice, 0x16, 0x005);
277 	else
278 		se200pci_WM8776_write(ice, 0x16, 0x001);
279 }
280 
281 static const char *se200pci_agc[] = {
282 	"Off", "LimiterMode", "ALCMode", NULL
283 };
284 
285 static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
286 {
287 	/* AGC -- Auto Gain Control of the input */
288 	switch (agc) {
289 	case 0:
290 		se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
291 		break;
292 	case 1:
293 		se200pci_WM8776_write(ice, 0x10, 0x07b);
294 		se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
295 		break;
296 	case 2:
297 		se200pci_WM8776_write(ice, 0x10, 0x1fb);
298 		se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
299 		break;
300 	}
301 }
302 
303 static 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); /* reset all */
316 	/* ADC and DAC interface is I2S 24bits mode */
317  	/* The sample-rate are automatically changed */
318 	udelay(10);
319 	/* BUT my board can not do reset all, so I load all by manually. */
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 	/* head phone mute and power down */
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 
336 static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
337 						unsigned int rate)
338 {
339 	/* nothing to do */
340 }
341 
342 
343 /****************************************************************************/
344 /*  runtime interface                                                       */
345 /****************************************************************************/
346 
347 static 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 
354 struct 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 
370 static 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 
422 static 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 
435 static 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; /* mute */
441 	uinfo->value.integer.max = 0xff; /* 0dB */
442 	return 0;
443 }
444 
445 #define se200pci_cont_boolean_info	snd_ctl_boolean_mono_info
446 
447 static 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 
466 static 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 
477 static 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 
487 static 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 
497 static 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 
538 static 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 
564 static 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 
581 static 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 
600 static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
601 static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
602 
603 static 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 /*  ONKYO WAVIO SE-90PCI                                                    */
653 /****************************************************************************/
654 /*
655  *  system configuration ICE_EEP2_SYSCONF=0x4b
656  *  AC-Link configuration ICE_EEP2_ACLINK=0x80
657  *  I2S converters feature ICE_EEP2_I2S=0x78
658  *  S/PDIF configuration ICE_EEP2_SPDIF=0xc3
659  *
660  *  ** connected chip **
661  *
662  *   WM8716
663  *      A 2ch-DAC of main outputs.
664  *      It setuped as I2S mode by wire, so no way to setup from software.
665  *         ML/I2S (28pin) -- +5V
666  *         MC/DM1 (27pin) -- GND
667  *         MC/DM0 (26pin) -- GND
668  *         MUTEB  (25pin) -- open (internal pull-up)
669  *         MODE   (24pin) -- GND
670  *         CSBIWO (23pin) -- +5V
671  *
672  */
673 
674  /* Nothing to do for this chip. */
675 
676 
677 /****************************************************************************/
678 /*  probe/initialize/setup                                                  */
679 /****************************************************************************/
680 
681 static 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 
709 static int __devinit se_add_controls(struct snd_ice1712 *ice)
710 {
711 	int err;
712 
713 	err = 0;
714 	/* nothing to do for VT1724_SUBDEVICE_SE90PCI */
715 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
716 		err = se200pci_add_controls(ice);
717 
718 	return err;
719 }
720 
721 
722 /****************************************************************************/
723 /*  entry point                                                             */
724 /****************************************************************************/
725 
726 static unsigned char se200pci_eeprom[] __devinitdata = {
727 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
728 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
729 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
730 	[ICE_EEP2_SPDIF]	= 0xc3,	/* out-en, out-int, spdif-in */
731 
732 	[ICE_EEP2_GPIO_DIR]	= 0x02, /* WM8766 mute      1=output */
733 	[ICE_EEP2_GPIO_DIR1]	= 0x00, /* not used */
734 	[ICE_EEP2_GPIO_DIR2]	= 0x07, /* WM8766 ML/MC/MD  1=output */
735 
736 	[ICE_EEP2_GPIO_MASK]	= 0x00, /* 0=writable */
737 	[ICE_EEP2_GPIO_MASK1]	= 0x00, /* 0=writable */
738 	[ICE_EEP2_GPIO_MASK2]	= 0x00, /* 0=writable */
739 
740 	[ICE_EEP2_GPIO_STATE]	= 0x00, /* WM8766 mute=0 */
741 	[ICE_EEP2_GPIO_STATE1]	= 0x00, /* not used */
742 	[ICE_EEP2_GPIO_STATE2]	= 0x07, /* WM8766 ML/MC/MD */
743 };
744 
745 static unsigned char se90pci_eeprom[] __devinitdata = {
746 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
747 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
748 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
749 	[ICE_EEP2_SPDIF]	= 0xc3,	/* out-en, out-int, spdif-in */
750 
751 	/* ALL GPIO bits are in input mode */
752 };
753 
754 struct 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 	{} /*terminator*/
774 };
775