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