xref: /linux/sound/pci/ice1712/se.c (revision f16a4e96)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f31639b8SShin-ya Okada /*
3f31639b8SShin-ya Okada  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
4f31639b8SShin-ya Okada  *
5f31639b8SShin-ya Okada  *   Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI
6f31639b8SShin-ya Okada  *
7f31639b8SShin-ya Okada  *	Copyright (c) 2007 Shin-ya Okada  sh_okada(at)d4.dion.ne.jp
8f31639b8SShin-ya Okada  *                                        (at) -> @
9f31639b8SShin-ya Okada  */
10f31639b8SShin-ya Okada 
11f31639b8SShin-ya Okada #include <linux/delay.h>
12f31639b8SShin-ya Okada #include <linux/interrupt.h>
13f31639b8SShin-ya Okada #include <linux/init.h>
14f31639b8SShin-ya Okada #include <linux/slab.h>
15f31639b8SShin-ya Okada #include <sound/core.h>
16f31639b8SShin-ya Okada #include <sound/tlv.h>
17f31639b8SShin-ya Okada 
18f31639b8SShin-ya Okada #include "ice1712.h"
19f31639b8SShin-ya Okada #include "envy24ht.h"
20f31639b8SShin-ya Okada #include "se.h"
21f31639b8SShin-ya Okada 
227cda8ba9STakashi Iwai struct se_spec {
237cda8ba9STakashi Iwai 	struct {
247cda8ba9STakashi Iwai 		unsigned char ch1, ch2;
257cda8ba9STakashi Iwai 	} vol[8];
267cda8ba9STakashi Iwai };
27f31639b8SShin-ya Okada 
28f31639b8SShin-ya Okada /****************************************************************************/
29f31639b8SShin-ya Okada /*  ONKYO WAVIO SE-200PCI                                                   */
30f31639b8SShin-ya Okada /****************************************************************************/
31f31639b8SShin-ya Okada /*
32f31639b8SShin-ya Okada  *  system configuration ICE_EEP2_SYSCONF=0x4b
33f31639b8SShin-ya Okada  *    XIN1 49.152MHz
34f31639b8SShin-ya Okada  *    not have UART
35f31639b8SShin-ya Okada  *    one stereo ADC and a S/PDIF receiver connected
36f31639b8SShin-ya Okada  *    four stereo DACs connected
37f31639b8SShin-ya Okada  *
38f31639b8SShin-ya Okada  *  AC-Link configuration ICE_EEP2_ACLINK=0x80
39f31639b8SShin-ya Okada  *    use I2C, not use AC97
40f31639b8SShin-ya Okada  *
41f31639b8SShin-ya Okada  *  I2S converters feature ICE_EEP2_I2S=0x78
42f31639b8SShin-ya Okada  *    I2S codec has no volume/mute control feature
43f31639b8SShin-ya Okada  *    I2S codec supports 96KHz and 192KHz
44f31639b8SShin-ya Okada  *    I2S codec 24bits
45f31639b8SShin-ya Okada  *
46f31639b8SShin-ya Okada  *  S/PDIF configuration ICE_EEP2_SPDIF=0xc3
47f31639b8SShin-ya Okada  *    Enable integrated S/PDIF transmitter
48f31639b8SShin-ya Okada  *    internal S/PDIF out implemented
49f31639b8SShin-ya Okada  *    S/PDIF is stereo
50f31639b8SShin-ya Okada  *    External S/PDIF out implemented
51f31639b8SShin-ya Okada  *
52f31639b8SShin-ya Okada  *
53f31639b8SShin-ya Okada  * ** connected chips **
54f31639b8SShin-ya Okada  *
55f31639b8SShin-ya Okada  *  WM8740
56f31639b8SShin-ya Okada  *      A 2ch-DAC of main outputs.
57f31639b8SShin-ya Okada  *      It setuped as I2S mode by wire, so no way to setup from software.
58f31639b8SShin-ya Okada  *      The sample-rate are automatically changed.
59f31639b8SShin-ya Okada  *          ML/I2S (28pin) --------+
60f31639b8SShin-ya Okada  *          MC/DM1 (27pin) -- 5V   |
61f31639b8SShin-ya Okada  *          MD/DM0 (26pin) -- GND  |
62f31639b8SShin-ya Okada  *          MUTEB  (25pin) -- NC   |
63f31639b8SShin-ya Okada  *          MODE   (24pin) -- GND  |
64f31639b8SShin-ya Okada  *          CSBIW  (23pin) --------+
65f31639b8SShin-ya Okada  *                                 |
66f31639b8SShin-ya Okada  *          RSTB   (22pin) --R(1K)-+
67f31639b8SShin-ya Okada  *      Probably it reduce the noise from the control line.
68f31639b8SShin-ya Okada  *
69f31639b8SShin-ya Okada  *  WM8766
70f31639b8SShin-ya Okada  *      A 6ch-DAC for surrounds.
71f31639b8SShin-ya Okada  *      It's control wire was connected to GPIOxx (3-wire serial interface)
72f31639b8SShin-ya Okada  *          ML/I2S (11pin) -- GPIO18
73f31639b8SShin-ya Okada  *          MC/IWL (12pin) -- GPIO17
74f31639b8SShin-ya Okada  *          MD/DM  (13pin) -- GPIO16
75f31639b8SShin-ya Okada  *          MUTE   (14pin) -- GPIO01
76f31639b8SShin-ya Okada  *
77f31639b8SShin-ya Okada  *  WM8776
78f31639b8SShin-ya Okada  *     A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
79f31639b8SShin-ya Okada  *     It's control wire was connected to SDA/SCLK (2-wire serial interface)
80f31639b8SShin-ya Okada  *          MODE (16pin) -- R(1K) -- GND
81f31639b8SShin-ya Okada  *          CE   (17pin) -- R(1K) -- GND  2-wire mode (address=0x34)
82f31639b8SShin-ya Okada  *          DI   (18pin) -- SDA
83f31639b8SShin-ya Okada  *          CL   (19pin) -- SCLK
84f31639b8SShin-ya Okada  *
85f31639b8SShin-ya Okada  *
86f31639b8SShin-ya Okada  * ** output pins and device names **
87f31639b8SShin-ya Okada  *
88f31639b8SShin-ya Okada  *   7.1ch name -- output connector color -- device (-D option)
89f31639b8SShin-ya Okada  *
90f31639b8SShin-ya Okada  *      FRONT 2ch                  -- green  -- plughw:0,0
91f31639b8SShin-ya Okada  *      CENTER(Lch) SUBWOOFER(Rch) -- black  -- plughw:0,2,0
92f31639b8SShin-ya Okada  *      SURROUND 2ch               -- orange -- plughw:0,2,1
93f31639b8SShin-ya Okada  *      SURROUND BACK 2ch          -- white  -- plughw:0,2,2
94f31639b8SShin-ya Okada  *
95f31639b8SShin-ya Okada  */
96f31639b8SShin-ya Okada 
97f31639b8SShin-ya Okada 
98f31639b8SShin-ya Okada /****************************************************************************/
99f31639b8SShin-ya Okada /*  WM8740 interface                                                        */
100f31639b8SShin-ya Okada /****************************************************************************/
101f31639b8SShin-ya Okada 
se200pci_WM8740_init(struct snd_ice1712 * ice)102e23e7a14SBill Pemberton static void se200pci_WM8740_init(struct snd_ice1712 *ice)
103f31639b8SShin-ya Okada {
104f31639b8SShin-ya Okada 	/* nothing to do */
105f31639b8SShin-ya Okada }
106f31639b8SShin-ya Okada 
107f31639b8SShin-ya Okada 
se200pci_WM8740_set_pro_rate(struct snd_ice1712 * ice,unsigned int rate)108f31639b8SShin-ya Okada static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
109f31639b8SShin-ya Okada 						unsigned int rate)
110f31639b8SShin-ya Okada {
111f31639b8SShin-ya Okada 	/* nothing to do */
112f31639b8SShin-ya Okada }
113f31639b8SShin-ya Okada 
114f31639b8SShin-ya Okada 
115f31639b8SShin-ya Okada /****************************************************************************/
116f31639b8SShin-ya Okada /*  WM8766 interface                                                        */
117f31639b8SShin-ya Okada /****************************************************************************/
118f31639b8SShin-ya Okada 
se200pci_WM8766_write(struct snd_ice1712 * ice,unsigned int addr,unsigned int data)119f31639b8SShin-ya Okada static void se200pci_WM8766_write(struct snd_ice1712 *ice,
120f31639b8SShin-ya Okada 					unsigned int addr, unsigned int data)
121f31639b8SShin-ya Okada {
122f31639b8SShin-ya Okada 	unsigned int st;
123f31639b8SShin-ya Okada 	unsigned int bits;
124f31639b8SShin-ya Okada 	int i;
125f31639b8SShin-ya Okada 	const unsigned int DATA  = 0x010000;
126f31639b8SShin-ya Okada 	const unsigned int CLOCK = 0x020000;
127f31639b8SShin-ya Okada 	const unsigned int LOAD  = 0x040000;
128f31639b8SShin-ya Okada 	const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
129f31639b8SShin-ya Okada 
130f31639b8SShin-ya Okada 	snd_ice1712_save_gpio_status(ice);
131f31639b8SShin-ya Okada 
132f31639b8SShin-ya Okada 	st = ((addr & 0x7f) << 9) | (data & 0x1ff);
133f31639b8SShin-ya Okada 	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
134f31639b8SShin-ya Okada 	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
135f31639b8SShin-ya Okada 	bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
136f31639b8SShin-ya Okada 
137f31639b8SShin-ya Okada 	snd_ice1712_gpio_write(ice, bits);
138f31639b8SShin-ya Okada 	for (i = 0; i < 16; i++) {
139f31639b8SShin-ya Okada 		udelay(1);
140f31639b8SShin-ya Okada 		bits &= ~CLOCK;
141f31639b8SShin-ya Okada 		st = (st << 1);
142f31639b8SShin-ya Okada 		if (st & 0x10000)
143f31639b8SShin-ya Okada 			bits |= DATA;
144f31639b8SShin-ya Okada 		else
145f31639b8SShin-ya Okada 			bits &= ~DATA;
146f31639b8SShin-ya Okada 
147f31639b8SShin-ya Okada 		snd_ice1712_gpio_write(ice, bits);
148f31639b8SShin-ya Okada 
149f31639b8SShin-ya Okada 		udelay(1);
150f31639b8SShin-ya Okada 		bits |= CLOCK;
151f31639b8SShin-ya Okada 		snd_ice1712_gpio_write(ice, bits);
152f31639b8SShin-ya Okada 	}
153f31639b8SShin-ya Okada 
154f31639b8SShin-ya Okada 	udelay(1);
155f31639b8SShin-ya Okada 	bits |= LOAD;
156f31639b8SShin-ya Okada 	snd_ice1712_gpio_write(ice, bits);
157f31639b8SShin-ya Okada 
158f31639b8SShin-ya Okada 	udelay(1);
159f31639b8SShin-ya Okada 	bits |= (DATA | CLOCK);
160f31639b8SShin-ya Okada 	snd_ice1712_gpio_write(ice, bits);
161f31639b8SShin-ya Okada 
162f31639b8SShin-ya Okada 	snd_ice1712_restore_gpio_status(ice);
163f31639b8SShin-ya Okada }
164f31639b8SShin-ya Okada 
se200pci_WM8766_set_volume(struct snd_ice1712 * ice,int ch,unsigned int vol1,unsigned int vol2)165f31639b8SShin-ya Okada static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
166f31639b8SShin-ya Okada 					unsigned int vol1, unsigned int vol2)
167f31639b8SShin-ya Okada {
168f31639b8SShin-ya Okada 	switch (ch) {
169f31639b8SShin-ya Okada 	case 0:
170f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x000, vol1);
171f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
172f31639b8SShin-ya Okada 		break;
173f31639b8SShin-ya Okada 	case 1:
174f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x004, vol1);
175f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
176f31639b8SShin-ya Okada 		break;
177f31639b8SShin-ya Okada 	case 2:
178f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x006, vol1);
179f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
180f31639b8SShin-ya Okada 		break;
181f31639b8SShin-ya Okada 	}
182f31639b8SShin-ya Okada }
183f31639b8SShin-ya Okada 
se200pci_WM8766_init(struct snd_ice1712 * ice)184e23e7a14SBill Pemberton static void se200pci_WM8766_init(struct snd_ice1712 *ice)
185f31639b8SShin-ya Okada {
186f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
187f31639b8SShin-ya Okada 	udelay(10);
188f31639b8SShin-ya Okada 
189f31639b8SShin-ya Okada 	se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
190f31639b8SShin-ya Okada 	se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
191f31639b8SShin-ya Okada 	se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
192f31639b8SShin-ya Okada 
193f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
194f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
195f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
196f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
197f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
198f31639b8SShin-ya Okada 
199f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
200f31639b8SShin-ya Okada 	se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
201f31639b8SShin-ya Okada }
202f31639b8SShin-ya Okada 
se200pci_WM8766_set_pro_rate(struct snd_ice1712 * ice,unsigned int rate)203f31639b8SShin-ya Okada static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
204f31639b8SShin-ya Okada 					unsigned int rate)
205f31639b8SShin-ya Okada {
206f31639b8SShin-ya Okada 	if (rate > 96000)
207f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */
208f31639b8SShin-ya Okada 	else
209f31639b8SShin-ya Okada 		se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
210f31639b8SShin-ya Okada }
211f31639b8SShin-ya Okada 
212f31639b8SShin-ya Okada 
213f31639b8SShin-ya Okada /****************************************************************************/
214f31639b8SShin-ya Okada /*  WM8776 interface                                                        */
215f31639b8SShin-ya Okada /****************************************************************************/
216f31639b8SShin-ya Okada 
se200pci_WM8776_write(struct snd_ice1712 * ice,unsigned int addr,unsigned int data)217f31639b8SShin-ya Okada static void se200pci_WM8776_write(struct snd_ice1712 *ice,
218f31639b8SShin-ya Okada 					unsigned int addr, unsigned int data)
219f31639b8SShin-ya Okada {
220f31639b8SShin-ya Okada 	unsigned int val;
221f31639b8SShin-ya Okada 
222f31639b8SShin-ya Okada 	val = (addr << 9) | data;
223f31639b8SShin-ya Okada 	snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
224f31639b8SShin-ya Okada }
225f31639b8SShin-ya Okada 
226f31639b8SShin-ya Okada 
se200pci_WM8776_set_output_volume(struct snd_ice1712 * ice,unsigned int vol1,unsigned int vol2)227f31639b8SShin-ya Okada static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
228f31639b8SShin-ya Okada 					unsigned int vol1, unsigned int vol2)
229f31639b8SShin-ya Okada {
230f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x03, vol1);
231f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
232f31639b8SShin-ya Okada }
233f31639b8SShin-ya Okada 
se200pci_WM8776_set_input_volume(struct snd_ice1712 * ice,unsigned int vol1,unsigned int vol2)234f31639b8SShin-ya Okada static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
235f31639b8SShin-ya Okada 					unsigned int vol1, unsigned int vol2)
236f31639b8SShin-ya Okada {
237f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x0e, vol1);
238f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
239f31639b8SShin-ya Okada }
240f31639b8SShin-ya Okada 
241a2af050fSTakashi Iwai static const char * const se200pci_sel[] = {
242f31639b8SShin-ya Okada 	"LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
243f31639b8SShin-ya Okada };
244f31639b8SShin-ya Okada 
se200pci_WM8776_set_input_selector(struct snd_ice1712 * ice,unsigned int sel)245f31639b8SShin-ya Okada static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
246f31639b8SShin-ya Okada 					       unsigned int sel)
247f31639b8SShin-ya Okada {
248*f16a4e96STakashi Iwai 	static const unsigned char vals[] = {
249f31639b8SShin-ya Okada 		/* LINE, CD, MIC, ALL, GND */
250f31639b8SShin-ya Okada 		0x10, 0x04, 0x08, 0x1c, 0x03
251f31639b8SShin-ya Okada 	};
252f31639b8SShin-ya Okada 	if (sel > 4)
253f31639b8SShin-ya Okada 		sel = 4;
254f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x15, vals[sel]);
255f31639b8SShin-ya Okada }
256f31639b8SShin-ya Okada 
se200pci_WM8776_set_afl(struct snd_ice1712 * ice,unsigned int afl)257f31639b8SShin-ya Okada static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
258f31639b8SShin-ya Okada {
259f31639b8SShin-ya Okada 	/* AFL -- After Fader Listening */
260f31639b8SShin-ya Okada 	if (afl)
261f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x16, 0x005);
262f31639b8SShin-ya Okada 	else
263f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x16, 0x001);
264f31639b8SShin-ya Okada }
265f31639b8SShin-ya Okada 
266a2af050fSTakashi Iwai static const char * const se200pci_agc[] = {
267f31639b8SShin-ya Okada 	"Off", "LimiterMode", "ALCMode", NULL
268f31639b8SShin-ya Okada };
269f31639b8SShin-ya Okada 
se200pci_WM8776_set_agc(struct snd_ice1712 * ice,unsigned int agc)270f31639b8SShin-ya Okada static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
271f31639b8SShin-ya Okada {
272f31639b8SShin-ya Okada 	/* AGC -- Auto Gain Control of the input */
273f31639b8SShin-ya Okada 	switch (agc) {
274f31639b8SShin-ya Okada 	case 0:
275f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
276f31639b8SShin-ya Okada 		break;
277f31639b8SShin-ya Okada 	case 1:
278f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x10, 0x07b);
279f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
280f31639b8SShin-ya Okada 		break;
281f31639b8SShin-ya Okada 	case 2:
282f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x10, 0x1fb);
283f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
284f31639b8SShin-ya Okada 		break;
285f31639b8SShin-ya Okada 	}
286f31639b8SShin-ya Okada }
287f31639b8SShin-ya Okada 
se200pci_WM8776_init(struct snd_ice1712 * ice)288e23e7a14SBill Pemberton static void se200pci_WM8776_init(struct snd_ice1712 *ice)
289f31639b8SShin-ya Okada {
290f31639b8SShin-ya Okada 	int i;
291*f16a4e96STakashi Iwai 	static const unsigned short default_values[] = {
292f31639b8SShin-ya Okada 		0x100, 0x100, 0x100,
293f31639b8SShin-ya Okada 		0x100, 0x100, 0x100,
294f31639b8SShin-ya Okada 		0x000, 0x090, 0x000, 0x000,
295f31639b8SShin-ya Okada 		0x022, 0x022, 0x022,
296f31639b8SShin-ya Okada 		0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
297f31639b8SShin-ya Okada 		0x032, 0x000, 0x0a6, 0x001, 0x001
298f31639b8SShin-ya Okada 	};
299f31639b8SShin-ya Okada 
300f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */
301f31639b8SShin-ya Okada 	/* ADC and DAC interface is I2S 24bits mode */
302f31639b8SShin-ya Okada  	/* The sample-rate are automatically changed */
303f31639b8SShin-ya Okada 	udelay(10);
304f31639b8SShin-ya Okada 	/* BUT my board can not do reset all, so I load all by manually. */
305f31639b8SShin-ya Okada 	for (i = 0; i < ARRAY_SIZE(default_values); i++)
306f31639b8SShin-ya Okada 		se200pci_WM8776_write(ice, i, default_values[i]);
307f31639b8SShin-ya Okada 
308f31639b8SShin-ya Okada 	se200pci_WM8776_set_input_selector(ice, 0);
309f31639b8SShin-ya Okada 	se200pci_WM8776_set_afl(ice, 0);
310f31639b8SShin-ya Okada 	se200pci_WM8776_set_agc(ice, 0);
311f31639b8SShin-ya Okada 	se200pci_WM8776_set_input_volume(ice, 0, 0);
312f31639b8SShin-ya Okada 	se200pci_WM8776_set_output_volume(ice, 0, 0);
313f31639b8SShin-ya Okada 
314f31639b8SShin-ya Okada 	/* head phone mute and power down */
315f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x00, 0);
316f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x01, 0);
317f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x02, 0x100);
318f31639b8SShin-ya Okada 	se200pci_WM8776_write(ice, 0x0d, 0x080);
319f31639b8SShin-ya Okada }
320f31639b8SShin-ya Okada 
se200pci_WM8776_set_pro_rate(struct snd_ice1712 * ice,unsigned int rate)321f31639b8SShin-ya Okada static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
322f31639b8SShin-ya Okada 						unsigned int rate)
323f31639b8SShin-ya Okada {
324f31639b8SShin-ya Okada 	/* nothing to do */
325f31639b8SShin-ya Okada }
326f31639b8SShin-ya Okada 
327f31639b8SShin-ya Okada 
328f31639b8SShin-ya Okada /****************************************************************************/
329f31639b8SShin-ya Okada /*  runtime interface                                                       */
330f31639b8SShin-ya Okada /****************************************************************************/
331f31639b8SShin-ya Okada 
se200pci_set_pro_rate(struct snd_ice1712 * ice,unsigned int rate)332f31639b8SShin-ya Okada static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
333f31639b8SShin-ya Okada {
334f31639b8SShin-ya Okada 	se200pci_WM8740_set_pro_rate(ice, rate);
335f31639b8SShin-ya Okada 	se200pci_WM8766_set_pro_rate(ice, rate);
336f31639b8SShin-ya Okada 	se200pci_WM8776_set_pro_rate(ice, rate);
337f31639b8SShin-ya Okada }
338f31639b8SShin-ya Okada 
339f31639b8SShin-ya Okada struct se200pci_control {
340a2af050fSTakashi Iwai 	const char *name;
341f31639b8SShin-ya Okada 	enum {
342f31639b8SShin-ya Okada 		WM8766,
343f31639b8SShin-ya Okada 		WM8776in,
344f31639b8SShin-ya Okada 		WM8776out,
345f31639b8SShin-ya Okada 		WM8776sel,
346f31639b8SShin-ya Okada 		WM8776agc,
347f31639b8SShin-ya Okada 		WM8776afl
348f31639b8SShin-ya Okada 	} target;
349f31639b8SShin-ya Okada 	enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
350f31639b8SShin-ya Okada 	int ch;
351a2af050fSTakashi Iwai 	const char * const *member;
352f31639b8SShin-ya Okada 	const char *comment;
353f31639b8SShin-ya Okada };
354f31639b8SShin-ya Okada 
355f31639b8SShin-ya Okada static const struct se200pci_control se200pci_cont[] = {
356f31639b8SShin-ya Okada 	{
357f31639b8SShin-ya Okada 		.name = "Front Playback Volume",
358f31639b8SShin-ya Okada 		.target = WM8776out,
359f31639b8SShin-ya Okada 		.type = VOLUME1,
360f31639b8SShin-ya Okada 		.comment = "Front(green)"
361f31639b8SShin-ya Okada 	},
362f31639b8SShin-ya Okada 	{
363f31639b8SShin-ya Okada 		.name = "Side Playback Volume",
364f31639b8SShin-ya Okada 		.target = WM8766,
365f31639b8SShin-ya Okada 		.type = VOLUME1,
366f31639b8SShin-ya Okada 		.ch = 1,
367f31639b8SShin-ya Okada 		.comment = "Surround(orange)"
368f31639b8SShin-ya Okada 	},
369f31639b8SShin-ya Okada 	{
370f31639b8SShin-ya Okada 		.name = "Surround Playback Volume",
371f31639b8SShin-ya Okada 		.target = WM8766,
372f31639b8SShin-ya Okada 		.type = VOLUME1,
373f31639b8SShin-ya Okada 		.ch = 2,
374f31639b8SShin-ya Okada 		.comment = "SurroundBack(white)"
375f31639b8SShin-ya Okada 	},
376f31639b8SShin-ya Okada 	{
377f31639b8SShin-ya Okada 		.name = "CLFE Playback Volume",
378f31639b8SShin-ya Okada 		.target = WM8766,
379f31639b8SShin-ya Okada 		.type = VOLUME1,
380f31639b8SShin-ya Okada 		.ch = 0,
381f31639b8SShin-ya Okada 		.comment = "Center(Lch)&SubWoofer(Rch)(black)"
382f31639b8SShin-ya Okada 	},
383f31639b8SShin-ya Okada 	{
384f31639b8SShin-ya Okada 		.name = "Capture Volume",
385f31639b8SShin-ya Okada 		.target = WM8776in,
386f31639b8SShin-ya Okada 		.type = VOLUME2
387f31639b8SShin-ya Okada 	},
388f31639b8SShin-ya Okada 	{
389f31639b8SShin-ya Okada 		.name = "Capture Select",
390f31639b8SShin-ya Okada 		.target = WM8776sel,
391f31639b8SShin-ya Okada 		.type = ENUM,
392f31639b8SShin-ya Okada 		.member = se200pci_sel
393f31639b8SShin-ya Okada 	},
394f31639b8SShin-ya Okada 	{
395f31639b8SShin-ya Okada 		.name = "AGC Capture Mode",
396f31639b8SShin-ya Okada 		.target = WM8776agc,
397f31639b8SShin-ya Okada 		.type = ENUM,
398f31639b8SShin-ya Okada 		.member = se200pci_agc
399f31639b8SShin-ya Okada 	},
400f31639b8SShin-ya Okada 	{
401f31639b8SShin-ya Okada 		.name = "AFL Bypass Playback Switch",
402f31639b8SShin-ya Okada 		.target = WM8776afl,
403f31639b8SShin-ya Okada 		.type = BOOLEAN
404f31639b8SShin-ya Okada 	}
405f31639b8SShin-ya Okada };
406f31639b8SShin-ya Okada 
se200pci_get_enum_count(int n)4079c45ba10STakashi Iwai static int se200pci_get_enum_count(int n)
4089c45ba10STakashi Iwai {
409a2af050fSTakashi Iwai 	const char * const *member;
4109c45ba10STakashi Iwai 	int c;
4119c45ba10STakashi Iwai 
4129c45ba10STakashi Iwai 	member = se200pci_cont[n].member;
4139c45ba10STakashi Iwai 	if (!member)
4149c45ba10STakashi Iwai 		return 0;
4159c45ba10STakashi Iwai 	for (c = 0; member[c]; c++)
4169c45ba10STakashi Iwai 		;
4179c45ba10STakashi Iwai 	return c;
4189c45ba10STakashi Iwai }
4199c45ba10STakashi Iwai 
se200pci_cont_volume_info(struct snd_kcontrol * kc,struct snd_ctl_elem_info * uinfo)4209c45ba10STakashi Iwai static int se200pci_cont_volume_info(struct snd_kcontrol *kc,
421f31639b8SShin-ya Okada 				     struct snd_ctl_elem_info *uinfo)
422f31639b8SShin-ya Okada {
423f31639b8SShin-ya Okada 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
424f31639b8SShin-ya Okada 	uinfo->count = 2;
425f31639b8SShin-ya Okada 	uinfo->value.integer.min = 0; /* mute */
426f31639b8SShin-ya Okada 	uinfo->value.integer.max = 0xff; /* 0dB */
4279c45ba10STakashi Iwai 	return 0;
4289c45ba10STakashi Iwai }
429f31639b8SShin-ya Okada 
4309c45ba10STakashi Iwai #define se200pci_cont_boolean_info	snd_ctl_boolean_mono_info
431f31639b8SShin-ya Okada 
se200pci_cont_enum_info(struct snd_kcontrol * kc,struct snd_ctl_elem_info * uinfo)4329c45ba10STakashi Iwai static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
4339c45ba10STakashi Iwai 				   struct snd_ctl_elem_info *uinfo)
4349c45ba10STakashi Iwai {
4359c45ba10STakashi Iwai 	int n, c;
4369c45ba10STakashi Iwai 
4379c45ba10STakashi Iwai 	n = kc->private_value;
4389c45ba10STakashi Iwai 	c = se200pci_get_enum_count(n);
4399c45ba10STakashi Iwai 	if (!c)
440f31639b8SShin-ya Okada 		return -EINVAL;
441597da2e4STakashi Iwai 	return snd_ctl_enum_info(uinfo, 1, c, se200pci_cont[n].member);
442f31639b8SShin-ya Okada }
443f31639b8SShin-ya Okada 
se200pci_cont_volume_get(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)4449c45ba10STakashi Iwai static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
445f31639b8SShin-ya Okada 				    struct snd_ctl_elem_value *uc)
446f31639b8SShin-ya Okada {
4479c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
4487cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
4499c45ba10STakashi Iwai 	int n = kc->private_value;
4507cda8ba9STakashi Iwai 	uc->value.integer.value[0] = spec->vol[n].ch1;
4517cda8ba9STakashi Iwai 	uc->value.integer.value[1] = spec->vol[n].ch2;
452f31639b8SShin-ya Okada 	return 0;
453f31639b8SShin-ya Okada }
454f31639b8SShin-ya Okada 
se200pci_cont_boolean_get(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)4559c45ba10STakashi Iwai static int se200pci_cont_boolean_get(struct snd_kcontrol *kc,
456f31639b8SShin-ya Okada 				     struct snd_ctl_elem_value *uc)
457f31639b8SShin-ya Okada {
4589c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
4597cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
4609c45ba10STakashi Iwai 	int n = kc->private_value;
4617cda8ba9STakashi Iwai 	uc->value.integer.value[0] = spec->vol[n].ch1;
4629c45ba10STakashi Iwai 	return 0;
463f31639b8SShin-ya Okada }
464f31639b8SShin-ya Okada 
se200pci_cont_enum_get(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)4659c45ba10STakashi Iwai static int se200pci_cont_enum_get(struct snd_kcontrol *kc,
4669c45ba10STakashi Iwai 				  struct snd_ctl_elem_value *uc)
4679c45ba10STakashi Iwai {
4689c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
4697cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
4709c45ba10STakashi Iwai 	int n = kc->private_value;
4717cda8ba9STakashi Iwai 	uc->value.enumerated.item[0] = spec->vol[n].ch1;
4729c45ba10STakashi Iwai 	return 0;
4739c45ba10STakashi Iwai }
4749c45ba10STakashi Iwai 
se200pci_cont_update(struct snd_ice1712 * ice,int n)4759c45ba10STakashi Iwai static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
4769c45ba10STakashi Iwai {
4777cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
478f31639b8SShin-ya Okada 	switch (se200pci_cont[n].target) {
479f31639b8SShin-ya Okada 	case WM8766:
480f31639b8SShin-ya Okada 		se200pci_WM8766_set_volume(ice,
4819c45ba10STakashi Iwai 					   se200pci_cont[n].ch,
4827cda8ba9STakashi Iwai 					   spec->vol[n].ch1,
4837cda8ba9STakashi Iwai 					   spec->vol[n].ch2);
484f31639b8SShin-ya Okada 		break;
485f31639b8SShin-ya Okada 
486f31639b8SShin-ya Okada 	case WM8776in:
4879c45ba10STakashi Iwai 		se200pci_WM8776_set_input_volume(ice,
4887cda8ba9STakashi Iwai 						 spec->vol[n].ch1,
4897cda8ba9STakashi Iwai 						 spec->vol[n].ch2);
490f31639b8SShin-ya Okada 		break;
491f31639b8SShin-ya Okada 
492f31639b8SShin-ya Okada 	case WM8776out:
4939c45ba10STakashi Iwai 		se200pci_WM8776_set_output_volume(ice,
4947cda8ba9STakashi Iwai 						  spec->vol[n].ch1,
4957cda8ba9STakashi Iwai 						  spec->vol[n].ch2);
496f31639b8SShin-ya Okada 		break;
497f31639b8SShin-ya Okada 
498f31639b8SShin-ya Okada 	case WM8776sel:
4999c45ba10STakashi Iwai 		se200pci_WM8776_set_input_selector(ice,
5007cda8ba9STakashi Iwai 						   spec->vol[n].ch1);
501f31639b8SShin-ya Okada 		break;
502f31639b8SShin-ya Okada 
503f31639b8SShin-ya Okada 	case WM8776agc:
5047cda8ba9STakashi Iwai 		se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
505f31639b8SShin-ya Okada 		break;
506f31639b8SShin-ya Okada 
507f31639b8SShin-ya Okada 	case WM8776afl:
5087cda8ba9STakashi Iwai 		se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
509f31639b8SShin-ya Okada 		break;
510f31639b8SShin-ya Okada 
511f31639b8SShin-ya Okada 	default:
512f31639b8SShin-ya Okada 		break;
513f31639b8SShin-ya Okada 	}
5149c45ba10STakashi Iwai }
5159c45ba10STakashi Iwai 
se200pci_cont_volume_put(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)5169c45ba10STakashi Iwai static int se200pci_cont_volume_put(struct snd_kcontrol *kc,
5179c45ba10STakashi Iwai 				    struct snd_ctl_elem_value *uc)
5189c45ba10STakashi Iwai {
5199c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
5207cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
5219c45ba10STakashi Iwai 	int n = kc->private_value;
5229c45ba10STakashi Iwai 	unsigned int vol1, vol2;
5239c45ba10STakashi Iwai 	int changed;
5249c45ba10STakashi Iwai 
5259c45ba10STakashi Iwai 	changed = 0;
5269c45ba10STakashi Iwai 	vol1 = uc->value.integer.value[0] & 0xff;
5279c45ba10STakashi Iwai 	vol2 = uc->value.integer.value[1] & 0xff;
5287cda8ba9STakashi Iwai 	if (spec->vol[n].ch1 != vol1) {
5297cda8ba9STakashi Iwai 		spec->vol[n].ch1 = vol1;
5309c45ba10STakashi Iwai 		changed = 1;
5319c45ba10STakashi Iwai 	}
5327cda8ba9STakashi Iwai 	if (spec->vol[n].ch2 != vol2) {
5337cda8ba9STakashi Iwai 		spec->vol[n].ch2 = vol2;
5349c45ba10STakashi Iwai 		changed = 1;
5359c45ba10STakashi Iwai 	}
5369c45ba10STakashi Iwai 	if (changed)
5379c45ba10STakashi Iwai 		se200pci_cont_update(ice, n);
538f31639b8SShin-ya Okada 
539f31639b8SShin-ya Okada 	return changed;
540f31639b8SShin-ya Okada }
541f31639b8SShin-ya Okada 
se200pci_cont_boolean_put(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)5429c45ba10STakashi Iwai static int se200pci_cont_boolean_put(struct snd_kcontrol *kc,
5439c45ba10STakashi Iwai 				     struct snd_ctl_elem_value *uc)
5449c45ba10STakashi Iwai {
5459c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
5467cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
5479c45ba10STakashi Iwai 	int n = kc->private_value;
5489c45ba10STakashi Iwai 	unsigned int vol1;
5499c45ba10STakashi Iwai 
5509c45ba10STakashi Iwai 	vol1 = !!uc->value.integer.value[0];
5517cda8ba9STakashi Iwai 	if (spec->vol[n].ch1 != vol1) {
5527cda8ba9STakashi Iwai 		spec->vol[n].ch1 = vol1;
5539c45ba10STakashi Iwai 		se200pci_cont_update(ice, n);
5549c45ba10STakashi Iwai 		return 1;
5559c45ba10STakashi Iwai 	}
5569c45ba10STakashi Iwai 	return 0;
5579c45ba10STakashi Iwai }
5589c45ba10STakashi Iwai 
se200pci_cont_enum_put(struct snd_kcontrol * kc,struct snd_ctl_elem_value * uc)5599c45ba10STakashi Iwai static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
5609c45ba10STakashi Iwai 				  struct snd_ctl_elem_value *uc)
5619c45ba10STakashi Iwai {
5629c45ba10STakashi Iwai 	struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
5637cda8ba9STakashi Iwai 	struct se_spec *spec = ice->spec;
5649c45ba10STakashi Iwai 	int n = kc->private_value;
5659c45ba10STakashi Iwai 	unsigned int vol1;
5669c45ba10STakashi Iwai 
5679c45ba10STakashi Iwai 	vol1 = uc->value.enumerated.item[0];
5689c45ba10STakashi Iwai 	if (vol1 >= se200pci_get_enum_count(n))
5699c45ba10STakashi Iwai 		return -EINVAL;
5707cda8ba9STakashi Iwai 	if (spec->vol[n].ch1 != vol1) {
5717cda8ba9STakashi Iwai 		spec->vol[n].ch1 = vol1;
5729c45ba10STakashi Iwai 		se200pci_cont_update(ice, n);
5739c45ba10STakashi Iwai 		return 1;
5749c45ba10STakashi Iwai 	}
5759c45ba10STakashi Iwai 	return 0;
5769c45ba10STakashi Iwai }
5779c45ba10STakashi Iwai 
578f31639b8SShin-ya Okada static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
579f31639b8SShin-ya Okada static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
580f31639b8SShin-ya Okada 
se200pci_add_controls(struct snd_ice1712 * ice)581e23e7a14SBill Pemberton static int se200pci_add_controls(struct snd_ice1712 *ice)
582f31639b8SShin-ya Okada {
583f31639b8SShin-ya Okada 	int i;
584f31639b8SShin-ya Okada 	struct snd_kcontrol_new cont;
585f31639b8SShin-ya Okada 	int err;
586f31639b8SShin-ya Okada 
587f31639b8SShin-ya Okada 	memset(&cont, 0, sizeof(cont));
588f31639b8SShin-ya Okada 	cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
589f31639b8SShin-ya Okada 	for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
590f31639b8SShin-ya Okada 		cont.private_value = i;
591f31639b8SShin-ya Okada 		cont.name = se200pci_cont[i].name;
592f31639b8SShin-ya Okada 		cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
593f31639b8SShin-ya Okada 		cont.tlv.p = NULL;
5949c45ba10STakashi Iwai 		switch (se200pci_cont[i].type) {
5959c45ba10STakashi Iwai 		case VOLUME1:
5969c45ba10STakashi Iwai 		case VOLUME2:
5979c45ba10STakashi Iwai 			cont.info = se200pci_cont_volume_info;
5989c45ba10STakashi Iwai 			cont.get = se200pci_cont_volume_get;
5999c45ba10STakashi Iwai 			cont.put = se200pci_cont_volume_put;
600f31639b8SShin-ya Okada 			cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
601f31639b8SShin-ya Okada 			if (se200pci_cont[i].type == VOLUME1)
602f31639b8SShin-ya Okada 				cont.tlv.p = db_scale_gain1;
603f31639b8SShin-ya Okada 			else
604f31639b8SShin-ya Okada 				cont.tlv.p = db_scale_gain2;
6059c45ba10STakashi Iwai 			break;
6069c45ba10STakashi Iwai 		case BOOLEAN:
6079c45ba10STakashi Iwai 			cont.info = se200pci_cont_boolean_info;
6089c45ba10STakashi Iwai 			cont.get = se200pci_cont_boolean_get;
6099c45ba10STakashi Iwai 			cont.put = se200pci_cont_boolean_put;
6109c45ba10STakashi Iwai 			break;
6119c45ba10STakashi Iwai 		case ENUM:
6129c45ba10STakashi Iwai 			cont.info = se200pci_cont_enum_info;
6139c45ba10STakashi Iwai 			cont.get = se200pci_cont_enum_get;
6149c45ba10STakashi Iwai 			cont.put = se200pci_cont_enum_put;
6159c45ba10STakashi Iwai 			break;
6169c45ba10STakashi Iwai 		default:
6179c45ba10STakashi Iwai 			snd_BUG();
6189c45ba10STakashi Iwai 			return -EINVAL;
619f31639b8SShin-ya Okada 		}
620f31639b8SShin-ya Okada 		err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
621f31639b8SShin-ya Okada 		if (err < 0)
622f31639b8SShin-ya Okada 			return err;
623f31639b8SShin-ya Okada 	}
624f31639b8SShin-ya Okada 
625f31639b8SShin-ya Okada 	return 0;
626f31639b8SShin-ya Okada }
627f31639b8SShin-ya Okada 
628f31639b8SShin-ya Okada 
629f31639b8SShin-ya Okada /****************************************************************************/
630f31639b8SShin-ya Okada /*  ONKYO WAVIO SE-90PCI                                                    */
631f31639b8SShin-ya Okada /****************************************************************************/
632f31639b8SShin-ya Okada /*
633f31639b8SShin-ya Okada  *  system configuration ICE_EEP2_SYSCONF=0x4b
634f31639b8SShin-ya Okada  *  AC-Link configuration ICE_EEP2_ACLINK=0x80
635f31639b8SShin-ya Okada  *  I2S converters feature ICE_EEP2_I2S=0x78
636f31639b8SShin-ya Okada  *  S/PDIF configuration ICE_EEP2_SPDIF=0xc3
637f31639b8SShin-ya Okada  *
638f31639b8SShin-ya Okada  *  ** connected chip **
639f31639b8SShin-ya Okada  *
640f31639b8SShin-ya Okada  *   WM8716
641f31639b8SShin-ya Okada  *      A 2ch-DAC of main outputs.
642f31639b8SShin-ya Okada  *      It setuped as I2S mode by wire, so no way to setup from software.
643f31639b8SShin-ya Okada  *         ML/I2S (28pin) -- +5V
644f31639b8SShin-ya Okada  *         MC/DM1 (27pin) -- GND
645f31639b8SShin-ya Okada  *         MC/DM0 (26pin) -- GND
646f31639b8SShin-ya Okada  *         MUTEB  (25pin) -- open (internal pull-up)
647f31639b8SShin-ya Okada  *         MODE   (24pin) -- GND
648f31639b8SShin-ya Okada  *         CSBIWO (23pin) -- +5V
649f31639b8SShin-ya Okada  *
650f31639b8SShin-ya Okada  */
651f31639b8SShin-ya Okada 
652f31639b8SShin-ya Okada  /* Nothing to do for this chip. */
653f31639b8SShin-ya Okada 
654f31639b8SShin-ya Okada 
655f31639b8SShin-ya Okada /****************************************************************************/
656f31639b8SShin-ya Okada /*  probe/initialize/setup                                                  */
657f31639b8SShin-ya Okada /****************************************************************************/
658f31639b8SShin-ya Okada 
se_init(struct snd_ice1712 * ice)659e23e7a14SBill Pemberton static int se_init(struct snd_ice1712 *ice)
660f31639b8SShin-ya Okada {
6617cda8ba9STakashi Iwai 	struct se_spec *spec;
6627cda8ba9STakashi Iwai 
6637cda8ba9STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6647cda8ba9STakashi Iwai 	if (!spec)
6657cda8ba9STakashi Iwai 		return -ENOMEM;
6667cda8ba9STakashi Iwai 	ice->spec = spec;
6677cda8ba9STakashi Iwai 
668f31639b8SShin-ya Okada 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
669f31639b8SShin-ya Okada 		ice->num_total_dacs = 2;
670f31639b8SShin-ya Okada 		ice->num_total_adcs = 0;
671f31639b8SShin-ya Okada 		ice->vt1720 = 1;
672f31639b8SShin-ya Okada 		return 0;
673f31639b8SShin-ya Okada 
674f31639b8SShin-ya Okada 	} else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
675f31639b8SShin-ya Okada 		ice->num_total_dacs = 8;
676f31639b8SShin-ya Okada 		ice->num_total_adcs = 2;
677f31639b8SShin-ya Okada 		se200pci_WM8740_init(ice);
678f31639b8SShin-ya Okada 		se200pci_WM8766_init(ice);
679f31639b8SShin-ya Okada 		se200pci_WM8776_init(ice);
680f31639b8SShin-ya Okada 		ice->gpio.set_pro_rate = se200pci_set_pro_rate;
681f31639b8SShin-ya Okada 		return 0;
682f31639b8SShin-ya Okada 	}
683f31639b8SShin-ya Okada 
684f31639b8SShin-ya Okada 	return -ENOENT;
685f31639b8SShin-ya Okada }
686f31639b8SShin-ya Okada 
se_add_controls(struct snd_ice1712 * ice)687e23e7a14SBill Pemberton static int se_add_controls(struct snd_ice1712 *ice)
688f31639b8SShin-ya Okada {
689f31639b8SShin-ya Okada 	int err;
690f31639b8SShin-ya Okada 
691f31639b8SShin-ya Okada 	err = 0;
692f31639b8SShin-ya Okada 	/* nothing to do for VT1724_SUBDEVICE_SE90PCI */
693f31639b8SShin-ya Okada 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
694f31639b8SShin-ya Okada 		err = se200pci_add_controls(ice);
695f31639b8SShin-ya Okada 
696f31639b8SShin-ya Okada 	return err;
697f31639b8SShin-ya Okada }
698f31639b8SShin-ya Okada 
699f31639b8SShin-ya Okada 
700f31639b8SShin-ya Okada /****************************************************************************/
701f31639b8SShin-ya Okada /*  entry point                                                             */
702f31639b8SShin-ya Okada /****************************************************************************/
703f31639b8SShin-ya Okada 
704*f16a4e96STakashi Iwai static const unsigned char se200pci_eeprom[] = {
705f31639b8SShin-ya Okada 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
706f31639b8SShin-ya Okada 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
707f31639b8SShin-ya Okada 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
708f31639b8SShin-ya Okada 	[ICE_EEP2_SPDIF]	= 0xc3,	/* out-en, out-int, spdif-in */
709f31639b8SShin-ya Okada 
710f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_DIR]	= 0x02, /* WM8766 mute      1=output */
711f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_DIR1]	= 0x00, /* not used */
712f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_DIR2]	= 0x07, /* WM8766 ML/MC/MD  1=output */
713f31639b8SShin-ya Okada 
714f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_MASK]	= 0x00, /* 0=writable */
715f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_MASK1]	= 0x00, /* 0=writable */
716f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_MASK2]	= 0x00, /* 0=writable */
717f31639b8SShin-ya Okada 
718f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_STATE]	= 0x00, /* WM8766 mute=0 */
719f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_STATE1]	= 0x00, /* not used */
720f31639b8SShin-ya Okada 	[ICE_EEP2_GPIO_STATE2]	= 0x07, /* WM8766 ML/MC/MD */
721f31639b8SShin-ya Okada };
722f31639b8SShin-ya Okada 
723*f16a4e96STakashi Iwai static const unsigned char se90pci_eeprom[] = {
724f31639b8SShin-ya Okada 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
725f31639b8SShin-ya Okada 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
726f31639b8SShin-ya Okada 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
727f31639b8SShin-ya Okada 	[ICE_EEP2_SPDIF]	= 0xc3,	/* out-en, out-int, spdif-in */
728f31639b8SShin-ya Okada 
729f31639b8SShin-ya Okada 	/* ALL GPIO bits are in input mode */
730f31639b8SShin-ya Okada };
731f31639b8SShin-ya Okada 
732e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
733f31639b8SShin-ya Okada 	{
734f31639b8SShin-ya Okada 		.subvendor = VT1724_SUBDEVICE_SE200PCI,
735f31639b8SShin-ya Okada 		.name = "ONKYO SE200PCI",
736f31639b8SShin-ya Okada 		.model = "se200pci",
737f31639b8SShin-ya Okada 		.chip_init = se_init,
738f31639b8SShin-ya Okada 		.build_controls = se_add_controls,
739f31639b8SShin-ya Okada 		.eeprom_size = sizeof(se200pci_eeprom),
740f31639b8SShin-ya Okada 		.eeprom_data = se200pci_eeprom,
741f31639b8SShin-ya Okada 	},
742f31639b8SShin-ya Okada 	{
743f31639b8SShin-ya Okada 		.subvendor = VT1724_SUBDEVICE_SE90PCI,
744f31639b8SShin-ya Okada 		.name = "ONKYO SE90PCI",
745f31639b8SShin-ya Okada 		.model = "se90pci",
746f31639b8SShin-ya Okada 		.chip_init = se_init,
747f31639b8SShin-ya Okada 		.build_controls = se_add_controls,
748f31639b8SShin-ya Okada 		.eeprom_size = sizeof(se90pci_eeprom),
749f31639b8SShin-ya Okada 		.eeprom_data = se90pci_eeprom,
750f31639b8SShin-ya Okada 	},
751f31639b8SShin-ya Okada 	{} /*terminator*/
752f31639b8SShin-ya Okada };
753