xref: /linux/sound/pci/ice1712/wtm.c (revision f8a8b3a835ef9e5f94163c9dc62fc2e2e375b10c)
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 <linux/delay.h>
29f6cdab5fSClement Guedez #include <linux/interrupt.h>
30f6cdab5fSClement Guedez #include <linux/init.h>
31f6cdab5fSClement Guedez #include <sound/core.h>
32f6cdab5fSClement Guedez 
33f6cdab5fSClement Guedez #include "ice1712.h"
34f6cdab5fSClement Guedez #include "envy24ht.h"
35f6cdab5fSClement Guedez #include "wtm.h"
36f6cdab5fSClement Guedez #include "stac946x.h"
37f6cdab5fSClement Guedez 
38f6cdab5fSClement Guedez 
39f6cdab5fSClement Guedez /*
40f6cdab5fSClement Guedez  *	2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
41f6cdab5fSClement Guedez  */
42f6cdab5fSClement Guedez static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
43f6cdab5fSClement Guedez 						unsigned char val)
44f6cdab5fSClement Guedez {
45f6cdab5fSClement Guedez 	snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
46f6cdab5fSClement Guedez }
47f6cdab5fSClement Guedez 
48f6cdab5fSClement Guedez static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
49f6cdab5fSClement Guedez {
50f6cdab5fSClement Guedez 	return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
51f6cdab5fSClement Guedez }
52f6cdab5fSClement Guedez 
53f6cdab5fSClement Guedez /*
54f6cdab5fSClement Guedez  *	2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
55f6cdab5fSClement Guedez  */
56f6cdab5fSClement Guedez static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
57f6cdab5fSClement Guedez 						unsigned char val)
58f6cdab5fSClement Guedez {
59f6cdab5fSClement Guedez 	snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
60f6cdab5fSClement Guedez }
61f6cdab5fSClement Guedez 
62f6cdab5fSClement Guedez static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
63f6cdab5fSClement Guedez {
64f6cdab5fSClement Guedez 	return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
65f6cdab5fSClement Guedez }
66f6cdab5fSClement Guedez 
67f6cdab5fSClement Guedez 
68f6cdab5fSClement Guedez /*
69f6cdab5fSClement Guedez  *	DAC mute control
70f6cdab5fSClement Guedez  */
71a5ce8890STakashi Iwai #define stac9460_dac_mute_info		snd_ctl_boolean_mono_info
72f6cdab5fSClement Guedez 
73f6cdab5fSClement Guedez static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
74f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
75f6cdab5fSClement Guedez {
76f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
77f6cdab5fSClement Guedez 	unsigned char val;
78f6cdab5fSClement Guedez 	int idx, id;
79f6cdab5fSClement Guedez 
80f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
81f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
82f6cdab5fSClement Guedez 		id = 0;
83f6cdab5fSClement Guedez 	} else {
84f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
85f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
86f6cdab5fSClement Guedez 	}
87f6cdab5fSClement Guedez 	if (id < 6)
88f6cdab5fSClement Guedez 		val = stac9460_get(ice, idx);
89f6cdab5fSClement Guedez 	else
90f6cdab5fSClement Guedez 		val = stac9460_2_get(ice, idx - 6);
91f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
92f6cdab5fSClement Guedez 	return 0;
93f6cdab5fSClement Guedez }
94f6cdab5fSClement Guedez 
95f6cdab5fSClement Guedez static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
96f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
97f6cdab5fSClement Guedez {
98f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
99f6cdab5fSClement Guedez 	unsigned char new, old;
100f6cdab5fSClement Guedez 	int id, idx;
101f6cdab5fSClement Guedez 	int change;
102f6cdab5fSClement Guedez 
103f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
104f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
105f6cdab5fSClement Guedez 		old = stac9460_get(ice, idx);
106f6cdab5fSClement Guedez 		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
107f6cdab5fSClement Guedez 							(old & ~0x80);
108f6cdab5fSClement Guedez 		change = (new != old);
109f6cdab5fSClement Guedez 		if (change) {
110f6cdab5fSClement Guedez 			stac9460_put(ice, idx, new);
111f6cdab5fSClement Guedez 			stac9460_2_put(ice, idx, new);
112f6cdab5fSClement Guedez 		}
113f6cdab5fSClement Guedez 	} else {
114f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
115f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
116f6cdab5fSClement Guedez 		if (id < 6)
117f6cdab5fSClement Guedez 			old = stac9460_get(ice, idx);
118f6cdab5fSClement Guedez 		else
119f6cdab5fSClement Guedez 			old = stac9460_2_get(ice, idx - 6);
120f6cdab5fSClement Guedez 		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
121f6cdab5fSClement Guedez 							(old & ~0x80);
122f6cdab5fSClement Guedez 		change = (new != old);
123f6cdab5fSClement Guedez 		if (change) {
124f6cdab5fSClement Guedez 			if (id < 6)
125f6cdab5fSClement Guedez 				stac9460_put(ice, idx, new);
126f6cdab5fSClement Guedez 			else
127f6cdab5fSClement Guedez 				stac9460_2_put(ice, idx - 6, new);
128f6cdab5fSClement Guedez 		}
129f6cdab5fSClement Guedez 	}
130f6cdab5fSClement Guedez 	return change;
131f6cdab5fSClement Guedez }
132f6cdab5fSClement Guedez 
133f6cdab5fSClement Guedez /*
134f6cdab5fSClement Guedez  * 	DAC volume attenuation mixer control
135f6cdab5fSClement Guedez  */
136f6cdab5fSClement Guedez static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
137f6cdab5fSClement Guedez 				struct snd_ctl_elem_info *uinfo)
138f6cdab5fSClement Guedez {
139f6cdab5fSClement Guedez 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
140f6cdab5fSClement Guedez 	uinfo->count = 1;
141f6cdab5fSClement Guedez 	uinfo->value.integer.min = 0;			/* mute */
142f6cdab5fSClement Guedez 	uinfo->value.integer.max = 0x7f;		/* 0dB */
143f6cdab5fSClement Guedez 	return 0;
144f6cdab5fSClement Guedez }
145f6cdab5fSClement Guedez 
146f6cdab5fSClement Guedez static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
147f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
148f6cdab5fSClement Guedez {
149f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
150f6cdab5fSClement Guedez 	int idx, id;
151f6cdab5fSClement Guedez 	unsigned char vol;
152f6cdab5fSClement Guedez 
153f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
154f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
155f6cdab5fSClement Guedez 		id = 0;
156f6cdab5fSClement Guedez 	} else {
157f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
158f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
159f6cdab5fSClement Guedez 	}
160f6cdab5fSClement Guedez 	if (id < 6)
161f6cdab5fSClement Guedez 		vol = stac9460_get(ice, idx) & 0x7f;
162f6cdab5fSClement Guedez 	else
163f6cdab5fSClement Guedez 		vol = stac9460_2_get(ice, idx - 6) & 0x7f;
164f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = 0x7f - vol;
165f6cdab5fSClement Guedez 	return 0;
166f6cdab5fSClement Guedez }
167f6cdab5fSClement Guedez 
168f6cdab5fSClement Guedez static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
169f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
170f6cdab5fSClement Guedez {
171f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
172f6cdab5fSClement Guedez 	int idx, id;
173f6cdab5fSClement Guedez 	unsigned char tmp, ovol, nvol;
174f6cdab5fSClement Guedez 	int change;
175f6cdab5fSClement Guedez 
176f6cdab5fSClement Guedez 	if (kcontrol->private_value) {
177f6cdab5fSClement Guedez 		idx = STAC946X_MASTER_VOLUME;
1789cd17cd2STakashi Iwai 		nvol = ucontrol->value.integer.value[0] & 0x7f;
179f6cdab5fSClement Guedez 		tmp = stac9460_get(ice, idx);
180f6cdab5fSClement Guedez 		ovol = 0x7f - (tmp & 0x7f);
181f6cdab5fSClement Guedez 		change = (ovol != nvol);
182f6cdab5fSClement Guedez 		if (change) {
183f6cdab5fSClement Guedez 			stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
184f6cdab5fSClement Guedez 			stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
185f6cdab5fSClement Guedez 		}
186f6cdab5fSClement Guedez 	} else {
187f6cdab5fSClement Guedez 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
188f6cdab5fSClement Guedez 		idx = id + STAC946X_LF_VOLUME;
1899cd17cd2STakashi Iwai 		nvol = ucontrol->value.integer.value[0] & 0x7f;
190f6cdab5fSClement Guedez 		if (id < 6)
191f6cdab5fSClement Guedez 			tmp = stac9460_get(ice, idx);
192f6cdab5fSClement Guedez 		else
193f6cdab5fSClement Guedez 			tmp = stac9460_2_get(ice, idx - 6);
194f6cdab5fSClement Guedez 		ovol = 0x7f - (tmp & 0x7f);
195f6cdab5fSClement Guedez 		change = (ovol != nvol);
196f6cdab5fSClement Guedez 		if (change) {
197f6cdab5fSClement Guedez 			if (id < 6)
198f6cdab5fSClement Guedez 				stac9460_put(ice, idx, (0x7f - nvol) |
199f6cdab5fSClement Guedez 							(tmp & 0x80));
200f6cdab5fSClement Guedez 			else
201f6cdab5fSClement Guedez 				stac9460_2_put(ice, idx-6, (0x7f - nvol) |
202f6cdab5fSClement Guedez 							(tmp & 0x80));
203f6cdab5fSClement Guedez 		}
204f6cdab5fSClement Guedez 	}
205f6cdab5fSClement Guedez 	return change;
206f6cdab5fSClement Guedez }
207f6cdab5fSClement Guedez 
208f6cdab5fSClement Guedez /*
209f6cdab5fSClement Guedez  * ADC mute control
210f6cdab5fSClement Guedez  */
211a5ce8890STakashi Iwai #define stac9460_adc_mute_info		snd_ctl_boolean_stereo_info
212f6cdab5fSClement Guedez 
213f6cdab5fSClement Guedez static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
214f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
215f6cdab5fSClement Guedez {
216f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
217f6cdab5fSClement Guedez 	unsigned char val;
218f6cdab5fSClement Guedez 	int i, id;
219f6cdab5fSClement Guedez 
220f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
221f6cdab5fSClement Guedez 	if (id == 0) {
222f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
223f6cdab5fSClement Guedez 			val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
224f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
225f6cdab5fSClement Guedez 		}
226f6cdab5fSClement Guedez 	} else {
227f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
228f6cdab5fSClement Guedez 			val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
229f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
230f6cdab5fSClement Guedez 		}
231f6cdab5fSClement Guedez 	}
232f6cdab5fSClement Guedez 	return 0;
233f6cdab5fSClement Guedez }
234f6cdab5fSClement Guedez 
235f6cdab5fSClement Guedez static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
236f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
237f6cdab5fSClement Guedez {
238f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
239f6cdab5fSClement Guedez 	unsigned char new, old;
240f6cdab5fSClement Guedez 	int i, reg, id;
241f6cdab5fSClement Guedez 	int change;
242f6cdab5fSClement Guedez 
243f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
244f6cdab5fSClement Guedez 	if (id == 0) {
245f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
246f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
247f6cdab5fSClement Guedez 			old = stac9460_get(ice, reg);
248f6cdab5fSClement Guedez 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
249f6cdab5fSClement Guedez 								(old&~0x80);
250f6cdab5fSClement Guedez 			change = (new != old);
251f6cdab5fSClement Guedez 			if (change)
252f6cdab5fSClement Guedez 				stac9460_put(ice, reg, new);
253f6cdab5fSClement Guedez 		}
254f6cdab5fSClement Guedez 	} else {
255f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
256f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
257f6cdab5fSClement Guedez 			old = stac9460_2_get(ice, reg);
258f6cdab5fSClement Guedez 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
259f6cdab5fSClement Guedez 								(old&~0x80);
260f6cdab5fSClement Guedez 			change = (new != old);
261f6cdab5fSClement Guedez 			if (change)
262f6cdab5fSClement Guedez 				stac9460_2_put(ice, reg, new);
263f6cdab5fSClement Guedez 		}
264f6cdab5fSClement Guedez 	}
265f6cdab5fSClement Guedez 	return change;
266f6cdab5fSClement Guedez }
267f6cdab5fSClement Guedez 
268f6cdab5fSClement Guedez /*
269f6cdab5fSClement Guedez  *ADC gain mixer control
270f6cdab5fSClement Guedez  */
271f6cdab5fSClement Guedez static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
272f6cdab5fSClement Guedez 				struct snd_ctl_elem_info *uinfo)
273f6cdab5fSClement Guedez {
274f6cdab5fSClement Guedez 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
275f6cdab5fSClement Guedez 	uinfo->count = 2;
276f6cdab5fSClement Guedez 	uinfo->value.integer.min = 0;		/* 0dB */
277f6cdab5fSClement Guedez 	uinfo->value.integer.max = 0x0f;	/* 22.5dB */
278f6cdab5fSClement Guedez 	return 0;
279f6cdab5fSClement Guedez }
280f6cdab5fSClement Guedez 
281f6cdab5fSClement Guedez static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
282f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
283f6cdab5fSClement Guedez {
284f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
285f6cdab5fSClement Guedez 	int i, reg, id;
286f6cdab5fSClement Guedez 	unsigned char vol;
287f6cdab5fSClement Guedez 
288f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
289f6cdab5fSClement Guedez 	if (id == 0) {
290f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
291f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
292f6cdab5fSClement Guedez 			vol = stac9460_get(ice, reg) & 0x0f;
293f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = 0x0f - vol;
294f6cdab5fSClement Guedez 		}
295f6cdab5fSClement Guedez 	} else {
296f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
297f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
298f6cdab5fSClement Guedez 			vol = stac9460_2_get(ice, reg) & 0x0f;
299f6cdab5fSClement Guedez 			ucontrol->value.integer.value[i] = 0x0f - vol;
300f6cdab5fSClement Guedez 		}
301f6cdab5fSClement Guedez 	}
302f6cdab5fSClement Guedez 	return 0;
303f6cdab5fSClement Guedez }
304f6cdab5fSClement Guedez 
305f6cdab5fSClement Guedez static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
306f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
307f6cdab5fSClement Guedez {
308f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
309f6cdab5fSClement Guedez 	int i, reg, id;
310f6cdab5fSClement Guedez 	unsigned char ovol, nvol;
311f6cdab5fSClement Guedez 	int change;
312f6cdab5fSClement Guedez 
313f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
314f6cdab5fSClement Guedez 	if (id == 0) {
315f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
316f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
3179cd17cd2STakashi Iwai 			nvol = ucontrol->value.integer.value[i] & 0x0f;
318f6cdab5fSClement Guedez 			ovol = 0x0f - stac9460_get(ice, reg);
319f6cdab5fSClement Guedez 			change = ((ovol & 0x0f) != nvol);
320f6cdab5fSClement Guedez 			if (change)
321f6cdab5fSClement Guedez 				stac9460_put(ice, reg, (0x0f - nvol) |
322f6cdab5fSClement Guedez 							(ovol & ~0x0f));
323f6cdab5fSClement Guedez 		}
324f6cdab5fSClement Guedez 	} else {
325f6cdab5fSClement Guedez 		for (i = 0; i < 2; ++i) {
326f6cdab5fSClement Guedez 			reg = STAC946X_MIC_L_VOLUME + i;
3279cd17cd2STakashi Iwai 			nvol = ucontrol->value.integer.value[i] & 0x0f;
328f6cdab5fSClement Guedez 			ovol = 0x0f - stac9460_2_get(ice, reg);
329f6cdab5fSClement Guedez 			change = ((ovol & 0x0f) != nvol);
330f6cdab5fSClement Guedez 			if (change)
331f6cdab5fSClement Guedez 				stac9460_2_put(ice, reg, (0x0f - nvol) |
332f6cdab5fSClement Guedez 							(ovol & ~0x0f));
333f6cdab5fSClement Guedez 		}
334f6cdab5fSClement Guedez 	}
335f6cdab5fSClement Guedez 	return change;
336f6cdab5fSClement Guedez }
337f6cdab5fSClement Guedez 
338f6cdab5fSClement Guedez /*
339f6cdab5fSClement Guedez  * MIC / LINE switch fonction
340f6cdab5fSClement Guedez  */
341f6cdab5fSClement Guedez 
342a5ce8890STakashi Iwai #define stac9460_mic_sw_info		snd_ctl_boolean_mono_info
343f6cdab5fSClement Guedez 
344f6cdab5fSClement Guedez static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
345f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
346f6cdab5fSClement Guedez {
347f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
348f6cdab5fSClement Guedez 	unsigned char val;
349f6cdab5fSClement Guedez 	int id;
350f6cdab5fSClement Guedez 
351f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
352f6cdab5fSClement Guedez 	if (id == 0)
353f6cdab5fSClement Guedez 		val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
354f6cdab5fSClement Guedez 	else
355f6cdab5fSClement Guedez 		val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
356f6cdab5fSClement Guedez 	ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
357f6cdab5fSClement Guedez 	return 0;
358f6cdab5fSClement Guedez }
359f6cdab5fSClement Guedez 
360f6cdab5fSClement Guedez static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
361f6cdab5fSClement Guedez 				struct snd_ctl_elem_value *ucontrol)
362f6cdab5fSClement Guedez {
363f6cdab5fSClement Guedez 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
364f6cdab5fSClement Guedez 	unsigned char new, old;
365f6cdab5fSClement Guedez 	int change, id;
366f6cdab5fSClement Guedez 
367f6cdab5fSClement Guedez 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
368f6cdab5fSClement Guedez 	if (id == 0)
369f6cdab5fSClement Guedez 		old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
370f6cdab5fSClement Guedez 	else
371f6cdab5fSClement Guedez 		old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
372f6cdab5fSClement Guedez 	new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80);
373f6cdab5fSClement Guedez 	change = (new != old);
374f6cdab5fSClement Guedez 	if (change) {
375f6cdab5fSClement Guedez 		if (id == 0)
376f6cdab5fSClement Guedez 			stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
377f6cdab5fSClement Guedez 		else
378f6cdab5fSClement Guedez 			stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
379f6cdab5fSClement Guedez 	}
380f6cdab5fSClement Guedez 	return change;
381f6cdab5fSClement Guedez }
382f6cdab5fSClement Guedez 
383f6cdab5fSClement Guedez /*
384f6cdab5fSClement Guedez  * Control tabs
385f6cdab5fSClement Guedez  */
386e23e7a14SBill Pemberton static struct snd_kcontrol_new stac9640_controls[] = {
387f6cdab5fSClement Guedez 	{
388f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
389f6cdab5fSClement Guedez 		.name = "Master Playback Switch",
390f6cdab5fSClement Guedez 		.info = stac9460_dac_mute_info,
391f6cdab5fSClement Guedez 		.get = stac9460_dac_mute_get,
392f6cdab5fSClement Guedez 		.put = stac9460_dac_mute_put,
393f6cdab5fSClement Guedez 		.private_value = 1
394f6cdab5fSClement Guedez 	},
395f6cdab5fSClement Guedez 	{
396f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
397f6cdab5fSClement Guedez 		.name = "Master Playback Volume",
398f6cdab5fSClement Guedez 		.info = stac9460_dac_vol_info,
399f6cdab5fSClement Guedez 		.get = stac9460_dac_vol_get,
400f6cdab5fSClement Guedez 		.put = stac9460_dac_vol_put,
401f6cdab5fSClement Guedez 		.private_value = 1,
402f6cdab5fSClement Guedez 	},
403f6cdab5fSClement Guedez 	{
404f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
405f6cdab5fSClement Guedez 		.name = "MIC/Line switch",
406f6cdab5fSClement Guedez 		.count = 2,
407f6cdab5fSClement Guedez 		.info = stac9460_mic_sw_info,
408f6cdab5fSClement Guedez 		.get = stac9460_mic_sw_get,
409f6cdab5fSClement Guedez 		.put = stac9460_mic_sw_put,
410f6cdab5fSClement Guedez 
411f6cdab5fSClement Guedez 	},
412f6cdab5fSClement Guedez 	{
413f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
414f6cdab5fSClement Guedez 		.name = "DAC Switch",
415f6cdab5fSClement Guedez 		.count = 8,
416f6cdab5fSClement Guedez 		.info = stac9460_dac_mute_info,
417f6cdab5fSClement Guedez 		.get = stac9460_dac_mute_get,
418f6cdab5fSClement Guedez 		.put = stac9460_dac_mute_put,
419f6cdab5fSClement Guedez 	},
420f6cdab5fSClement Guedez 	{
421f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
422f6cdab5fSClement Guedez 		.name = "DAC Volume",
423f6cdab5fSClement Guedez 		.count = 8,
424f6cdab5fSClement Guedez 		.info = stac9460_dac_vol_info,
425f6cdab5fSClement Guedez 		.get = stac9460_dac_vol_get,
426f6cdab5fSClement Guedez 		.put = stac9460_dac_vol_put,
427f6cdab5fSClement Guedez 	},
428f6cdab5fSClement Guedez 	{
429f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
430f6cdab5fSClement Guedez 		.name = "ADC Switch",
431f6cdab5fSClement Guedez 		.count = 2,
432f6cdab5fSClement Guedez 		.info = stac9460_adc_mute_info,
433f6cdab5fSClement Guedez 		.get = stac9460_adc_mute_get,
434f6cdab5fSClement Guedez 		.put = stac9460_adc_mute_put,
435f6cdab5fSClement Guedez 	},
436f6cdab5fSClement Guedez 	{
437f6cdab5fSClement Guedez 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
438f6cdab5fSClement Guedez 		.name = "ADC Volume",
439f6cdab5fSClement Guedez 		.count = 2,
440f6cdab5fSClement Guedez 		.info = stac9460_adc_vol_info,
441f6cdab5fSClement Guedez 		.get = stac9460_adc_vol_get,
442f6cdab5fSClement Guedez 		.put = stac9460_adc_vol_put,
443f6cdab5fSClement Guedez 
444f6cdab5fSClement Guedez 	}
445f6cdab5fSClement Guedez };
446f6cdab5fSClement Guedez 
447f6cdab5fSClement Guedez 
448f6cdab5fSClement Guedez 
449f6cdab5fSClement Guedez /*INIT*/
450e23e7a14SBill Pemberton static int wtm_add_controls(struct snd_ice1712 *ice)
451f6cdab5fSClement Guedez {
452f6cdab5fSClement Guedez 	unsigned int i;
453f6cdab5fSClement Guedez 	int err;
454f6cdab5fSClement Guedez 
455f6cdab5fSClement Guedez 	for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
456f6cdab5fSClement Guedez 		err = snd_ctl_add(ice->card,
457f6cdab5fSClement Guedez 				snd_ctl_new1(&stac9640_controls[i], ice));
458f6cdab5fSClement Guedez 		if (err < 0)
459f6cdab5fSClement Guedez 			return err;
460f6cdab5fSClement Guedez 	}
461f6cdab5fSClement Guedez 	return 0;
462f6cdab5fSClement Guedez }
463f6cdab5fSClement Guedez 
464e23e7a14SBill Pemberton static int wtm_init(struct snd_ice1712 *ice)
465f6cdab5fSClement Guedez {
466b56df151SClément Guedez 	static unsigned short stac_inits_wtm[] = {
467f6cdab5fSClement Guedez 		STAC946X_RESET, 0,
468f6cdab5fSClement Guedez 		(unsigned short)-1
469f6cdab5fSClement Guedez 	};
470f6cdab5fSClement Guedez 	unsigned short *p;
471f6cdab5fSClement Guedez 
472f6cdab5fSClement Guedez 	/*WTM 192M*/
473f6cdab5fSClement Guedez 	ice->num_total_dacs = 8;
474f6cdab5fSClement Guedez 	ice->num_total_adcs = 4;
475f6cdab5fSClement Guedez 	ice->force_rdma1 = 1;
476f6cdab5fSClement Guedez 
477f6cdab5fSClement Guedez 	/*initialize codec*/
478b56df151SClément Guedez 	p = stac_inits_wtm;
479f6cdab5fSClement Guedez 	for (; *p != (unsigned short)-1; p += 2) {
480f6cdab5fSClement Guedez 		stac9460_put(ice, p[0], p[1]);
481f6cdab5fSClement Guedez 		stac9460_2_put(ice, p[0], p[1]);
482f6cdab5fSClement Guedez 	}
483f6cdab5fSClement Guedez 	return 0;
484f6cdab5fSClement Guedez }
485f6cdab5fSClement Guedez 
486f6cdab5fSClement Guedez 
487e23e7a14SBill Pemberton static unsigned char wtm_eeprom[] = {
488*f8a8b3a8SClément Guedez 	[ICE_EEP2_SYSCONF]      = 0x67, /*SYSCONF: clock 192KHz, mpu401,
489*f8a8b3a8SClément Guedez 							4ADC, 8DAC */
4907127744aSClément Guedez 	[ICE_EEP2_ACLINK]       = 0x80, /* ACLINK : I2S */
4917127744aSClément Guedez 	[ICE_EEP2_I2S]          = 0xf8, /* I2S: vol; 96k, 24bit, 192k */
4927127744aSClément Guedez 	[ICE_EEP2_SPDIF]        = 0xc1, /*SPDIF: out-en, spidf ext out*/
4937127744aSClément Guedez 	[ICE_EEP2_GPIO_DIR]     = 0x9f,
4947127744aSClément Guedez 	[ICE_EEP2_GPIO_DIR1]    = 0xff,
4957127744aSClément Guedez 	[ICE_EEP2_GPIO_DIR2]    = 0x7f,
4967127744aSClément Guedez 	[ICE_EEP2_GPIO_MASK]    = 0x9f,
4977127744aSClément Guedez 	[ICE_EEP2_GPIO_MASK1]   = 0xff,
4987127744aSClément Guedez 	[ICE_EEP2_GPIO_MASK2]   = 0x7f,
4997127744aSClément Guedez 	[ICE_EEP2_GPIO_STATE]   = 0x16,
5007127744aSClément Guedez 	[ICE_EEP2_GPIO_STATE1]  = 0x80,
5017127744aSClément Guedez 	[ICE_EEP2_GPIO_STATE2]  = 0x00,
502f6cdab5fSClement Guedez };
503f6cdab5fSClement Guedez 
504f6cdab5fSClement Guedez 
505f6cdab5fSClement Guedez /*entry point*/
506e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
507f6cdab5fSClement Guedez 	{
508f6cdab5fSClement Guedez 		.subvendor = VT1724_SUBDEVICE_WTM,
509f6cdab5fSClement Guedez 		.name = "ESI Waveterminal 192M",
510f6cdab5fSClement Guedez 		.model = "WT192M",
511f6cdab5fSClement Guedez 		.chip_init = wtm_init,
512f6cdab5fSClement Guedez 		.build_controls = wtm_add_controls,
513f6cdab5fSClement Guedez 		.eeprom_size = sizeof(wtm_eeprom),
514f6cdab5fSClement Guedez 		.eeprom_data = wtm_eeprom,
515f6cdab5fSClement Guedez 	},
516f6cdab5fSClement Guedez 	{} /*terminator*/
517f6cdab5fSClement Guedez };
518