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