xref: /linux/sound/pci/ice1712/wtm.c (revision 9cd17cd2409ddbe9853575569cfd97561fa86b14)
1f6cdab5fSClement Guedez /*
2f6cdab5fSClement Guedez  *	ALSA driver for ICEnsemble VT1724 (Envy24HT)
3f6cdab5fSClement Guedez  *
4f6cdab5fSClement Guedez  *	Lowlevel functions for Ego Sys Waveterminal 192M
5f6cdab5fSClement Guedez  *
6f6cdab5fSClement Guedez  *		Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
7f6cdab5fSClement Guedez  *		Some functions are taken from the Prodigy192 driver
8f6cdab5fSClement Guedez  *		source
9f6cdab5fSClement Guedez  *
10f6cdab5fSClement Guedez  *	This program is free software; you can redistribute it and/or modify
11f6cdab5fSClement Guedez  *	it under the terms of the GNU General Public License as published by
12f6cdab5fSClement Guedez  *	the Free Software Foundation; either version 2 of the License, or
13f6cdab5fSClement Guedez  *	(at your option) any later version.
14f6cdab5fSClement Guedez  *
15f6cdab5fSClement Guedez  *	This program is distributed in the hope that it will be useful,
16f6cdab5fSClement Guedez  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
17f6cdab5fSClement Guedez  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18f6cdab5fSClement Guedez  *	GNU General Public License for more details.
19f6cdab5fSClement Guedez  *
20f6cdab5fSClement Guedez  *	You should have received a copy of the GNU General Public License
21f6cdab5fSClement Guedez  *	along with this program; if not, write to the Free Software
22f6cdab5fSClement Guedez  *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23f6cdab5fSClement Guedez  *
24f6cdab5fSClement Guedez  */
25f6cdab5fSClement Guedez 
26f6cdab5fSClement Guedez 
27f6cdab5fSClement Guedez 
28f6cdab5fSClement Guedez #include <sound/driver.h>
29f6cdab5fSClement Guedez #include <asm/io.h>
30f6cdab5fSClement Guedez #include <linux/delay.h>
31f6cdab5fSClement Guedez #include <linux/interrupt.h>
32f6cdab5fSClement Guedez #include <linux/init.h>
33f6cdab5fSClement Guedez #include <linux/slab.h>
34f6cdab5fSClement Guedez #include <sound/core.h>
35f6cdab5fSClement Guedez 
36f6cdab5fSClement Guedez #include "ice1712.h"
37f6cdab5fSClement Guedez #include "envy24ht.h"
38f6cdab5fSClement Guedez #include "wtm.h"
39f6cdab5fSClement Guedez #include "stac946x.h"
40f6cdab5fSClement Guedez 
41f6cdab5fSClement Guedez 
42f6cdab5fSClement Guedez /*
43f6cdab5fSClement Guedez  *	2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
44f6cdab5fSClement Guedez  */
45f6cdab5fSClement Guedez static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
46f6cdab5fSClement Guedez 						unsigned char val)
47f6cdab5fSClement Guedez {
48f6cdab5fSClement Guedez 	snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
49f6cdab5fSClement Guedez }
50f6cdab5fSClement Guedez 
51f6cdab5fSClement Guedez static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
52f6cdab5fSClement Guedez {
53f6cdab5fSClement Guedez 	return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
54f6cdab5fSClement Guedez }
55f6cdab5fSClement Guedez 
56f6cdab5fSClement Guedez /*
57f6cdab5fSClement Guedez  *	2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
58f6cdab5fSClement Guedez  */
59f6cdab5fSClement Guedez static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
60f6cdab5fSClement Guedez 						unsigned char val)
61f6cdab5fSClement Guedez {
62f6cdab5fSClement Guedez 	snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
63f6cdab5fSClement Guedez }
64f6cdab5fSClement Guedez 
65f6cdab5fSClement Guedez static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
66f6cdab5fSClement Guedez {
67f6cdab5fSClement Guedez 	return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
68f6cdab5fSClement Guedez }
69f6cdab5fSClement Guedez 
70f6cdab5fSClement Guedez 
71f6cdab5fSClement Guedez /*
72f6cdab5fSClement Guedez  *	DAC mute control
73f6cdab5fSClement Guedez  */
74a5ce8890STakashi Iwai #define stac9460_dac_mute_info		snd_ctl_boolean_mono_info
75f6cdab5fSClement Guedez 
76f6cdab5fSClement Guedez static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
77f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
78f6cdab5fSClement Guedez {
79f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
80f6cdab5fSClement Guedez 	unsigned char val;
81f6cdab5fSClement Guedez 	int idx, id;
82f6cdab5fSClement Guedez 
83f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
84f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
85f6cdab5fSClement Guedez 		id = 0;
86f6cdab5fSClement Guedez 	} else {
87f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
88f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
89f6cdab5fSClement Guedez 	}
90f6cdab5fSClement Guedez 	if (id < 6)
91f6cdab5fSClement Guedez 		val = stac9460_get(ice, idx);
92f6cdab5fSClement Guedez 	else
93f6cdab5fSClement Guedez 		val = stac9460_2_get(ice,idx - 6);
94f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
95f6cdab5fSClement Guedez 	return 0;
96f6cdab5fSClement Guedez }
97f6cdab5fSClement Guedez 
98f6cdab5fSClement Guedez static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
99f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
100f6cdab5fSClement Guedez {
101f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
102f6cdab5fSClement Guedez 	unsigned char new, old;
103f6cdab5fSClement Guedez 	int id, idx;
104f6cdab5fSClement Guedez 	int change;
105f6cdab5fSClement Guedez 
106f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
107f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
108f6cdab5fSClement Guedez 		old = stac9460_get(ice, idx);
109f6cdab5fSClement Guedez 		new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
110f6cdab5fSClement Guedez 		       					(old & ~0x80);
111f6cdab5fSClement Guedez 		change = (new != old);
112f6cdab5fSClement Guedez 		if (change) {
113f6cdab5fSClement Guedez 			stac9460_put(ice, idx, new);
114f6cdab5fSClement Guedez 			stac9460_2_put(ice, idx, new);
115f6cdab5fSClement Guedez 		}
116f6cdab5fSClement Guedez 	} else {
117f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
118f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
119f6cdab5fSClement Guedez 		if (id < 6)
120f6cdab5fSClement Guedez 			old = stac9460_get(ice, idx);
121f6cdab5fSClement Guedez 		else
122f6cdab5fSClement Guedez 			old = stac9460_2_get(ice, idx - 6);
123f6cdab5fSClement Guedez 		new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
124f6cdab5fSClement Guedez 							(old & ~0x80);
125f6cdab5fSClement Guedez 		change = (new != old);
126f6cdab5fSClement Guedez 		if (change) {
127f6cdab5fSClement Guedez 			if (id < 6)
128f6cdab5fSClement Guedez 			       	stac9460_put(ice, idx, new);
129f6cdab5fSClement Guedez 			else
130f6cdab5fSClement Guedez 			       	stac9460_2_put(ice, idx - 6, new);
131f6cdab5fSClement Guedez 		}
132f6cdab5fSClement Guedez 	}
133f6cdab5fSClement Guedez 	return change;
134f6cdab5fSClement Guedez }
135f6cdab5fSClement Guedez 
136f6cdab5fSClement Guedez /*
137f6cdab5fSClement Guedez  * 	DAC volume attenuation mixer control
138f6cdab5fSClement Guedez  */
139f6cdab5fSClement Guedez static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
140f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_info *uinfo)
141f6cdab5fSClement Guedez {
142f6cdab5fSClement Guedez 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
143f6cdab5fSClement Guedez 	uinfo->count = 1;
144f6cdab5fSClement Guedez 	uinfo->value.integer.min = 0;			/* mute */
145f6cdab5fSClement Guedez 	uinfo->value.integer.max = 0x7f;		/* 0dB */
146f6cdab5fSClement Guedez 	return 0;
147f6cdab5fSClement Guedez }
148f6cdab5fSClement Guedez 
149f6cdab5fSClement Guedez static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
150f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
151f6cdab5fSClement Guedez {
152f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
153f6cdab5fSClement Guedez 	int idx, id;
154f6cdab5fSClement Guedez 	unsigned char vol;
155f6cdab5fSClement Guedez 
156f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
157f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
158f6cdab5fSClement Guedez 		id = 0;
159f6cdab5fSClement Guedez 	} else {
160f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
161f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
162f6cdab5fSClement Guedez 	}
163f6cdab5fSClement Guedez 	if (id < 6)
164f6cdab5fSClement Guedez 		vol = stac9460_get(ice, idx) & 0x7f;
165f6cdab5fSClement Guedez 	else
166f6cdab5fSClement Guedez 		vol = stac9460_2_get(ice, idx - 6) & 0x7f;
167f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = 0x7f - vol;
168f6cdab5fSClement Guedez 	return 0;
169f6cdab5fSClement Guedez }
170f6cdab5fSClement Guedez 
171f6cdab5fSClement Guedez static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
172f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
173f6cdab5fSClement Guedez {
174f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
175f6cdab5fSClement Guedez 	int idx, id;
176f6cdab5fSClement Guedez 	unsigned char tmp, ovol, nvol;
177f6cdab5fSClement Guedez 	int change;
178f6cdab5fSClement Guedez 
179f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
180f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
181*9cd17cd2STakashi Iwai 		nvol = ucontrol->value.integer.value[0] & 0x7f;
182f6cdab5fSClement Guedez 		tmp = stac9460_get(ice, idx);
183f6cdab5fSClement Guedez 		ovol = 0x7f - (tmp & 0x7f);
184f6cdab5fSClement Guedez 		change = (ovol != nvol);
185f6cdab5fSClement Guedez 		if (change) {
186f6cdab5fSClement Guedez 			 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
187f6cdab5fSClement Guedez 			 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
188f6cdab5fSClement Guedez 		}
189f6cdab5fSClement Guedez 	} else {
190f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
191f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
192*9cd17cd2STakashi Iwai 		nvol = ucontrol->value.integer.value[0] & 0x7f;
193f6cdab5fSClement Guedez 		if (id < 6)
194f6cdab5fSClement Guedez 			tmp = stac9460_get(ice, idx);
195f6cdab5fSClement Guedez 		else
196f6cdab5fSClement Guedez 			tmp = stac9460_2_get(ice, idx - 6);
197f6cdab5fSClement Guedez 		ovol = 0x7f - (tmp & 0x7f);
198f6cdab5fSClement Guedez 		change = (ovol != nvol);
199f6cdab5fSClement Guedez 		if (change) {
200f6cdab5fSClement Guedez 			if (id < 6)
201f6cdab5fSClement Guedez 				stac9460_put(ice, idx, (0x7f - nvol) |
202f6cdab5fSClement Guedez 					       		(tmp & 0x80));
203f6cdab5fSClement Guedez 			else
204f6cdab5fSClement Guedez 				stac9460_2_put(ice, idx-6, (0x7f - nvol) |
205f6cdab5fSClement Guedez 					       			(tmp & 0x80));
206f6cdab5fSClement Guedez 		}
207f6cdab5fSClement Guedez 	}
208f6cdab5fSClement Guedez 	return change;
209f6cdab5fSClement Guedez }
210f6cdab5fSClement Guedez 
211f6cdab5fSClement Guedez /*
212f6cdab5fSClement Guedez  * ADC mute control
213f6cdab5fSClement Guedez  */
214a5ce8890STakashi Iwai #define stac9460_adc_mute_info		snd_ctl_boolean_stereo_info
215f6cdab5fSClement Guedez 
216f6cdab5fSClement Guedez static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
217f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
218f6cdab5fSClement Guedez {
219f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
220f6cdab5fSClement Guedez 	unsigned char val;
221f6cdab5fSClement Guedez 	int i, id;
222f6cdab5fSClement Guedez 
223f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
224f6cdab5fSClement Guedez 	if (id == 0) {
225f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
226f6cdab5fSClement Guedez 			val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
227f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
228f6cdab5fSClement Guedez 		}
229f6cdab5fSClement Guedez 	} else {
230f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
231f6cdab5fSClement Guedez 			val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
232f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
233f6cdab5fSClement Guedez 		}
234f6cdab5fSClement Guedez 	}
235f6cdab5fSClement Guedez 	return 0;
236f6cdab5fSClement Guedez }
237f6cdab5fSClement Guedez 
238f6cdab5fSClement Guedez static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
239f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
240f6cdab5fSClement Guedez {
241f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
242f6cdab5fSClement Guedez 	unsigned char new, old;
243f6cdab5fSClement Guedez 	int i, reg, id;
244f6cdab5fSClement Guedez 	int change;
245f6cdab5fSClement Guedez 
246f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247f6cdab5fSClement Guedez 	if (id == 0) {
248f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
249f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
250f6cdab5fSClement Guedez 			old = stac9460_get(ice, reg);
251f6cdab5fSClement Guedez 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
252f6cdab5fSClement Guedez 			       					(old&~0x80);
253f6cdab5fSClement Guedez 			change = (new != old);
254f6cdab5fSClement Guedez 			if (change)
255f6cdab5fSClement Guedez 				stac9460_put(ice, reg, new);
256f6cdab5fSClement Guedez 		}
257f6cdab5fSClement Guedez 	} else {
258f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
259f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
260f6cdab5fSClement Guedez 			old = stac9460_2_get(ice, reg);
261f6cdab5fSClement Guedez 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
262f6cdab5fSClement Guedez 			       					(old&~0x80);
263f6cdab5fSClement Guedez 			change = (new != old);
264f6cdab5fSClement Guedez 			if (change)
265f6cdab5fSClement Guedez 				stac9460_2_put(ice, reg, new);
266f6cdab5fSClement Guedez 		}
267f6cdab5fSClement Guedez 	}
268f6cdab5fSClement Guedez 	return change;
269f6cdab5fSClement Guedez }
270f6cdab5fSClement Guedez 
271f6cdab5fSClement Guedez /*
272f6cdab5fSClement Guedez  *ADC gain mixer control
273f6cdab5fSClement Guedez  */
274f6cdab5fSClement Guedez static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
275f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_info *uinfo)
276f6cdab5fSClement Guedez {
277f6cdab5fSClement Guedez 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
278f6cdab5fSClement Guedez 	uinfo->count = 2;
279f6cdab5fSClement Guedez 	uinfo->value.integer.min = 0;		/* 0dB */
280f6cdab5fSClement Guedez 	uinfo->value.integer.max = 0x0f;	/* 22.5dB */
281f6cdab5fSClement Guedez 	return 0;
282f6cdab5fSClement Guedez }
283f6cdab5fSClement Guedez 
284f6cdab5fSClement Guedez static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
285f6cdab5fSClement Guedez 	       			struct snd_ctl_elem_value *ucontrol)
286f6cdab5fSClement Guedez {
287f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
288f6cdab5fSClement Guedez 	int i, reg, id;
289f6cdab5fSClement Guedez 	unsigned char vol;
290f6cdab5fSClement Guedez 
291f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
292f6cdab5fSClement Guedez 	if (id == 0) {
293f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
294f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
295f6cdab5fSClement Guedez 			vol = stac9460_get(ice, reg) & 0x0f;
296f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = 0x0f - vol;
297f6cdab5fSClement Guedez 		}
298f6cdab5fSClement Guedez 	} else {
299f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
300f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
301f6cdab5fSClement Guedez 			vol = stac9460_2_get(ice, reg) & 0x0f;
302f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = 0x0f - vol;
303f6cdab5fSClement Guedez 		}
304f6cdab5fSClement Guedez 	}
305f6cdab5fSClement Guedez 	return 0;
306f6cdab5fSClement Guedez }
307f6cdab5fSClement Guedez 
308f6cdab5fSClement Guedez static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
309f6cdab5fSClement Guedez 	       		struct snd_ctl_elem_value *ucontrol)
310f6cdab5fSClement Guedez {
311f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
312f6cdab5fSClement Guedez 	int i, reg, id;
313f6cdab5fSClement Guedez 	unsigned char ovol, nvol;
314f6cdab5fSClement Guedez 	int change;
315f6cdab5fSClement Guedez 
316f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
317f6cdab5fSClement Guedez 	if (id == 0) {
318f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
319f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
320*9cd17cd2STakashi Iwai 			nvol = ucontrol->value.integer.value[i] & 0x0f;
321f6cdab5fSClement Guedez 			ovol = 0x0f - stac9460_get(ice, reg);
322f6cdab5fSClement Guedez 			change = ((ovol & 0x0f) != nvol);
323f6cdab5fSClement Guedez 			if (change)
324f6cdab5fSClement Guedez 				stac9460_put(ice, reg, (0x0f - nvol) |
325f6cdab5fSClement Guedez 					       		(ovol & ~0x0f));
326f6cdab5fSClement Guedez 		}
327f6cdab5fSClement Guedez 	} else {
328f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
329f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
330*9cd17cd2STakashi Iwai 			nvol = ucontrol->value.integer.value[i] & 0x0f;
331f6cdab5fSClement Guedez 			ovol = 0x0f - stac9460_2_get(ice, reg);
332f6cdab5fSClement Guedez 			change = ((ovol & 0x0f) != nvol);
333f6cdab5fSClement Guedez 			if (change)
334f6cdab5fSClement Guedez 				stac9460_2_put(ice, reg, (0x0f - nvol) |
335f6cdab5fSClement Guedez 					       		(ovol & ~0x0f));
336f6cdab5fSClement Guedez 		}
337f6cdab5fSClement Guedez 	}
338f6cdab5fSClement Guedez 	return change;
339f6cdab5fSClement Guedez }
340f6cdab5fSClement Guedez 
341f6cdab5fSClement Guedez /*
342f6cdab5fSClement Guedez  * MIC / LINE switch fonction
343f6cdab5fSClement Guedez  */
344f6cdab5fSClement Guedez 
345a5ce8890STakashi Iwai #define stac9460_mic_sw_info		snd_ctl_boolean_mono_info
346f6cdab5fSClement Guedez 
347f6cdab5fSClement Guedez static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
348f6cdab5fSClement Guedez 	       		struct snd_ctl_elem_value *ucontrol)
349f6cdab5fSClement Guedez {
350f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
351f6cdab5fSClement Guedez 	unsigned char val;
352f6cdab5fSClement Guedez 	int id;
353f6cdab5fSClement Guedez 
354f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
355f6cdab5fSClement Guedez 	if (id == 0)
356f6cdab5fSClement Guedez 	       	val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
357f6cdab5fSClement Guedez 	else
358f6cdab5fSClement Guedez 	       	val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
359f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
360f6cdab5fSClement Guedez 	return 0;
361f6cdab5fSClement Guedez }
362f6cdab5fSClement Guedez 
363f6cdab5fSClement Guedez static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
364f6cdab5fSClement Guedez 	       		struct snd_ctl_elem_value *ucontrol)
365f6cdab5fSClement Guedez {
366f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
367f6cdab5fSClement Guedez 	unsigned char new, old;
368f6cdab5fSClement Guedez 	int change, id;
369f6cdab5fSClement Guedez 
370f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
371f6cdab5fSClement Guedez 	if (id == 0)
372f6cdab5fSClement Guedez 	       	old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
373f6cdab5fSClement Guedez 	else
374f6cdab5fSClement Guedez 	       	old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
375f6cdab5fSClement Guedez 	new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
376f6cdab5fSClement Guedez 	change = (new != old);
377f6cdab5fSClement Guedez 	if (change) {
378f6cdab5fSClement Guedez 		if (id == 0)
379f6cdab5fSClement Guedez 		       	stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
380f6cdab5fSClement Guedez 		else
381f6cdab5fSClement Guedez 		       	stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
382f6cdab5fSClement Guedez 	}
383f6cdab5fSClement Guedez 	return change;
384f6cdab5fSClement Guedez }
385f6cdab5fSClement Guedez 
386f6cdab5fSClement Guedez /*
387f6cdab5fSClement Guedez  * Control tabs
388f6cdab5fSClement Guedez  */
3891b60f6b0STakashi Iwai static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
390f6cdab5fSClement Guedez 	{
391f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
392f6cdab5fSClement Guedez 		.name = "Master Playback Switch",
393f6cdab5fSClement Guedez 		.info = stac9460_dac_mute_info,
394f6cdab5fSClement Guedez 		.get = stac9460_dac_mute_get,
395f6cdab5fSClement Guedez 		.put = stac9460_dac_mute_put,
396f6cdab5fSClement Guedez 		.private_value = 1
397f6cdab5fSClement Guedez 	},
398f6cdab5fSClement Guedez 	{
399f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
400f6cdab5fSClement Guedez 		.name = "Master Playback Volume",
401f6cdab5fSClement Guedez 		.info = stac9460_dac_vol_info,
402f6cdab5fSClement Guedez 		.get = stac9460_dac_vol_get,
403f6cdab5fSClement Guedez 		.put = stac9460_dac_vol_put,
404f6cdab5fSClement Guedez 		.private_value = 1,
405f6cdab5fSClement Guedez 	},
406f6cdab5fSClement Guedez 	{
407f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408f6cdab5fSClement Guedez 		.name = "MIC/Line switch",
409f6cdab5fSClement Guedez 		.count = 2,
410f6cdab5fSClement Guedez 		.info = stac9460_mic_sw_info,
411f6cdab5fSClement Guedez 		.get = stac9460_mic_sw_get,
412f6cdab5fSClement Guedez 		.put = stac9460_mic_sw_put,
413f6cdab5fSClement Guedez 
414f6cdab5fSClement Guedez 	},
415f6cdab5fSClement Guedez 	{
416f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
417f6cdab5fSClement Guedez 		.name = "DAC Switch",
418f6cdab5fSClement Guedez 		.count = 8,
419f6cdab5fSClement Guedez 		.info = stac9460_dac_mute_info,
420f6cdab5fSClement Guedez 		.get = stac9460_dac_mute_get,
421f6cdab5fSClement Guedez 		.put = stac9460_dac_mute_put,
422f6cdab5fSClement Guedez 	},
423f6cdab5fSClement Guedez 	{
424f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
425f6cdab5fSClement Guedez 		.name = "DAC Volume",
426f6cdab5fSClement Guedez 		.count = 8,
427f6cdab5fSClement Guedez 		.info = stac9460_dac_vol_info,
428f6cdab5fSClement Guedez 		.get = stac9460_dac_vol_get,
429f6cdab5fSClement Guedez 		.put = stac9460_dac_vol_put,
430f6cdab5fSClement Guedez 	},
431f6cdab5fSClement Guedez 	{
432f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
433f6cdab5fSClement Guedez 		.name = "ADC Switch",
434f6cdab5fSClement Guedez 		.count = 2,
435f6cdab5fSClement Guedez 		.info = stac9460_adc_mute_info,
436f6cdab5fSClement Guedez 		.get = stac9460_adc_mute_get,
437f6cdab5fSClement Guedez 		.put = stac9460_adc_mute_put,
438f6cdab5fSClement Guedez 	},
439f6cdab5fSClement Guedez 	{
440f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
441f6cdab5fSClement Guedez 		.name = "ADC Volume",
442f6cdab5fSClement Guedez 		.count = 2,
443f6cdab5fSClement Guedez 		.info = stac9460_adc_vol_info,
444f6cdab5fSClement Guedez 		.get = stac9460_adc_vol_get,
445f6cdab5fSClement Guedez 		.put = stac9460_adc_vol_put,
446f6cdab5fSClement Guedez 
447f6cdab5fSClement Guedez 	}
448f6cdab5fSClement Guedez };
449f6cdab5fSClement Guedez 
450f6cdab5fSClement Guedez 
451f6cdab5fSClement Guedez 
452f6cdab5fSClement Guedez /*INIT*/
453f6cdab5fSClement Guedez static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
454f6cdab5fSClement Guedez {
455f6cdab5fSClement Guedez 	unsigned int i;
456f6cdab5fSClement Guedez 	int err;
457f6cdab5fSClement Guedez 
458f6cdab5fSClement Guedez 	for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
459f6cdab5fSClement Guedez 		err = snd_ctl_add(ice->card,
460f6cdab5fSClement Guedez 				snd_ctl_new1(&stac9640_controls[i], ice));
461f6cdab5fSClement Guedez 		if (err < 0)
462f6cdab5fSClement Guedez 			return err;
463f6cdab5fSClement Guedez 	}
464f6cdab5fSClement Guedez 	return 0;
465f6cdab5fSClement Guedez }
466f6cdab5fSClement Guedez 
467f6cdab5fSClement Guedez static int __devinit wtm_init(struct snd_ice1712 *ice)
468f6cdab5fSClement Guedez {
469f6cdab5fSClement Guedez 	static unsigned short stac_inits_prodigy[] = {
470f6cdab5fSClement Guedez 		STAC946X_RESET, 0,
471f6cdab5fSClement Guedez 		(unsigned short)-1
472f6cdab5fSClement Guedez 	};
473f6cdab5fSClement Guedez 	unsigned short *p;
474f6cdab5fSClement Guedez 
475f6cdab5fSClement Guedez 	/*WTM 192M*/
476f6cdab5fSClement Guedez 	ice->num_total_dacs = 8;
477f6cdab5fSClement Guedez 	ice->num_total_adcs = 4;
478f6cdab5fSClement Guedez 	ice->force_rdma1 = 1;
479f6cdab5fSClement Guedez 
480f6cdab5fSClement Guedez 	/*initialize codec*/
481f6cdab5fSClement Guedez 	p = stac_inits_prodigy;
482f6cdab5fSClement Guedez 	for (; *p != (unsigned short)-1; p += 2) {
483f6cdab5fSClement Guedez 		stac9460_put(ice, p[0], p[1]);
484f6cdab5fSClement Guedez 		stac9460_2_put(ice, p[0], p[1]);
485f6cdab5fSClement Guedez 	}
486f6cdab5fSClement Guedez 	return 0;
487f6cdab5fSClement Guedez }
488f6cdab5fSClement Guedez 
489f6cdab5fSClement Guedez 
490f6cdab5fSClement Guedez static unsigned char wtm_eeprom[] __devinitdata = {
491f6cdab5fSClement Guedez 	0x47,	/*SYSCONF: clock 192KHz, 4ADC, 8DAC */
492f6cdab5fSClement Guedez 	0x80,	/* ACLINK : I2S */
493f6cdab5fSClement Guedez 	0xf8,	/* I2S: vol; 96k, 24bit, 192k */
494f6cdab5fSClement Guedez 	0xc1	/*SPDIF: out-en, spidf ext out*/,
495f6cdab5fSClement Guedez 	0x9f,	/* GPIO_DIR */
496f6cdab5fSClement Guedez 	0xff,	/* GPIO_DIR1 */
497f6cdab5fSClement Guedez 	0x7f,	/* GPIO_DIR2 */
498f6cdab5fSClement Guedez 	0x9f,	/* GPIO_MASK */
499f6cdab5fSClement Guedez 	0xff,	/* GPIO_MASK1 */
500f6cdab5fSClement Guedez 	0x7f,	/* GPIO_MASK2 */
501f6cdab5fSClement Guedez 	0x16,	/* GPIO_STATE */
502f6cdab5fSClement Guedez 	0x80,	/* GPIO_STATE1 */
503f6cdab5fSClement Guedez 	0x00,	/* GPIO_STATE2 */
504f6cdab5fSClement Guedez };
505f6cdab5fSClement Guedez 
506f6cdab5fSClement Guedez 
507f6cdab5fSClement Guedez /*entry point*/
508f6cdab5fSClement Guedez struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
509f6cdab5fSClement Guedez 	{
510f6cdab5fSClement Guedez 		.subvendor = VT1724_SUBDEVICE_WTM,
511f6cdab5fSClement Guedez 		.name = "ESI Waveterminal 192M",
512f6cdab5fSClement Guedez 		.model = "WT192M",
513f6cdab5fSClement Guedez 		.chip_init = wtm_init,
514f6cdab5fSClement Guedez 		.build_controls = wtm_add_controls,
515f6cdab5fSClement Guedez 		.eeprom_size = sizeof(wtm_eeprom),
516f6cdab5fSClement Guedez 		.eeprom_data = wtm_eeprom,
517f6cdab5fSClement Guedez 	},
518f6cdab5fSClement Guedez 	{} /*terminator*/
519f6cdab5fSClement Guedez };
520