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