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