Merge git://git.infradead.org/mtd-2.6
[linux-2.6-block.git] / sound / pci / ice1712 / phase.c
CommitLineData
1da177e4
LT
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:
eee75a6c 25 * Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out)
1da177e4 26 * Analog chip: AK4524 (partially via Philip's 74HCT125)
eee75a6c
VM
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)
1da177e4
LT
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
eee75a6c
VM
35 * CDTI may be completely blocked by 74HCT125's gate #1
36 * controlled by GPIO 3
37 */
38
39/* PHASE 28 overview:
cc67b7f7 40 * Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
eee75a6c
VM
41 * Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
42 * Digital receiver: CS8414-CS (supported in this release)
1da177e4
LT
43 */
44
1da177e4
LT
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>
62932df8
IM
50#include <linux/mutex.h>
51
1da177e4
LT
52#include <sound/core.h>
53
54#include "ice1712.h"
55#include "envy24ht.h"
56#include "phase.h"
f640c320 57#include <sound/tlv.h>
1da177e4 58
7cda8ba9
TI
59/* AC97 register cache for Phase28 */
60struct phase28_spec {
61 unsigned short master[2];
62 unsigned short vol[8];
008f3599 63};
7cda8ba9 64
aed058e8
SZ
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 */
32b47da0 88static const unsigned char wm_vol[256] = {
cc67b7f7
VM
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
aed058e8
SZ
101};
102
103#define WM_VOL_MAX (sizeof(wm_vol) - 1)
104#define WM_VOL_MUTE 0x8000
105
1b60f6b0 106static struct snd_akm4xxx akm_phase22 __devinitdata = {
1da177e4
LT
107 .type = SND_AK4524,
108 .num_dacs = 2,
109 .num_adcs = 2,
110};
111
1b60f6b0 112static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
1da177e4
LT
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
ab0c7d72 124static int __devinit phase22_init(struct snd_ice1712 *ice)
1da177e4 125{
ab0c7d72 126 struct snd_akm4xxx *ak;
1da177e4
LT
127 int err;
128
cc67b7f7 129 /* Configure DAC/ADC description for generic part of ice1724 */
1da177e4
LT
130 switch (ice->eeprom.subvendor) {
131 case VT1724_SUBDEVICE_PHASE22:
740dc9c4 132 case VT1724_SUBDEVICE_TS22:
1da177e4
LT
133 ice->num_total_dacs = 2;
134 ice->num_total_adcs = 2;
cc67b7f7 135 ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
1da177e4
LT
136 break;
137 default:
138 snd_BUG();
139 return -EINVAL;
140 }
141
cc67b7f7
VM
142 /* Initialize analog chips */
143 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
144 ak = ice->akm;
145 if (!ak)
1da177e4
LT
146 return -ENOMEM;
147 ice->akm_codecs = 1;
148 switch (ice->eeprom.subvendor) {
149 case VT1724_SUBDEVICE_PHASE22:
740dc9c4 150 case VT1724_SUBDEVICE_TS22:
cc67b7f7
VM
151 err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
152 &akm_phase22_priv, ice);
153 if (err < 0)
1da177e4
LT
154 return err;
155 break;
156 }
157
158 return 0;
159}
160
ab0c7d72 161static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
1da177e4
LT
162{
163 int err = 0;
164
165 switch (ice->eeprom.subvendor) {
166 case VT1724_SUBDEVICE_PHASE22:
740dc9c4 167 case VT1724_SUBDEVICE_TS22:
1da177e4
LT
168 err = snd_ice1712_akm4xxx_build_controls(ice);
169 if (err < 0)
170 return err;
171 }
172 return 0;
173}
174
1b60f6b0 175static unsigned char phase22_eeprom[] __devinitdata = {
eee75a6c
VM
176 [ICE_EEP2_SYSCONF] = 0x28, /* clock 512, mpu 401,
177 spdif-in/1xADC, 1xDACs */
189bc171 178 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
eee75a6c 179 [ICE_EEP2_I2S] = 0xf0, /* vol, 96k, 24bit */
189bc171
TI
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,
1da177e4
LT
190};
191
1b60f6b0 192static unsigned char phase28_eeprom[] __devinitdata = {
eee75a6c
VM
193 [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401,
194 spdif-in/1xADC, 4xDACs */
189bc171
TI
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,
aed058e8
SZ
207};
208
209/*
210 * write data in the SPI mode
211 */
cc67b7f7
VM
212static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
213 unsigned int data, int bits)
aed058e8
SZ
214{
215 unsigned int tmp;
216 int i;
217
218 tmp = snd_ice1712_gpio_read(ice);
219
cc67b7f7
VM
220 snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
221 PHASE28_SPI_CLK|PHASE28_WM_CS));
aed058e8
SZ
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 */
ab0c7d72 254static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
aed058e8
SZ
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 */
ab0c7d72 264static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
aed058e8
SZ
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 */
ab0c7d72 272static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
aed058e8
SZ
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
cc67b7f7
VM
280static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
281 unsigned short vol, unsigned short master)
aed058e8
SZ
282{
283 unsigned char nvol;
284
285 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
286 nvol = 0;
287 else
cc67b7f7
VM
288 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
289 (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
aed058e8
SZ
290
291 wm_put(ice, index, nvol);
292 wm_put_nocache(ice, index, 0x180 | nvol);
293}
294
295/*
296 * DAC mute control
297 */
a5ce8890 298#define wm_pcm_mute_info snd_ctl_boolean_mono_info
aed058e8 299
cc67b7f7
VM
300static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
301 struct snd_ctl_elem_value *ucontrol)
aed058e8 302{
ab0c7d72 303 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8 304
62932df8 305 mutex_lock(&ice->gpio_mutex);
cc67b7f7
VM
306 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
307 0 : 1;
62932df8 308 mutex_unlock(&ice->gpio_mutex);
aed058e8
SZ
309 return 0;
310}
311
cc67b7f7
VM
312static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
aed058e8 314{
ab0c7d72 315 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
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);
cc67b7f7
VM
322 change = (nval != oval);
323 if (change)
aed058e8
SZ
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 */
cc67b7f7
VM
333static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
334 struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
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
cc67b7f7
VM
343static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
344 struct snd_ctl_elem_value *ucontrol)
aed058e8 345{
ab0c7d72 346 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 347 struct phase28_spec *spec = ice->spec;
aed058e8 348 int i;
cc67b7f7
VM
349 for (i = 0; i < 2; i++)
350 ucontrol->value.integer.value[i] = spec->master[i] &
351 ~WM_VOL_MUTE;
aed058e8
SZ
352 return 0;
353}
354
cc67b7f7
VM
355static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
356 struct snd_ctl_elem_value *ucontrol)
aed058e8 357{
ab0c7d72 358 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 359 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
360 int ch, change = 0;
361
362 snd_ice1712_save_gpio_status(ice);
363 for (ch = 0; ch < 2; ch++) {
9cd17cd2
TI
364 unsigned int vol = ucontrol->value.integer.value[ch];
365 if (vol > WM_VOL_MAX)
366 continue;
7cda8ba9
TI
367 vol |= spec->master[ch] & WM_VOL_MUTE;
368 if (vol != spec->master[ch]) {
aed058e8 369 int dac;
7cda8ba9 370 spec->master[ch] = vol;
aed058e8
SZ
371 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
372 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
7cda8ba9
TI
373 spec->vol[dac + ch],
374 spec->master[ch]);
aed058e8
SZ
375 change = 1;
376 }
377 }
378 snd_ice1712_restore_gpio_status(ice);
379 return change;
380}
381
ab0c7d72 382static int __devinit phase28_init(struct snd_ice1712 *ice)
aed058e8 383{
32b47da0 384 static const unsigned short wm_inits_phase28[] = {
aed058e8 385 /* These come first to reduce init pop noise */
cc67b7f7
VM
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 */
aed058e8
SZ
418 (unsigned short)-1
419 };
420
421 unsigned int tmp;
ab0c7d72 422 struct snd_akm4xxx *ak;
7cda8ba9 423 struct phase28_spec *spec;
32b47da0 424 const unsigned short *p;
aed058e8
SZ
425 int i;
426
427 ice->num_total_dacs = 8;
428 ice->num_total_adcs = 2;
429
7cda8ba9
TI
430 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
431 if (!spec)
432 return -ENOMEM;
433 ice->spec = spec;
434
cc67b7f7
VM
435 /* Initialize analog chips */
436 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
437 ak = ice->akm;
aed058e8
SZ
438 if (!ak)
439 return -ENOMEM;
440 ice->akm_codecs = 1;
441
cc67b7f7 442 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
aed058e8
SZ
443
444 /* reset the wm codec as the SPI mode */
445 snd_ice1712_save_gpio_status(ice);
cc67b7f7
VM
446 snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
447 PHASE28_HP_SEL));
aed058e8
SZ
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
7cda8ba9
TI
466 spec->master[0] = WM_VOL_MUTE;
467 spec->master[1] = WM_VOL_MUTE;
aed058e8 468 for (i = 0; i < ice->num_total_dacs; i++) {
7cda8ba9
TI
469 spec->vol[i] = WM_VOL_MUTE;
470 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
aed058e8
SZ
471 }
472
473 return 0;
474}
475
476/*
477 * DAC volume attenuation mixer control
478 */
cc67b7f7
VM
479static int wm_vol_info(struct snd_kcontrol *kcontrol,
480 struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
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
cc67b7f7
VM
490static int wm_vol_get(struct snd_kcontrol *kcontrol,
491 struct snd_ctl_elem_value *ucontrol)
aed058e8 492{
ab0c7d72 493 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 494 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
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++)
7cda8ba9
TI
500 ucontrol->value.integer.value[i] =
501 spec->vol[ofs+i] & ~WM_VOL_MUTE;
aed058e8
SZ
502 return 0;
503}
504
cc67b7f7
VM
505static int wm_vol_put(struct snd_kcontrol *kcontrol,
506 struct snd_ctl_elem_value *ucontrol)
aed058e8 507{
ab0c7d72 508 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 509 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
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++) {
9cd17cd2
TI
517 unsigned int vol;
518 vol = ucontrol->value.integer.value[i];
519 if (vol > 0x7f)
520 continue;
7cda8ba9
TI
521 vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
522 if (vol != spec->vol[ofs+i]) {
523 spec->vol[ofs+i] = vol;
9cd17cd2 524 idx = WM_DAC_ATTEN + ofs + i;
7cda8ba9
TI
525 wm_set_vol(ice, idx, spec->vol[ofs+i],
526 spec->master[i]);
aed058e8
SZ
527 change = 1;
528 }
529 }
530 snd_ice1712_restore_gpio_status(ice);
531 return change;
532}
533
534/*
535 * WM8770 mute control
536 */
cc67b7f7
VM
537static int wm_mute_info(struct snd_kcontrol *kcontrol,
538 struct snd_ctl_elem_info *uinfo) {
aed058e8
SZ
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
cc67b7f7
VM
546static int wm_mute_get(struct snd_kcontrol *kcontrol,
547 struct snd_ctl_elem_value *ucontrol)
aed058e8 548{
ab0c7d72 549 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 550 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
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++)
7cda8ba9
TI
557 ucontrol->value.integer.value[i] =
558 (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
aed058e8
SZ
559 return 0;
560}
561
cc67b7f7
VM
562static int wm_mute_put(struct snd_kcontrol *kcontrol,
563 struct snd_ctl_elem_value *ucontrol)
aed058e8 564{
ab0c7d72 565 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 566 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
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++) {
7cda8ba9 574 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
aed058e8 575 if (ucontrol->value.integer.value[i] != val) {
7cda8ba9
TI
576 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
577 spec->vol[ofs + i] |=
cc67b7f7
VM
578 ucontrol->value.integer.value[i] ? 0 :
579 WM_VOL_MUTE;
7cda8ba9 580 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
cc67b7f7 581 spec->master[i]);
aed058e8
SZ
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 */
a5ce8890 593#define wm_master_mute_info snd_ctl_boolean_stereo_info
aed058e8 594
cc67b7f7
VM
595static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
596 struct snd_ctl_elem_value *ucontrol)
aed058e8 597{
ab0c7d72 598 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 599 struct phase28_spec *spec = ice->spec;
aed058e8 600
7cda8ba9
TI
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;
aed058e8
SZ
605 return 0;
606}
607
cc67b7f7
VM
608static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
609 struct snd_ctl_elem_value *ucontrol)
aed058e8 610{
ab0c7d72 611 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 612 struct phase28_spec *spec = ice->spec;
aed058e8
SZ
613 int change = 0, i;
614
615 snd_ice1712_save_gpio_status(ice);
616 for (i = 0; i < 2; i++) {
7cda8ba9 617 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
aed058e8
SZ
618 if (ucontrol->value.integer.value[i] != val) {
619 int dac;
7cda8ba9
TI
620 spec->master[i] &= ~WM_VOL_MUTE;
621 spec->master[i] |=
cc67b7f7
VM
622 ucontrol->value.integer.value[i] ? 0 :
623 WM_VOL_MUTE;
aed058e8
SZ
624 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
625 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
cc67b7f7
VM
626 spec->vol[dac + i],
627 spec->master[i]);
aed058e8
SZ
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)
cc67b7f7
VM
640static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
641 struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
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
cc67b7f7
VM
650static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
651 struct snd_ctl_elem_value *ucontrol)
aed058e8 652{
ab0c7d72 653 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
654 unsigned short val;
655
62932df8 656 mutex_lock(&ice->gpio_mutex);
aed058e8
SZ
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;
62932df8 660 mutex_unlock(&ice->gpio_mutex);
aed058e8
SZ
661 return 0;
662}
663
cc67b7f7
VM
664static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
665 struct snd_ctl_elem_value *ucontrol)
aed058e8 666{
ab0c7d72 667 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
668 unsigned short ovol, nvol;
669 int change = 0;
670
aed058e8 671 nvol = ucontrol->value.integer.value[0];
9cd17cd2
TI
672 if (nvol > PCM_RES)
673 return -EINVAL;
674 snd_ice1712_save_gpio_status(ice);
aed058e8
SZ
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 */
cc67b7f7
VM
679 /* update */
680 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
aed058e8
SZ
681 change = 1;
682 }
683 snd_ice1712_restore_gpio_status(ice);
684 return change;
685}
686
aed058e8
SZ
687/*
688 * Deemphasis
689 */
a5ce8890 690#define phase28_deemp_info snd_ctl_boolean_mono_info
aed058e8 691
cc67b7f7
VM
692static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
693 struct snd_ctl_elem_value *ucontrol)
aed058e8 694{
ab0c7d72 695 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
cc67b7f7
VM
696 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
697 0xf;
aed058e8
SZ
698 return 0;
699}
700
cc67b7f7
VM
701static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
702 struct snd_ctl_elem_value *ucontrol)
aed058e8 703{
ab0c7d72 704 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8 705 int temp, temp2;
cc67b7f7
VM
706 temp = wm_get(ice, WM_DAC_CTRL2);
707 temp2 = temp;
aed058e8
SZ
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 */
cc67b7f7
VM
722static int phase28_oversampling_info(struct snd_kcontrol *k,
723 struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
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)
cc67b7f7
VM
732 uinfo->value.enumerated.item = uinfo->value.enumerated.items -
733 1;
734 strcpy(uinfo->value.enumerated.name,
735 texts[uinfo->value.enumerated.item]);
aed058e8 736
cc67b7f7 737 return 0;
aed058e8
SZ
738}
739
cc67b7f7
VM
740static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
741 struct snd_ctl_elem_value *ucontrol)
aed058e8 742{
ab0c7d72 743 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
cc67b7f7
VM
744 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
745 0x8;
aed058e8
SZ
746 return 0;
747}
748
cc67b7f7
VM
749static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
750 struct snd_ctl_elem_value *ucontrol)
aed058e8
SZ
751{
752 int temp, temp2;
ab0c7d72 753 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8 754
cc67b7f7
VM
755 temp = wm_get(ice, WM_MASTER);
756 temp2 = temp;
aed058e8
SZ
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
0cb29ea0
TI
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);
f640c320 772
1b60f6b0 773static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
aed058e8
SZ
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,
f640c320
TI
783 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
784 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
785 .name = "Master Playback Volume",
786 .info = wm_master_vol_info,
787 .get = wm_master_vol_get,
f640c320
TI
788 .put = wm_master_vol_put,
789 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
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,
f640c320
TI
801 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
802 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
803 .name = "Front Playback Volume",
804 .info = wm_vol_info,
805 .get = wm_vol_get,
806 .put = wm_vol_put,
f640c320
TI
807 .private_value = (2 << 8) | 0,
808 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
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,
f640c320
TI
820 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
821 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
822 .name = "Rear Playback Volume",
823 .info = wm_vol_info,
824 .get = wm_vol_get,
825 .put = wm_vol_put,
f640c320
TI
826 .private_value = (2 << 8) | 2,
827 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
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,
f640c320
TI
839 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
840 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
841 .name = "Center Playback Volume",
842 .info = wm_vol_info,
843 .get = wm_vol_get,
844 .put = wm_vol_put,
f640c320
TI
845 .private_value = (1 << 8) | 4,
846 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
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,
f640c320
TI
858 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
859 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
860 .name = "LFE Playback Volume",
861 .info = wm_vol_info,
862 .get = wm_vol_get,
863 .put = wm_vol_put,
f640c320
TI
864 .private_value = (1 << 8) | 5,
865 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
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,
f640c320
TI
877 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
878 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
879 .name = "Side Playback Volume",
880 .info = wm_vol_info,
881 .get = wm_vol_get,
882 .put = wm_vol_put,
f640c320
TI
883 .private_value = (2 << 8) | 6,
884 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
885 }
886};
887
1b60f6b0 888static struct snd_kcontrol_new wm_controls[] __devinitdata = {
aed058e8
SZ
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,
f640c320
TI
898 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
899 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
900 .name = "PCM Playback Volume",
901 .info = wm_pcm_vol_info,
902 .get = wm_pcm_vol_get,
f640c320
TI
903 .put = wm_pcm_vol_put,
904 .tlv = { .p = db_scale_wm_pcm }
aed058e8
SZ
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
ab0c7d72 922static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
aed058e8
SZ
923{
924 unsigned int i, counts;
925 int err;
926
927 counts = ARRAY_SIZE(phase28_dac_controls);
928 for (i = 0; i < counts; i++) {
cc67b7f7
VM
929 err = snd_ctl_add(ice->card,
930 snd_ctl_new1(&phase28_dac_controls[i],
931 ice));
aed058e8
SZ
932 if (err < 0)
933 return err;
934 }
935
936 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
cc67b7f7
VM
937 err = snd_ctl_add(ice->card,
938 snd_ctl_new1(&wm_controls[i], ice));
aed058e8
SZ
939 if (err < 0)
940 return err;
941 }
942
943 return 0;
944}
945
1b60f6b0 946struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
1da177e4
LT
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 },
aed058e8
SZ
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 },
740dc9c4
MZ
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 },
1da177e4
LT
974 { } /* terminator */
975};