[ALSA] Add some more 'const', but needs changes in i2c/other/ak4*
[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
32b47da0 92static const struct snd_akm4xxx akm_phase22 __devinitdata = {
1da177e4
LT
93 .type = SND_AK4524,
94 .num_dacs = 2,
95 .num_adcs = 2,
96};
97
32b47da0 98static const 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
32b47da0 155static const 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
32b47da0 171static const 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 */
273#define wm_pcm_mute_info phase28_mono_bool_info
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 */
ab0c7d72 530static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
aed058e8
SZ
531 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
532 uinfo->count = 2;
533 uinfo->value.integer.min = 0;
534 uinfo->value.integer.max = 1;
535 return 0;
536}
537
ab0c7d72 538static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 539{
ab0c7d72 540 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
541
542 ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
543 ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
544 return 0;
545}
546
ab0c7d72 547static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 548{
ab0c7d72 549 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
550 int change = 0, i;
551
552 snd_ice1712_save_gpio_status(ice);
553 for (i = 0; i < 2; i++) {
554 int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
555 if (ucontrol->value.integer.value[i] != val) {
556 int dac;
557 ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
558 ice->spec.phase28.master[i] |=
559 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
560 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
561 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
562 ice->spec.phase28.vol[dac + i],
563 ice->spec.phase28.master[i]);
564 change = 1;
565 }
566 }
567 snd_ice1712_restore_gpio_status(ice);
568
569 return change;
570}
571
572/* digital master volume */
573#define PCM_0dB 0xff
574#define PCM_RES 128 /* -64dB */
575#define PCM_MIN (PCM_0dB - PCM_RES)
ab0c7d72 576static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
577{
578 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
579 uinfo->count = 1;
580 uinfo->value.integer.min = 0; /* mute (-64dB) */
581 uinfo->value.integer.max = PCM_RES; /* 0dB */
582 return 0;
583}
584
ab0c7d72 585static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 586{
ab0c7d72 587 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
588 unsigned short val;
589
62932df8 590 mutex_lock(&ice->gpio_mutex);
aed058e8
SZ
591 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
592 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
593 ucontrol->value.integer.value[0] = val;
62932df8 594 mutex_unlock(&ice->gpio_mutex);
aed058e8
SZ
595 return 0;
596}
597
ab0c7d72 598static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 599{
ab0c7d72 600 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
601 unsigned short ovol, nvol;
602 int change = 0;
603
604 snd_ice1712_save_gpio_status(ice);
605 nvol = ucontrol->value.integer.value[0];
606 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
607 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
608 if (ovol != nvol) {
609 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
610 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
611 change = 1;
612 }
613 snd_ice1712_restore_gpio_status(ice);
614 return change;
615}
616
617/*
618 */
ab0c7d72 619static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
620{
621 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
622 uinfo->count = 1;
623 uinfo->value.integer.min = 0;
624 uinfo->value.integer.max = 1;
625 return 0;
626}
627
628/*
629 * Deemphasis
630 */
631#define phase28_deemp_info phase28_mono_bool_info
632
ab0c7d72 633static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 634{
ab0c7d72 635 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
636 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
637 return 0;
638}
639
ab0c7d72 640static int phase28_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 641{
ab0c7d72 642 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
643 int temp, temp2;
644 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
645 if (ucontrol->value.integer.value[0])
646 temp |= 0xf;
647 else
648 temp &= ~0xf;
649 if (temp != temp2) {
650 wm_put(ice, WM_DAC_CTRL2, temp);
651 return 1;
652 }
653 return 0;
654}
655
656/*
657 * ADC Oversampling
658 */
ab0c7d72 659static int phase28_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
aed058e8
SZ
660{
661 static char *texts[2] = { "128x", "64x" };
662
663 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
664 uinfo->count = 1;
665 uinfo->value.enumerated.items = 2;
666
667 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
668 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
669 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
670
671 return 0;
672}
673
ab0c7d72 674static int phase28_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8 675{
ab0c7d72 676 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
677 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
678 return 0;
679}
680
ab0c7d72 681static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
aed058e8
SZ
682{
683 int temp, temp2;
ab0c7d72 684 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
aed058e8
SZ
685
686 temp2 = temp = wm_get(ice, WM_MASTER);
687
688 if (ucontrol->value.enumerated.item[0])
689 temp |= 0x8;
690 else
691 temp &= ~0x8;
692
693 if (temp != temp2) {
694 wm_put(ice, WM_MASTER, temp);
695 return 1;
696 }
697 return 0;
698}
699
f640c320
TI
700static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
701static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
702
32b47da0 703static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
aed058e8
SZ
704 {
705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
706 .name = "Master Playback Switch",
707 .info = wm_master_mute_info,
708 .get = wm_master_mute_get,
709 .put = wm_master_mute_put
710 },
711 {
712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
713 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
714 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
715 .name = "Master Playback Volume",
716 .info = wm_master_vol_info,
717 .get = wm_master_vol_get,
f640c320
TI
718 .put = wm_master_vol_put,
719 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
720 },
721 {
722 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
723 .name = "Front Playback Switch",
724 .info = wm_mute_info,
725 .get = wm_mute_get,
726 .put = wm_mute_put,
727 .private_value = (2 << 8) | 0
728 },
729 {
730 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
731 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
732 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
733 .name = "Front Playback Volume",
734 .info = wm_vol_info,
735 .get = wm_vol_get,
736 .put = wm_vol_put,
f640c320
TI
737 .private_value = (2 << 8) | 0,
738 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
739 },
740 {
741 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
742 .name = "Rear Playback Switch",
743 .info = wm_mute_info,
744 .get = wm_mute_get,
745 .put = wm_mute_put,
746 .private_value = (2 << 8) | 2
747 },
748 {
749 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
750 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
751 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
752 .name = "Rear Playback Volume",
753 .info = wm_vol_info,
754 .get = wm_vol_get,
755 .put = wm_vol_put,
f640c320
TI
756 .private_value = (2 << 8) | 2,
757 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
758 },
759 {
760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
761 .name = "Center Playback Switch",
762 .info = wm_mute_info,
763 .get = wm_mute_get,
764 .put = wm_mute_put,
765 .private_value = (1 << 8) | 4
766 },
767 {
768 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
769 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
770 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
771 .name = "Center Playback Volume",
772 .info = wm_vol_info,
773 .get = wm_vol_get,
774 .put = wm_vol_put,
f640c320
TI
775 .private_value = (1 << 8) | 4,
776 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
777 },
778 {
779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
780 .name = "LFE Playback Switch",
781 .info = wm_mute_info,
782 .get = wm_mute_get,
783 .put = wm_mute_put,
784 .private_value = (1 << 8) | 5
785 },
786 {
787 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
788 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
789 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
790 .name = "LFE Playback Volume",
791 .info = wm_vol_info,
792 .get = wm_vol_get,
793 .put = wm_vol_put,
f640c320
TI
794 .private_value = (1 << 8) | 5,
795 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
796 },
797 {
798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
799 .name = "Side Playback Switch",
800 .info = wm_mute_info,
801 .get = wm_mute_get,
802 .put = wm_mute_put,
803 .private_value = (2 << 8) | 6
804 },
805 {
806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320
TI
807 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
808 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
aed058e8
SZ
809 .name = "Side Playback Volume",
810 .info = wm_vol_info,
811 .get = wm_vol_get,
812 .put = wm_vol_put,
f640c320
TI
813 .private_value = (2 << 8) | 6,
814 .tlv = { .p = db_scale_wm_dac }
aed058e8
SZ
815 }
816};
817
32b47da0 818static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
aed058e8
SZ
819 {
820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
821 .name = "PCM Playback Switch",
822 .info = wm_pcm_mute_info,
823 .get = wm_pcm_mute_get,
824 .put = wm_pcm_mute_put
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 = "PCM Playback Volume",
831 .info = wm_pcm_vol_info,
832 .get = wm_pcm_vol_get,
f640c320
TI
833 .put = wm_pcm_vol_put,
834 .tlv = { .p = db_scale_wm_pcm }
aed058e8
SZ
835 },
836 {
837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
838 .name = "DAC Deemphasis Switch",
839 .info = phase28_deemp_info,
840 .get = phase28_deemp_get,
841 .put = phase28_deemp_put
842 },
843 {
844 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
845 .name = "ADC Oversampling",
846 .info = phase28_oversampling_info,
847 .get = phase28_oversampling_get,
848 .put = phase28_oversampling_put
849 }
850};
851
ab0c7d72 852static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
aed058e8
SZ
853{
854 unsigned int i, counts;
855 int err;
856
857 counts = ARRAY_SIZE(phase28_dac_controls);
858 for (i = 0; i < counts; i++) {
859 err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
860 if (err < 0)
861 return err;
862 }
863
864 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
865 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
866 if (err < 0)
867 return err;
868 }
869
870 return 0;
871}
872
32b47da0 873const struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
1da177e4
LT
874 {
875 .subvendor = VT1724_SUBDEVICE_PHASE22,
876 .name = "Terratec PHASE 22",
877 .model = "phase22",
878 .chip_init = phase22_init,
879 .build_controls = phase22_add_controls,
880 .eeprom_size = sizeof(phase22_eeprom),
881 .eeprom_data = phase22_eeprom,
882 },
aed058e8
SZ
883 {
884 .subvendor = VT1724_SUBDEVICE_PHASE28,
885 .name = "Terratec PHASE 28",
886 .model = "phase28",
887 .chip_init = phase28_init,
888 .build_controls = phase28_add_controls,
889 .eeprom_size = sizeof(phase28_eeprom),
890 .eeprom_data = phase28_eeprom,
891 },
1da177e4
LT
892 { } /* terminator */
893};
This page took 0.334636 seconds and 5 git commands to generate.