• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/sound/pci/ice1712/
1/*
2 *   ALSA driver for ICEnsemble ICE1724 (Envy24)
3 *
4 *   Lowlevel functions for Terratec PHASE 22
5 *
6 *	Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
7 *
8 *   This program is free software; you can redistribute it and/or modify
9 *   it under the terms of the GNU General Public License as published by
10 *   the Free Software Foundation; either version 2 of the License, or
11 *   (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 *
22 */
23
24/* PHASE 22 overview:
25 *   Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out)
26 *   Analog chip: AK4524 (partially via Philip's 74HCT125)
27 *   Digital receiver: CS8414-CS (supported in this release)
28 *		PHASE 22 revision 2.0 and Terrasoniq/Musonik TS22PCI have CS8416
29 *		(support status unknown, please test and report)
30 *
31 *   Envy connects to AK4524
32 *	- CS directly from GPIO 10
33 *	- CCLK via 74HCT125's gate #4 from GPIO 4
34 *	- CDTI via 74HCT125's gate #2 from GPIO 5
35 *		CDTI may be completely blocked by 74HCT125's gate #1
36 *		controlled by GPIO 3
37 */
38
39/* PHASE 28 overview:
40 *   Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
41 *   Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
42 *   Digital receiver: CS8414-CS (supported in this release)
43 */
44
45#include <asm/io.h>
46#include <linux/delay.h>
47#include <linux/interrupt.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/mutex.h>
51
52#include <sound/core.h>
53
54#include "ice1712.h"
55#include "envy24ht.h"
56#include "phase.h"
57#include <sound/tlv.h>
58
59/* AC97 register cache for Phase28 */
60struct phase28_spec {
61	unsigned short master[2];
62	unsigned short vol[8];
63};
64
65/* WM8770 registers */
66#define WM_DAC_ATTEN		0x00	/* DAC1-8 analog attenuation */
67#define WM_DAC_MASTER_ATTEN	0x08	/* DAC master analog attenuation */
68#define WM_DAC_DIG_ATTEN	0x09	/* DAC1-8 digital attenuation */
69#define WM_DAC_DIG_MASTER_ATTEN	0x11	/* DAC master digital attenuation */
70#define WM_PHASE_SWAP		0x12	/* DAC phase */
71#define WM_DAC_CTRL1		0x13	/* DAC control bits */
72#define WM_MUTE			0x14	/* mute controls */
73#define WM_DAC_CTRL2		0x15	/* de-emphasis and zefo-flag */
74#define WM_INT_CTRL		0x16	/* interface control */
75#define WM_MASTER		0x17	/* master clock and mode */
76#define WM_POWERDOWN		0x18	/* power-down controls */
77#define WM_ADC_GAIN		0x19	/* ADC gain L(19)/R(1a) */
78#define WM_ADC_MUX		0x1b	/* input MUX */
79#define WM_OUT_MUX1		0x1c	/* output MUX */
80#define WM_OUT_MUX2		0x1e	/* output MUX */
81#define WM_RESET		0x1f	/* software reset */
82
83
84/*
85 * Logarithmic volume values for WM8770
86 * Computed as 20 * Log10(255 / x)
87 */
88static const unsigned char wm_vol[256] = {
89	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24,
90	24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18,
91	17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14,
92	14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
93	11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9,
94	9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
95	7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
96	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
97	4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
98	3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
99	2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
100	1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
101};
102
103#define WM_VOL_MAX	(sizeof(wm_vol) - 1)
104#define WM_VOL_MUTE	0x8000
105
106static struct snd_akm4xxx akm_phase22 __devinitdata = {
107	.type = SND_AK4524,
108	.num_dacs = 2,
109	.num_adcs = 2,
110};
111
112static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
113	.caddr =	2,
114	.cif =		1,
115	.data_mask =	1 << 4,
116	.clk_mask =	1 << 5,
117	.cs_mask =	1 << 10,
118	.cs_addr =	1 << 10,
119	.cs_none =	0,
120	.add_flags = 	1 << 3,
121	.mask_flags =	0,
122};
123
124static int __devinit phase22_init(struct snd_ice1712 *ice)
125{
126	struct snd_akm4xxx *ak;
127	int err;
128
129	/* Configure DAC/ADC description for generic part of ice1724 */
130	switch (ice->eeprom.subvendor) {
131	case VT1724_SUBDEVICE_PHASE22:
132	case VT1724_SUBDEVICE_TS22:
133		ice->num_total_dacs = 2;
134		ice->num_total_adcs = 2;
135		ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
136		break;
137	default:
138		snd_BUG();
139		return -EINVAL;
140	}
141
142	/* Initialize analog chips */
143	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
144	ak = ice->akm;
145	if (!ak)
146		return -ENOMEM;
147	ice->akm_codecs = 1;
148	switch (ice->eeprom.subvendor) {
149	case VT1724_SUBDEVICE_PHASE22:
150	case VT1724_SUBDEVICE_TS22:
151		err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
152						&akm_phase22_priv, ice);
153		if (err < 0)
154			return err;
155		break;
156	}
157
158	return 0;
159}
160
161static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
162{
163	int err = 0;
164
165	switch (ice->eeprom.subvendor) {
166	case VT1724_SUBDEVICE_PHASE22:
167	case VT1724_SUBDEVICE_TS22:
168		err = snd_ice1712_akm4xxx_build_controls(ice);
169		if (err < 0)
170			return err;
171	}
172	return 0;
173}
174
175static unsigned char phase22_eeprom[] __devinitdata = {
176	[ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
177					spdif-in/1xADC, 1xDACs */
178	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
179	[ICE_EEP2_I2S]         = 0xf0,	/* vol, 96k, 24bit */
180	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
181	[ICE_EEP2_GPIO_DIR]    = 0xff,
182	[ICE_EEP2_GPIO_DIR1]   = 0xff,
183	[ICE_EEP2_GPIO_DIR2]   = 0xff,
184	[ICE_EEP2_GPIO_MASK]   = 0x00,
185	[ICE_EEP2_GPIO_MASK1]  = 0x00,
186	[ICE_EEP2_GPIO_MASK2]  = 0x00,
187	[ICE_EEP2_GPIO_STATE]  = 0x00,
188	[ICE_EEP2_GPIO_STATE1] = 0x00,
189	[ICE_EEP2_GPIO_STATE2] = 0x00,
190};
191
192static unsigned char phase28_eeprom[] __devinitdata = {
193	[ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
194					spdif-in/1xADC, 4xDACs */
195	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
196	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
197	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
198	[ICE_EEP2_GPIO_DIR]    = 0xff,
199	[ICE_EEP2_GPIO_DIR1]   = 0xff,
200	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
201	[ICE_EEP2_GPIO_MASK]   = 0x00,
202	[ICE_EEP2_GPIO_MASK1]  = 0x00,
203	[ICE_EEP2_GPIO_MASK2]  = 0x00,
204	[ICE_EEP2_GPIO_STATE]  = 0x00,
205	[ICE_EEP2_GPIO_STATE1] = 0x00,
206	[ICE_EEP2_GPIO_STATE2] = 0x00,
207};
208
209/*
210 * write data in the SPI mode
211 */
212static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
213				unsigned int data, int bits)
214{
215	unsigned int tmp;
216	int i;
217
218	tmp = snd_ice1712_gpio_read(ice);
219
220	snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
221					PHASE28_SPI_CLK|PHASE28_WM_CS));
222	tmp |= PHASE28_WM_RW;
223	tmp &= ~cs;
224	snd_ice1712_gpio_write(ice, tmp);
225	udelay(1);
226
227	for (i = bits - 1; i >= 0; i--) {
228		tmp &= ~PHASE28_SPI_CLK;
229		snd_ice1712_gpio_write(ice, tmp);
230		udelay(1);
231		if (data & (1 << i))
232			tmp |= PHASE28_SPI_MOSI;
233		else
234			tmp &= ~PHASE28_SPI_MOSI;
235		snd_ice1712_gpio_write(ice, tmp);
236		udelay(1);
237		tmp |= PHASE28_SPI_CLK;
238		snd_ice1712_gpio_write(ice, tmp);
239		udelay(1);
240	}
241
242	tmp &= ~PHASE28_SPI_CLK;
243	tmp |= cs;
244	snd_ice1712_gpio_write(ice, tmp);
245	udelay(1);
246	tmp |= PHASE28_SPI_CLK;
247	snd_ice1712_gpio_write(ice, tmp);
248	udelay(1);
249}
250
251/*
252 * get the current register value of WM codec
253 */
254static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
255{
256	reg <<= 1;
257	return ((unsigned short)ice->akm[0].images[reg] << 8) |
258		ice->akm[0].images[reg + 1];
259}
260
261/*
262 * set the register value of WM codec
263 */
264static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
265{
266	phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
267}
268
269/*
270 * set the register value of WM codec and remember it
271 */
272static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
273{
274	wm_put_nocache(ice, reg, val);
275	reg <<= 1;
276	ice->akm[0].images[reg] = val >> 8;
277	ice->akm[0].images[reg + 1] = val;
278}
279
280static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
281			unsigned short vol, unsigned short master)
282{
283	unsigned char nvol;
284
285	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
286		nvol = 0;
287	else
288		nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
289			(master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
290
291	wm_put(ice, index, nvol);
292	wm_put_nocache(ice, index, 0x180 | nvol);
293}
294
295/*
296 * DAC mute control
297 */
298#define wm_pcm_mute_info	snd_ctl_boolean_mono_info
299
300static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
301				struct snd_ctl_elem_value *ucontrol)
302{
303	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
304
305	mutex_lock(&ice->gpio_mutex);
306	ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
307						0 : 1;
308	mutex_unlock(&ice->gpio_mutex);
309	return 0;
310}
311
312static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
313				struct snd_ctl_elem_value *ucontrol)
314{
315	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
316	unsigned short nval, oval;
317	int change;
318
319	snd_ice1712_save_gpio_status(ice);
320	oval = wm_get(ice, WM_MUTE);
321	nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
322	change = (nval != oval);
323	if (change)
324		wm_put(ice, WM_MUTE, nval);
325	snd_ice1712_restore_gpio_status(ice);
326
327	return change;
328}
329
330/*
331 * Master volume attenuation mixer control
332 */
333static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
334				struct snd_ctl_elem_info *uinfo)
335{
336	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
337	uinfo->count = 2;
338	uinfo->value.integer.min = 0;
339	uinfo->value.integer.max = WM_VOL_MAX;
340	return 0;
341}
342
343static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
344				struct snd_ctl_elem_value *ucontrol)
345{
346	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
347	struct phase28_spec *spec = ice->spec;
348	int i;
349	for (i = 0; i < 2; i++)
350		ucontrol->value.integer.value[i] = spec->master[i] &
351							~WM_VOL_MUTE;
352	return 0;
353}
354
355static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
356				struct snd_ctl_elem_value *ucontrol)
357{
358	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
359	struct phase28_spec *spec = ice->spec;
360	int ch, change = 0;
361
362	snd_ice1712_save_gpio_status(ice);
363	for (ch = 0; ch < 2; ch++) {
364		unsigned int vol = ucontrol->value.integer.value[ch];
365		if (vol > WM_VOL_MAX)
366			continue;
367		vol |= spec->master[ch] & WM_VOL_MUTE;
368		if (vol != spec->master[ch]) {
369			int dac;
370			spec->master[ch] = vol;
371			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
372				wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
373					   spec->vol[dac + ch],
374					   spec->master[ch]);
375			change = 1;
376		}
377	}
378	snd_ice1712_restore_gpio_status(ice);
379	return change;
380}
381
382static int __devinit phase28_init(struct snd_ice1712 *ice)
383{
384	static const unsigned short wm_inits_phase28[] = {
385		/* These come first to reduce init pop noise */
386		0x1b, 0x044,	/* ADC Mux (AC'97 source) */
387		0x1c, 0x00B,	/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
388		0x1d, 0x009,	/* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
389
390		0x18, 0x000,	/* All power-up */
391
392		0x16, 0x122,	/* I2S, normal polarity, 24bit */
393		0x17, 0x022,	/* 256fs, slave mode */
394		0x00, 0,	/* DAC1 analog mute */
395		0x01, 0,	/* DAC2 analog mute */
396		0x02, 0,	/* DAC3 analog mute */
397		0x03, 0,	/* DAC4 analog mute */
398		0x04, 0,	/* DAC5 analog mute */
399		0x05, 0,	/* DAC6 analog mute */
400		0x06, 0,	/* DAC7 analog mute */
401		0x07, 0,	/* DAC8 analog mute */
402		0x08, 0x100,	/* master analog mute */
403		0x09, 0xff,	/* DAC1 digital full */
404		0x0a, 0xff,	/* DAC2 digital full */
405		0x0b, 0xff,	/* DAC3 digital full */
406		0x0c, 0xff,	/* DAC4 digital full */
407		0x0d, 0xff,	/* DAC5 digital full */
408		0x0e, 0xff,	/* DAC6 digital full */
409		0x0f, 0xff,	/* DAC7 digital full */
410		0x10, 0xff,	/* DAC8 digital full */
411		0x11, 0x1ff,	/* master digital full */
412		0x12, 0x000,	/* phase normal */
413		0x13, 0x090,	/* unmute DAC L/R */
414		0x14, 0x000,	/* all unmute */
415		0x15, 0x000,	/* no deemphasis, no ZFLG */
416		0x19, 0x000,	/* -12dB ADC/L */
417		0x1a, 0x000,	/* -12dB ADC/R */
418		(unsigned short)-1
419	};
420
421	unsigned int tmp;
422	struct snd_akm4xxx *ak;
423	struct phase28_spec *spec;
424	const unsigned short *p;
425	int i;
426
427	ice->num_total_dacs = 8;
428	ice->num_total_adcs = 2;
429
430	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
431	if (!spec)
432		return -ENOMEM;
433	ice->spec = spec;
434
435	/* Initialize analog chips */
436	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
437	ak = ice->akm;
438	if (!ak)
439		return -ENOMEM;
440	ice->akm_codecs = 1;
441
442	snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
443
444	/* reset the wm codec as the SPI mode */
445	snd_ice1712_save_gpio_status(ice);
446	snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
447					PHASE28_HP_SEL));
448
449	tmp = snd_ice1712_gpio_read(ice);
450	tmp &= ~PHASE28_WM_RESET;
451	snd_ice1712_gpio_write(ice, tmp);
452	udelay(1);
453	tmp |= PHASE28_WM_CS;
454	snd_ice1712_gpio_write(ice, tmp);
455	udelay(1);
456	tmp |= PHASE28_WM_RESET;
457	snd_ice1712_gpio_write(ice, tmp);
458	udelay(1);
459
460	p = wm_inits_phase28;
461	for (; *p != (unsigned short)-1; p += 2)
462		wm_put(ice, p[0], p[1]);
463
464	snd_ice1712_restore_gpio_status(ice);
465
466	spec->master[0] = WM_VOL_MUTE;
467	spec->master[1] = WM_VOL_MUTE;
468	for (i = 0; i < ice->num_total_dacs; i++) {
469		spec->vol[i] = WM_VOL_MUTE;
470		wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
471	}
472
473	return 0;
474}
475
476/*
477 * DAC volume attenuation mixer control
478 */
479static int wm_vol_info(struct snd_kcontrol *kcontrol,
480			struct snd_ctl_elem_info *uinfo)
481{
482	int voices = kcontrol->private_value >> 8;
483	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
484	uinfo->count = voices;
485	uinfo->value.integer.min = 0;		/* mute (-101dB) */
486	uinfo->value.integer.max = 0x7F;	/* 0dB */
487	return 0;
488}
489
490static int wm_vol_get(struct snd_kcontrol *kcontrol,
491			struct snd_ctl_elem_value *ucontrol)
492{
493	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
494	struct phase28_spec *spec = ice->spec;
495	int i, ofs, voices;
496
497	voices = kcontrol->private_value >> 8;
498	ofs = kcontrol->private_value & 0xff;
499	for (i = 0; i < voices; i++)
500		ucontrol->value.integer.value[i] =
501			spec->vol[ofs+i] & ~WM_VOL_MUTE;
502	return 0;
503}
504
505static int wm_vol_put(struct snd_kcontrol *kcontrol,
506			struct snd_ctl_elem_value *ucontrol)
507{
508	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
509	struct phase28_spec *spec = ice->spec;
510	int i, idx, ofs, voices;
511	int change = 0;
512
513	voices = kcontrol->private_value >> 8;
514	ofs = kcontrol->private_value & 0xff;
515	snd_ice1712_save_gpio_status(ice);
516	for (i = 0; i < voices; i++) {
517		unsigned int vol;
518		vol = ucontrol->value.integer.value[i];
519		if (vol > 0x7f)
520			continue;
521		vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
522		if (vol != spec->vol[ofs+i]) {
523			spec->vol[ofs+i] = vol;
524			idx  = WM_DAC_ATTEN + ofs + i;
525			wm_set_vol(ice, idx, spec->vol[ofs+i],
526				   spec->master[i]);
527			change = 1;
528		}
529	}
530	snd_ice1712_restore_gpio_status(ice);
531	return change;
532}
533
534/*
535 * WM8770 mute control
536 */
537static int wm_mute_info(struct snd_kcontrol *kcontrol,
538			struct snd_ctl_elem_info *uinfo) {
539	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
540	uinfo->count = kcontrol->private_value >> 8;
541	uinfo->value.integer.min = 0;
542	uinfo->value.integer.max = 1;
543	return 0;
544}
545
546static int wm_mute_get(struct snd_kcontrol *kcontrol,
547			struct snd_ctl_elem_value *ucontrol)
548{
549	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
550	struct phase28_spec *spec = ice->spec;
551	int voices, ofs, i;
552
553	voices = kcontrol->private_value >> 8;
554	ofs = kcontrol->private_value & 0xFF;
555
556	for (i = 0; i < voices; i++)
557		ucontrol->value.integer.value[i] =
558			(spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
559	return 0;
560}
561
562static int wm_mute_put(struct snd_kcontrol *kcontrol,
563			struct snd_ctl_elem_value *ucontrol)
564{
565	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
566	struct phase28_spec *spec = ice->spec;
567	int change = 0, voices, ofs, i;
568
569	voices = kcontrol->private_value >> 8;
570	ofs = kcontrol->private_value & 0xFF;
571
572	snd_ice1712_save_gpio_status(ice);
573	for (i = 0; i < voices; i++) {
574		int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
575		if (ucontrol->value.integer.value[i] != val) {
576			spec->vol[ofs + i] &= ~WM_VOL_MUTE;
577			spec->vol[ofs + i] |=
578				ucontrol->value.integer.value[i] ? 0 :
579				WM_VOL_MUTE;
580			wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
581					spec->master[i]);
582			change = 1;
583		}
584	}
585	snd_ice1712_restore_gpio_status(ice);
586
587	return change;
588}
589
590/*
591 * WM8770 master mute control
592 */
593#define wm_master_mute_info		snd_ctl_boolean_stereo_info
594
595static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
596				struct snd_ctl_elem_value *ucontrol)
597{
598	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
599	struct phase28_spec *spec = ice->spec;
600
601	ucontrol->value.integer.value[0] =
602		(spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
603	ucontrol->value.integer.value[1] =
604		(spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
605	return 0;
606}
607
608static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
609				struct snd_ctl_elem_value *ucontrol)
610{
611	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
612	struct phase28_spec *spec = ice->spec;
613	int change = 0, i;
614
615	snd_ice1712_save_gpio_status(ice);
616	for (i = 0; i < 2; i++) {
617		int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
618		if (ucontrol->value.integer.value[i] != val) {
619			int dac;
620			spec->master[i] &= ~WM_VOL_MUTE;
621			spec->master[i] |=
622				ucontrol->value.integer.value[i] ? 0 :
623				WM_VOL_MUTE;
624			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
625				wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
626						spec->vol[dac + i],
627						spec->master[i]);
628			change = 1;
629		}
630	}
631	snd_ice1712_restore_gpio_status(ice);
632
633	return change;
634}
635
636/* digital master volume */
637#define PCM_0dB 0xff
638#define PCM_RES 128	/* -64dB */
639#define PCM_MIN (PCM_0dB - PCM_RES)
640static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
641				struct snd_ctl_elem_info *uinfo)
642{
643	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
644	uinfo->count = 1;
645	uinfo->value.integer.min = 0;		/* mute (-64dB) */
646	uinfo->value.integer.max = PCM_RES;	/* 0dB */
647	return 0;
648}
649
650static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
651				struct snd_ctl_elem_value *ucontrol)
652{
653	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
654	unsigned short val;
655
656	mutex_lock(&ice->gpio_mutex);
657	val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
658	val = val > PCM_MIN ? (val - PCM_MIN) : 0;
659	ucontrol->value.integer.value[0] = val;
660	mutex_unlock(&ice->gpio_mutex);
661	return 0;
662}
663
664static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
665				struct snd_ctl_elem_value *ucontrol)
666{
667	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
668	unsigned short ovol, nvol;
669	int change = 0;
670
671	nvol = ucontrol->value.integer.value[0];
672	if (nvol > PCM_RES)
673		return -EINVAL;
674	snd_ice1712_save_gpio_status(ice);
675	nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
676	ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
677	if (ovol != nvol) {
678		wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
679		/* update */
680		wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
681		change = 1;
682	}
683	snd_ice1712_restore_gpio_status(ice);
684	return change;
685}
686
687/*
688 * Deemphasis
689 */
690#define phase28_deemp_info	snd_ctl_boolean_mono_info
691
692static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
693				struct snd_ctl_elem_value *ucontrol)
694{
695	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
696	ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
697						0xf;
698	return 0;
699}
700
701static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
702				struct snd_ctl_elem_value *ucontrol)
703{
704	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
705	int temp, temp2;
706	temp = wm_get(ice, WM_DAC_CTRL2);
707	temp2 = temp;
708	if (ucontrol->value.integer.value[0])
709		temp |= 0xf;
710	else
711		temp &= ~0xf;
712	if (temp != temp2) {
713		wm_put(ice, WM_DAC_CTRL2, temp);
714		return 1;
715	}
716	return 0;
717}
718
719/*
720 * ADC Oversampling
721 */
722static int phase28_oversampling_info(struct snd_kcontrol *k,
723					struct snd_ctl_elem_info *uinfo)
724{
725	static char *texts[2] = { "128x", "64x"	};
726
727	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
728	uinfo->count = 1;
729	uinfo->value.enumerated.items = 2;
730
731	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
732		uinfo->value.enumerated.item = uinfo->value.enumerated.items -
733						1;
734	strcpy(uinfo->value.enumerated.name,
735		texts[uinfo->value.enumerated.item]);
736
737	return 0;
738}
739
740static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
741					struct snd_ctl_elem_value *ucontrol)
742{
743	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
744	ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
745						0x8;
746	return 0;
747}
748
749static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
750					struct snd_ctl_elem_value *ucontrol)
751{
752	int temp, temp2;
753	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
754
755	temp = wm_get(ice, WM_MASTER);
756	temp2 = temp;
757
758	if (ucontrol->value.enumerated.item[0])
759		temp |= 0x8;
760	else
761		temp &= ~0x8;
762
763	if (temp != temp2) {
764		wm_put(ice, WM_MASTER, temp);
765		return 1;
766	}
767	return 0;
768}
769
770static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
771static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
772
773static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
774	{
775		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
776		.name = "Master Playback Switch",
777		.info = wm_master_mute_info,
778		.get = wm_master_mute_get,
779		.put = wm_master_mute_put
780	},
781	{
782		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
783		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
784			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
785		.name = "Master Playback Volume",
786		.info = wm_master_vol_info,
787		.get = wm_master_vol_get,
788		.put = wm_master_vol_put,
789		.tlv = { .p = db_scale_wm_dac }
790	},
791	{
792		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
793		.name = "Front Playback Switch",
794		.info = wm_mute_info,
795		.get = wm_mute_get,
796		.put = wm_mute_put,
797		.private_value = (2 << 8) | 0
798	},
799	{
800		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
801		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
802			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
803		.name = "Front Playback Volume",
804		.info = wm_vol_info,
805		.get = wm_vol_get,
806		.put = wm_vol_put,
807		.private_value = (2 << 8) | 0,
808		.tlv = { .p = db_scale_wm_dac }
809	},
810	{
811		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
812		.name = "Rear Playback Switch",
813		.info = wm_mute_info,
814		.get = wm_mute_get,
815		.put = wm_mute_put,
816		.private_value = (2 << 8) | 2
817	},
818	{
819		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
820		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
821			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
822		.name = "Rear Playback Volume",
823		.info = wm_vol_info,
824		.get = wm_vol_get,
825		.put = wm_vol_put,
826		.private_value = (2 << 8) | 2,
827		.tlv = { .p = db_scale_wm_dac }
828	},
829	{
830		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
831		.name = "Center Playback Switch",
832		.info = wm_mute_info,
833		.get = wm_mute_get,
834		.put = wm_mute_put,
835		.private_value = (1 << 8) | 4
836	},
837	{
838		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
839		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
840			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
841		.name = "Center Playback Volume",
842		.info = wm_vol_info,
843		.get = wm_vol_get,
844		.put = wm_vol_put,
845		.private_value = (1 << 8) | 4,
846		.tlv = { .p = db_scale_wm_dac }
847	},
848	{
849		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
850		.name = "LFE Playback Switch",
851		.info = wm_mute_info,
852		.get = wm_mute_get,
853		.put = wm_mute_put,
854		.private_value = (1 << 8) | 5
855	},
856	{
857		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
858		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
859			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
860		.name = "LFE Playback Volume",
861		.info = wm_vol_info,
862		.get = wm_vol_get,
863		.put = wm_vol_put,
864		.private_value = (1 << 8) | 5,
865		.tlv = { .p = db_scale_wm_dac }
866	},
867	{
868		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
869		.name = "Side Playback Switch",
870		.info = wm_mute_info,
871		.get = wm_mute_get,
872		.put = wm_mute_put,
873		.private_value = (2 << 8) | 6
874	},
875	{
876		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
878			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
879		.name = "Side Playback Volume",
880		.info = wm_vol_info,
881		.get = wm_vol_get,
882		.put = wm_vol_put,
883		.private_value = (2 << 8) | 6,
884		.tlv = { .p = db_scale_wm_dac }
885	}
886};
887
888static struct snd_kcontrol_new wm_controls[] __devinitdata = {
889	{
890		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
891		.name = "PCM Playback Switch",
892		.info = wm_pcm_mute_info,
893		.get = wm_pcm_mute_get,
894		.put = wm_pcm_mute_put
895	},
896	{
897		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
898		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
899			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
900		.name = "PCM Playback Volume",
901		.info = wm_pcm_vol_info,
902		.get = wm_pcm_vol_get,
903		.put = wm_pcm_vol_put,
904		.tlv = { .p = db_scale_wm_pcm }
905	},
906	{
907		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
908		.name = "DAC Deemphasis Switch",
909		.info = phase28_deemp_info,
910		.get = phase28_deemp_get,
911		.put = phase28_deemp_put
912	},
913	{
914		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
915		.name = "ADC Oversampling",
916		.info = phase28_oversampling_info,
917		.get = phase28_oversampling_get,
918		.put = phase28_oversampling_put
919	}
920};
921
922static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
923{
924	unsigned int i, counts;
925	int err;
926
927	counts = ARRAY_SIZE(phase28_dac_controls);
928	for (i = 0; i < counts; i++) {
929		err = snd_ctl_add(ice->card,
930					snd_ctl_new1(&phase28_dac_controls[i],
931							ice));
932		if (err < 0)
933			return err;
934	}
935
936	for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
937		err = snd_ctl_add(ice->card,
938					snd_ctl_new1(&wm_controls[i], ice));
939		if (err < 0)
940			return err;
941	}
942
943	return 0;
944}
945
946struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
947	{
948		.subvendor = VT1724_SUBDEVICE_PHASE22,
949		.name = "Terratec PHASE 22",
950		.model = "phase22",
951		.chip_init = phase22_init,
952		.build_controls = phase22_add_controls,
953		.eeprom_size = sizeof(phase22_eeprom),
954		.eeprom_data = phase22_eeprom,
955	},
956	{
957		.subvendor = VT1724_SUBDEVICE_PHASE28,
958		.name = "Terratec PHASE 28",
959		.model = "phase28",
960		.chip_init = phase28_init,
961		.build_controls = phase28_add_controls,
962		.eeprom_size = sizeof(phase28_eeprom),
963		.eeprom_data = phase28_eeprom,
964	},
965	{
966		.subvendor = VT1724_SUBDEVICE_TS22,
967		.name = "Terrasoniq TS22 PCI",
968		.model = "TS22",
969		.chip_init = phase22_init,
970		.build_controls = phase22_add_controls,
971		.eeprom_size = sizeof(phase22_eeprom),
972		.eeprom_data = phase22_eeprom,
973	},
974	{ } /* terminator */
975};
976