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