xref: /OK3568_Linux_fs/kernel/sound/pci/ice1712/wtm.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 Ego Sys Waveterminal 192M
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *		Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
8*4882a593Smuzhiyun  *		Some functions are taken from the Prodigy192 driver
9*4882a593Smuzhiyun  *		source
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <sound/core.h>
18*4882a593Smuzhiyun #include <sound/tlv.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include "ice1712.h"
22*4882a593Smuzhiyun #include "envy24ht.h"
23*4882a593Smuzhiyun #include "wtm.h"
24*4882a593Smuzhiyun #include "stac946x.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun struct wtm_spec {
27*4882a593Smuzhiyun 	/* rate change needs atomic mute/unmute of all dacs*/
28*4882a593Smuzhiyun 	struct mutex mute_mutex;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun  *	2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
34*4882a593Smuzhiyun  */
stac9460_put(struct snd_ice1712 * ice,int reg,unsigned char val)35*4882a593Smuzhiyun static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
36*4882a593Smuzhiyun 						unsigned char val)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
stac9460_get(struct snd_ice1712 * ice,int reg)41*4882a593Smuzhiyun static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun  *	2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
48*4882a593Smuzhiyun  */
stac9460_2_put(struct snd_ice1712 * ice,int reg,unsigned char val)49*4882a593Smuzhiyun static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
50*4882a593Smuzhiyun 						unsigned char val)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
stac9460_2_get(struct snd_ice1712 * ice,int reg)55*4882a593Smuzhiyun static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun  *	DAC mute control
63*4882a593Smuzhiyun  */
stac9460_dac_mute_all(struct snd_ice1712 * ice,unsigned char mute,unsigned short int * change_mask)64*4882a593Smuzhiyun static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute,
65*4882a593Smuzhiyun 				unsigned short int *change_mask)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	unsigned char new, old;
68*4882a593Smuzhiyun 	int id, idx, change;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/*stac9460 1*/
71*4882a593Smuzhiyun 	for (id = 0; id < 7; id++) {
72*4882a593Smuzhiyun 		if (*change_mask & (0x01 << id)) {
73*4882a593Smuzhiyun 			if (id == 0)
74*4882a593Smuzhiyun 				idx = STAC946X_MASTER_VOLUME;
75*4882a593Smuzhiyun 			else
76*4882a593Smuzhiyun 				idx = STAC946X_LF_VOLUME - 1 + id;
77*4882a593Smuzhiyun 			old = stac9460_get(ice, idx);
78*4882a593Smuzhiyun 			new = (~mute << 7 & 0x80) | (old & ~0x80);
79*4882a593Smuzhiyun 			change = (new != old);
80*4882a593Smuzhiyun 			if (change) {
81*4882a593Smuzhiyun 				stac9460_put(ice, idx, new);
82*4882a593Smuzhiyun 				*change_mask = *change_mask | (0x01 << id);
83*4882a593Smuzhiyun 			} else {
84*4882a593Smuzhiyun 				*change_mask = *change_mask & ~(0x01 << id);
85*4882a593Smuzhiyun 			}
86*4882a593Smuzhiyun 		}
87*4882a593Smuzhiyun 	}
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	/*stac9460 2*/
90*4882a593Smuzhiyun 	for (id = 0; id < 3; id++) {
91*4882a593Smuzhiyun 		if (*change_mask & (0x01 << (id + 7))) {
92*4882a593Smuzhiyun 			if (id == 0)
93*4882a593Smuzhiyun 				idx = STAC946X_MASTER_VOLUME;
94*4882a593Smuzhiyun 			else
95*4882a593Smuzhiyun 				idx = STAC946X_LF_VOLUME - 1 + id;
96*4882a593Smuzhiyun 			old = stac9460_2_get(ice, idx);
97*4882a593Smuzhiyun 			new = (~mute << 7 & 0x80) | (old & ~0x80);
98*4882a593Smuzhiyun 			change = (new != old);
99*4882a593Smuzhiyun 			if (change) {
100*4882a593Smuzhiyun 				stac9460_2_put(ice, idx, new);
101*4882a593Smuzhiyun 				*change_mask = *change_mask | (0x01 << id);
102*4882a593Smuzhiyun 			} else {
103*4882a593Smuzhiyun 				*change_mask = *change_mask & ~(0x01 << id);
104*4882a593Smuzhiyun 			}
105*4882a593Smuzhiyun 		}
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define stac9460_dac_mute_info		snd_ctl_boolean_mono_info
112*4882a593Smuzhiyun 
stac9460_dac_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)113*4882a593Smuzhiyun static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
114*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
117*4882a593Smuzhiyun 	struct wtm_spec *spec = ice->spec;
118*4882a593Smuzhiyun 	unsigned char val;
119*4882a593Smuzhiyun 	int idx, id;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	mutex_lock(&spec->mute_mutex);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	if (kcontrol->private_value) {
124*4882a593Smuzhiyun 		idx = STAC946X_MASTER_VOLUME;
125*4882a593Smuzhiyun 		id = 0;
126*4882a593Smuzhiyun 	} else {
127*4882a593Smuzhiyun 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
128*4882a593Smuzhiyun 		idx = id + STAC946X_LF_VOLUME;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 	if (id < 6)
131*4882a593Smuzhiyun 		val = stac9460_get(ice, idx);
132*4882a593Smuzhiyun 	else
133*4882a593Smuzhiyun 		val = stac9460_2_get(ice, idx - 6);
134*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	mutex_unlock(&spec->mute_mutex);
137*4882a593Smuzhiyun 	return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
stac9460_dac_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)140*4882a593Smuzhiyun static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
141*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
144*4882a593Smuzhiyun 	unsigned char new, old;
145*4882a593Smuzhiyun 	int id, idx;
146*4882a593Smuzhiyun 	int change;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (kcontrol->private_value) {
149*4882a593Smuzhiyun 		idx = STAC946X_MASTER_VOLUME;
150*4882a593Smuzhiyun 		old = stac9460_get(ice, idx);
151*4882a593Smuzhiyun 		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
152*4882a593Smuzhiyun 							(old & ~0x80);
153*4882a593Smuzhiyun 		change = (new != old);
154*4882a593Smuzhiyun 		if (change) {
155*4882a593Smuzhiyun 			stac9460_put(ice, idx, new);
156*4882a593Smuzhiyun 			stac9460_2_put(ice, idx, new);
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 	} else {
159*4882a593Smuzhiyun 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
160*4882a593Smuzhiyun 		idx = id + STAC946X_LF_VOLUME;
161*4882a593Smuzhiyun 		if (id < 6)
162*4882a593Smuzhiyun 			old = stac9460_get(ice, idx);
163*4882a593Smuzhiyun 		else
164*4882a593Smuzhiyun 			old = stac9460_2_get(ice, idx - 6);
165*4882a593Smuzhiyun 		new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
166*4882a593Smuzhiyun 							(old & ~0x80);
167*4882a593Smuzhiyun 		change = (new != old);
168*4882a593Smuzhiyun 		if (change) {
169*4882a593Smuzhiyun 			if (id < 6)
170*4882a593Smuzhiyun 				stac9460_put(ice, idx, new);
171*4882a593Smuzhiyun 			else
172*4882a593Smuzhiyun 				stac9460_2_put(ice, idx - 6, new);
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	return change;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun /*
179*4882a593Smuzhiyun  * 	DAC volume attenuation mixer control
180*4882a593Smuzhiyun  */
stac9460_dac_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)181*4882a593Smuzhiyun static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
182*4882a593Smuzhiyun 				struct snd_ctl_elem_info *uinfo)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
185*4882a593Smuzhiyun 	uinfo->count = 1;
186*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;			/* mute */
187*4882a593Smuzhiyun 	uinfo->value.integer.max = 0x7f;		/* 0dB */
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
stac9460_dac_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)191*4882a593Smuzhiyun static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
192*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
195*4882a593Smuzhiyun 	int idx, id;
196*4882a593Smuzhiyun 	unsigned char vol;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (kcontrol->private_value) {
199*4882a593Smuzhiyun 		idx = STAC946X_MASTER_VOLUME;
200*4882a593Smuzhiyun 		id = 0;
201*4882a593Smuzhiyun 	} else {
202*4882a593Smuzhiyun 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
203*4882a593Smuzhiyun 		idx = id + STAC946X_LF_VOLUME;
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun 	if (id < 6)
206*4882a593Smuzhiyun 		vol = stac9460_get(ice, idx) & 0x7f;
207*4882a593Smuzhiyun 	else
208*4882a593Smuzhiyun 		vol = stac9460_2_get(ice, idx - 6) & 0x7f;
209*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = 0x7f - vol;
210*4882a593Smuzhiyun 	return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
stac9460_dac_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)213*4882a593Smuzhiyun static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
214*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
217*4882a593Smuzhiyun 	int idx, id;
218*4882a593Smuzhiyun 	unsigned char tmp, ovol, nvol;
219*4882a593Smuzhiyun 	int change;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (kcontrol->private_value) {
222*4882a593Smuzhiyun 		idx = STAC946X_MASTER_VOLUME;
223*4882a593Smuzhiyun 		nvol = ucontrol->value.integer.value[0] & 0x7f;
224*4882a593Smuzhiyun 		tmp = stac9460_get(ice, idx);
225*4882a593Smuzhiyun 		ovol = 0x7f - (tmp & 0x7f);
226*4882a593Smuzhiyun 		change = (ovol != nvol);
227*4882a593Smuzhiyun 		if (change) {
228*4882a593Smuzhiyun 			stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
229*4882a593Smuzhiyun 			stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
230*4882a593Smuzhiyun 		}
231*4882a593Smuzhiyun 	} else {
232*4882a593Smuzhiyun 		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
233*4882a593Smuzhiyun 		idx = id + STAC946X_LF_VOLUME;
234*4882a593Smuzhiyun 		nvol = ucontrol->value.integer.value[0] & 0x7f;
235*4882a593Smuzhiyun 		if (id < 6)
236*4882a593Smuzhiyun 			tmp = stac9460_get(ice, idx);
237*4882a593Smuzhiyun 		else
238*4882a593Smuzhiyun 			tmp = stac9460_2_get(ice, idx - 6);
239*4882a593Smuzhiyun 		ovol = 0x7f - (tmp & 0x7f);
240*4882a593Smuzhiyun 		change = (ovol != nvol);
241*4882a593Smuzhiyun 		if (change) {
242*4882a593Smuzhiyun 			if (id < 6)
243*4882a593Smuzhiyun 				stac9460_put(ice, idx, (0x7f - nvol) |
244*4882a593Smuzhiyun 							(tmp & 0x80));
245*4882a593Smuzhiyun 			else
246*4882a593Smuzhiyun 				stac9460_2_put(ice, idx-6, (0x7f - nvol) |
247*4882a593Smuzhiyun 							(tmp & 0x80));
248*4882a593Smuzhiyun 		}
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 	return change;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun  * ADC mute control
255*4882a593Smuzhiyun  */
256*4882a593Smuzhiyun #define stac9460_adc_mute_info		snd_ctl_boolean_stereo_info
257*4882a593Smuzhiyun 
stac9460_adc_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)258*4882a593Smuzhiyun static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
259*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
262*4882a593Smuzhiyun 	unsigned char val;
263*4882a593Smuzhiyun 	int i, id;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
266*4882a593Smuzhiyun 	if (id == 0) {
267*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
268*4882a593Smuzhiyun 			val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
269*4882a593Smuzhiyun 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
270*4882a593Smuzhiyun 		}
271*4882a593Smuzhiyun 	} else {
272*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
273*4882a593Smuzhiyun 			val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
274*4882a593Smuzhiyun 			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
275*4882a593Smuzhiyun 		}
276*4882a593Smuzhiyun 	}
277*4882a593Smuzhiyun 	return 0;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
stac9460_adc_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)280*4882a593Smuzhiyun static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
281*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
284*4882a593Smuzhiyun 	unsigned char new, old;
285*4882a593Smuzhiyun 	int i, reg, id;
286*4882a593Smuzhiyun 	int change;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
289*4882a593Smuzhiyun 	if (id == 0) {
290*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
291*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
292*4882a593Smuzhiyun 			old = stac9460_get(ice, reg);
293*4882a593Smuzhiyun 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
294*4882a593Smuzhiyun 								(old&~0x80);
295*4882a593Smuzhiyun 			change = (new != old);
296*4882a593Smuzhiyun 			if (change)
297*4882a593Smuzhiyun 				stac9460_put(ice, reg, new);
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 	} else {
300*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
301*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
302*4882a593Smuzhiyun 			old = stac9460_2_get(ice, reg);
303*4882a593Smuzhiyun 			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
304*4882a593Smuzhiyun 								(old&~0x80);
305*4882a593Smuzhiyun 			change = (new != old);
306*4882a593Smuzhiyun 			if (change)
307*4882a593Smuzhiyun 				stac9460_2_put(ice, reg, new);
308*4882a593Smuzhiyun 		}
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 	return change;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun /*
314*4882a593Smuzhiyun  *ADC gain mixer control
315*4882a593Smuzhiyun  */
stac9460_adc_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)316*4882a593Smuzhiyun static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
317*4882a593Smuzhiyun 				struct snd_ctl_elem_info *uinfo)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
320*4882a593Smuzhiyun 	uinfo->count = 2;
321*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;		/* 0dB */
322*4882a593Smuzhiyun 	uinfo->value.integer.max = 0x0f;	/* 22.5dB */
323*4882a593Smuzhiyun 	return 0;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
stac9460_adc_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)326*4882a593Smuzhiyun static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
327*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
330*4882a593Smuzhiyun 	int i, reg, id;
331*4882a593Smuzhiyun 	unsigned char vol;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
334*4882a593Smuzhiyun 	if (id == 0) {
335*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
336*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
337*4882a593Smuzhiyun 			vol = stac9460_get(ice, reg) & 0x0f;
338*4882a593Smuzhiyun 			ucontrol->value.integer.value[i] = 0x0f - vol;
339*4882a593Smuzhiyun 		}
340*4882a593Smuzhiyun 	} else {
341*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
342*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
343*4882a593Smuzhiyun 			vol = stac9460_2_get(ice, reg) & 0x0f;
344*4882a593Smuzhiyun 			ucontrol->value.integer.value[i] = 0x0f - vol;
345*4882a593Smuzhiyun 		}
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 	return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
stac9460_adc_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)350*4882a593Smuzhiyun static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
351*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
354*4882a593Smuzhiyun 	int i, reg, id;
355*4882a593Smuzhiyun 	unsigned char ovol, nvol;
356*4882a593Smuzhiyun 	int change;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
359*4882a593Smuzhiyun 	if (id == 0) {
360*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
361*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
362*4882a593Smuzhiyun 			nvol = ucontrol->value.integer.value[i] & 0x0f;
363*4882a593Smuzhiyun 			ovol = 0x0f - stac9460_get(ice, reg);
364*4882a593Smuzhiyun 			change = ((ovol & 0x0f) != nvol);
365*4882a593Smuzhiyun 			if (change)
366*4882a593Smuzhiyun 				stac9460_put(ice, reg, (0x0f - nvol) |
367*4882a593Smuzhiyun 							(ovol & ~0x0f));
368*4882a593Smuzhiyun 		}
369*4882a593Smuzhiyun 	} else {
370*4882a593Smuzhiyun 		for (i = 0; i < 2; ++i) {
371*4882a593Smuzhiyun 			reg = STAC946X_MIC_L_VOLUME + i;
372*4882a593Smuzhiyun 			nvol = ucontrol->value.integer.value[i] & 0x0f;
373*4882a593Smuzhiyun 			ovol = 0x0f - stac9460_2_get(ice, reg);
374*4882a593Smuzhiyun 			change = ((ovol & 0x0f) != nvol);
375*4882a593Smuzhiyun 			if (change)
376*4882a593Smuzhiyun 				stac9460_2_put(ice, reg, (0x0f - nvol) |
377*4882a593Smuzhiyun 							(ovol & ~0x0f));
378*4882a593Smuzhiyun 		}
379*4882a593Smuzhiyun 	}
380*4882a593Smuzhiyun 	return change;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun /*
384*4882a593Smuzhiyun  * MIC / LINE switch fonction
385*4882a593Smuzhiyun  */
stac9460_mic_sw_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)386*4882a593Smuzhiyun static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
387*4882a593Smuzhiyun 				struct snd_ctl_elem_info *uinfo)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	static const char * const texts[2] = { "Line In", "Mic" };
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	return snd_ctl_enum_info(uinfo, 1, 2, texts);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 
stac9460_mic_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)395*4882a593Smuzhiyun static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
396*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
399*4882a593Smuzhiyun 	unsigned char val;
400*4882a593Smuzhiyun 	int id;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
403*4882a593Smuzhiyun 	if (id == 0)
404*4882a593Smuzhiyun 		val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
405*4882a593Smuzhiyun 	else
406*4882a593Smuzhiyun 		val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
407*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
408*4882a593Smuzhiyun 	return 0;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
stac9460_mic_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)411*4882a593Smuzhiyun static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
412*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
415*4882a593Smuzhiyun 	unsigned char new, old;
416*4882a593Smuzhiyun 	int change, id;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
419*4882a593Smuzhiyun 	if (id == 0)
420*4882a593Smuzhiyun 		old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
421*4882a593Smuzhiyun 	else
422*4882a593Smuzhiyun 		old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
423*4882a593Smuzhiyun 	new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
424*4882a593Smuzhiyun 	change = (new != old);
425*4882a593Smuzhiyun 	if (change) {
426*4882a593Smuzhiyun 		if (id == 0)
427*4882a593Smuzhiyun 			stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
428*4882a593Smuzhiyun 		else
429*4882a593Smuzhiyun 			stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 	return change;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun /*
436*4882a593Smuzhiyun  * Handler for setting correct codec rate - called when rate change is detected
437*4882a593Smuzhiyun  */
stac9460_set_rate_val(struct snd_ice1712 * ice,unsigned int rate)438*4882a593Smuzhiyun static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	unsigned char old, new;
441*4882a593Smuzhiyun 	unsigned short int changed;
442*4882a593Smuzhiyun 	struct wtm_spec *spec = ice->spec;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
445*4882a593Smuzhiyun 		return;
446*4882a593Smuzhiyun 	else if (rate <= 48000)
447*4882a593Smuzhiyun 		new = 0x08;     /* 256x, base rate mode */
448*4882a593Smuzhiyun 	else if (rate <= 96000)
449*4882a593Smuzhiyun 		new = 0x11;     /* 256x, mid rate mode */
450*4882a593Smuzhiyun 	else
451*4882a593Smuzhiyun 		new = 0x12;     /* 128x, high rate mode */
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);
454*4882a593Smuzhiyun 	if (old == new)
455*4882a593Smuzhiyun 		return;
456*4882a593Smuzhiyun 	/* change detected, setting master clock, muting first */
457*4882a593Smuzhiyun 	/* due to possible conflicts with mute controls - mutexing */
458*4882a593Smuzhiyun 	mutex_lock(&spec->mute_mutex);
459*4882a593Smuzhiyun 	/* we have to remember current mute status for each DAC */
460*4882a593Smuzhiyun 	changed = 0xFFFF;
461*4882a593Smuzhiyun 	stac9460_dac_mute_all(ice, 0, &changed);
462*4882a593Smuzhiyun 	/*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
463*4882a593Smuzhiyun 	stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
464*4882a593Smuzhiyun 	stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new);
465*4882a593Smuzhiyun 	udelay(10);
466*4882a593Smuzhiyun 	/* unmuting - only originally unmuted dacs -
467*4882a593Smuzhiyun 	* i.e. those changed when muting */
468*4882a593Smuzhiyun 	stac9460_dac_mute_all(ice, 1, &changed);
469*4882a593Smuzhiyun 	mutex_unlock(&spec->mute_mutex);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun /*Limits value in dB for fader*/
474*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
475*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun /*
478*4882a593Smuzhiyun  * Control tabs
479*4882a593Smuzhiyun  */
480*4882a593Smuzhiyun static const struct snd_kcontrol_new stac9640_controls[] = {
481*4882a593Smuzhiyun 	{
482*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
483*4882a593Smuzhiyun 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
484*4882a593Smuzhiyun 			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),
485*4882a593Smuzhiyun 		.name = "Master Playback Switch",
486*4882a593Smuzhiyun 		.info = stac9460_dac_mute_info,
487*4882a593Smuzhiyun 		.get = stac9460_dac_mute_get,
488*4882a593Smuzhiyun 		.put = stac9460_dac_mute_put,
489*4882a593Smuzhiyun 		.private_value = 1,
490*4882a593Smuzhiyun 		.tlv = { .p = db_scale_dac }
491*4882a593Smuzhiyun 	},
492*4882a593Smuzhiyun 	{
493*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494*4882a593Smuzhiyun 		.name = "Master Playback Volume",
495*4882a593Smuzhiyun 		.info = stac9460_dac_vol_info,
496*4882a593Smuzhiyun 		.get = stac9460_dac_vol_get,
497*4882a593Smuzhiyun 		.put = stac9460_dac_vol_put,
498*4882a593Smuzhiyun 		.private_value = 1,
499*4882a593Smuzhiyun 	},
500*4882a593Smuzhiyun 	{
501*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
502*4882a593Smuzhiyun 		.name = "MIC/Line Input Enum",
503*4882a593Smuzhiyun 		.count = 2,
504*4882a593Smuzhiyun 		.info = stac9460_mic_sw_info,
505*4882a593Smuzhiyun 		.get = stac9460_mic_sw_get,
506*4882a593Smuzhiyun 		.put = stac9460_mic_sw_put,
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	},
509*4882a593Smuzhiyun 	{
510*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
511*4882a593Smuzhiyun 		.name = "DAC Switch",
512*4882a593Smuzhiyun 		.count = 8,
513*4882a593Smuzhiyun 		.info = stac9460_dac_mute_info,
514*4882a593Smuzhiyun 		.get = stac9460_dac_mute_get,
515*4882a593Smuzhiyun 		.put = stac9460_dac_mute_put,
516*4882a593Smuzhiyun 	},
517*4882a593Smuzhiyun 	{
518*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
519*4882a593Smuzhiyun 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
520*4882a593Smuzhiyun 			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 		.name = "DAC Volume",
523*4882a593Smuzhiyun 		.count = 8,
524*4882a593Smuzhiyun 		.info = stac9460_dac_vol_info,
525*4882a593Smuzhiyun 		.get = stac9460_dac_vol_get,
526*4882a593Smuzhiyun 		.put = stac9460_dac_vol_put,
527*4882a593Smuzhiyun 		.tlv = { .p = db_scale_dac }
528*4882a593Smuzhiyun 	},
529*4882a593Smuzhiyun 	{
530*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
531*4882a593Smuzhiyun 		.name = "ADC Switch",
532*4882a593Smuzhiyun 		.count = 2,
533*4882a593Smuzhiyun 		.info = stac9460_adc_mute_info,
534*4882a593Smuzhiyun 		.get = stac9460_adc_mute_get,
535*4882a593Smuzhiyun 		.put = stac9460_adc_mute_put,
536*4882a593Smuzhiyun 	},
537*4882a593Smuzhiyun 	{
538*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
539*4882a593Smuzhiyun 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
540*4882a593Smuzhiyun 			    SNDRV_CTL_ELEM_ACCESS_TLV_READ),
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 		.name = "ADC Volume",
543*4882a593Smuzhiyun 		.count = 2,
544*4882a593Smuzhiyun 		.info = stac9460_adc_vol_info,
545*4882a593Smuzhiyun 		.get = stac9460_adc_vol_get,
546*4882a593Smuzhiyun 		.put = stac9460_adc_vol_put,
547*4882a593Smuzhiyun 		.tlv = { .p = db_scale_adc }
548*4882a593Smuzhiyun 	}
549*4882a593Smuzhiyun };
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun /*INIT*/
wtm_add_controls(struct snd_ice1712 * ice)554*4882a593Smuzhiyun static int wtm_add_controls(struct snd_ice1712 *ice)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	unsigned int i;
557*4882a593Smuzhiyun 	int err;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
560*4882a593Smuzhiyun 		err = snd_ctl_add(ice->card,
561*4882a593Smuzhiyun 				snd_ctl_new1(&stac9640_controls[i], ice));
562*4882a593Smuzhiyun 		if (err < 0)
563*4882a593Smuzhiyun 			return err;
564*4882a593Smuzhiyun 	}
565*4882a593Smuzhiyun 	return 0;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
wtm_init(struct snd_ice1712 * ice)568*4882a593Smuzhiyun static int wtm_init(struct snd_ice1712 *ice)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	static const unsigned short stac_inits_wtm[] = {
571*4882a593Smuzhiyun 		STAC946X_RESET, 0,
572*4882a593Smuzhiyun 		STAC946X_MASTER_CLOCKING, 0x11,
573*4882a593Smuzhiyun 		(unsigned short)-1
574*4882a593Smuzhiyun 	};
575*4882a593Smuzhiyun 	const unsigned short *p;
576*4882a593Smuzhiyun 	struct wtm_spec *spec;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	/*WTM 192M*/
579*4882a593Smuzhiyun 	ice->num_total_dacs = 8;
580*4882a593Smuzhiyun 	ice->num_total_adcs = 4;
581*4882a593Smuzhiyun 	ice->force_rdma1 = 1;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	/*init mutex for dac mute conflict*/
584*4882a593Smuzhiyun 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
585*4882a593Smuzhiyun 	if (!spec)
586*4882a593Smuzhiyun 		return -ENOMEM;
587*4882a593Smuzhiyun 	ice->spec = spec;
588*4882a593Smuzhiyun 	mutex_init(&spec->mute_mutex);
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	/*initialize codec*/
592*4882a593Smuzhiyun 	p = stac_inits_wtm;
593*4882a593Smuzhiyun 	for (; *p != (unsigned short)-1; p += 2) {
594*4882a593Smuzhiyun 		stac9460_put(ice, p[0], p[1]);
595*4882a593Smuzhiyun 		stac9460_2_put(ice, p[0], p[1]);
596*4882a593Smuzhiyun 	}
597*4882a593Smuzhiyun 	ice->gpio.set_pro_rate = stac9460_set_rate_val;
598*4882a593Smuzhiyun 	return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun static const unsigned char wtm_eeprom[] = {
603*4882a593Smuzhiyun 	[ICE_EEP2_SYSCONF]      = 0x67, /*SYSCONF: clock 192KHz, mpu401,
604*4882a593Smuzhiyun 							4ADC, 8DAC */
605*4882a593Smuzhiyun 	[ICE_EEP2_ACLINK]       = 0x80, /* ACLINK : I2S */
606*4882a593Smuzhiyun 	[ICE_EEP2_I2S]          = 0xf8, /* I2S: vol; 96k, 24bit, 192k */
607*4882a593Smuzhiyun 	[ICE_EEP2_SPDIF]        = 0xc1, /*SPDIF: out-en, spidf ext out*/
608*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_DIR]     = 0x9f,
609*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_DIR1]    = 0xff,
610*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_DIR2]    = 0x7f,
611*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_MASK]    = 0x9f,
612*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_MASK1]   = 0xff,
613*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_MASK2]   = 0x7f,
614*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_STATE]   = 0x16,
615*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_STATE1]  = 0x80,
616*4882a593Smuzhiyun 	[ICE_EEP2_GPIO_STATE2]  = 0x00,
617*4882a593Smuzhiyun };
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun /*entry point*/
621*4882a593Smuzhiyun struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
622*4882a593Smuzhiyun 	{
623*4882a593Smuzhiyun 		.subvendor = VT1724_SUBDEVICE_WTM,
624*4882a593Smuzhiyun 		.name = "ESI Waveterminal 192M",
625*4882a593Smuzhiyun 		.model = "WT192M",
626*4882a593Smuzhiyun 		.chip_init = wtm_init,
627*4882a593Smuzhiyun 		.build_controls = wtm_add_controls,
628*4882a593Smuzhiyun 		.eeprom_size = sizeof(wtm_eeprom),
629*4882a593Smuzhiyun 		.eeprom_data = wtm_eeprom,
630*4882a593Smuzhiyun 	},
631*4882a593Smuzhiyun 	{} /*terminator*/
632*4882a593Smuzhiyun };
633