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