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