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