GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / sound / pci / oxygen / xonar_wm87x6.c
blobb82c1cfa96f5334554435a6eeebc6e82fa63857d
1 /*
2 * card driver for models with WM8776/WM8766 DACs (Xonar DS)
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
20 * Xonar DS
21 * --------
23 * CMI8788:
25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input)
28 * GPIO 4 <- headphone detect
29 * GPIO 6 -> route input jack to input 1/2 (1/0)
30 * GPIO 7 -> enable output to speakers
31 * GPIO 8 -> enable output to speakers
34 #include <linux/pci.h>
35 #include <linux/delay.h>
36 #include <sound/control.h>
37 #include <sound/core.h>
38 #include <sound/pcm.h>
39 #include <sound/pcm_params.h>
40 #include <sound/tlv.h>
41 #include "xonar.h"
42 #include "wm8776.h"
43 #include "wm8766.h"
45 #define GPIO_DS_HP_DETECT 0x0010
46 #define GPIO_DS_INPUT_ROUTE 0x0040
47 #define GPIO_DS_OUTPUT_ENABLE 0x0180
49 #define LC_CONTROL_LIMITER 0x40000000
50 #define LC_CONTROL_ALC 0x20000000
52 struct xonar_wm87x6 {
53 struct xonar_generic generic;
54 u16 wm8776_regs[0x17];
55 u16 wm8766_regs[0x10];
56 struct snd_kcontrol *line_adcmux_control;
57 struct snd_kcontrol *mic_adcmux_control;
58 struct snd_kcontrol *lc_controls[13];
61 static void wm8776_write(struct oxygen *chip,
62 unsigned int reg, unsigned int value)
64 struct xonar_wm87x6 *data = chip->model_data;
66 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
67 OXYGEN_SPI_DATA_LENGTH_2 |
68 OXYGEN_SPI_CLOCK_160 |
69 (1 << OXYGEN_SPI_CODEC_SHIFT) |
70 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
71 (reg << 9) | value);
72 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
73 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
74 value &= ~WM8776_UPDATE;
75 data->wm8776_regs[reg] = value;
79 static void wm8776_write_cached(struct oxygen *chip,
80 unsigned int reg, unsigned int value)
82 struct xonar_wm87x6 *data = chip->model_data;
84 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
85 value != data->wm8776_regs[reg])
86 wm8776_write(chip, reg, value);
89 static void wm8766_write(struct oxygen *chip,
90 unsigned int reg, unsigned int value)
92 struct xonar_wm87x6 *data = chip->model_data;
94 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
95 OXYGEN_SPI_DATA_LENGTH_2 |
96 OXYGEN_SPI_CLOCK_160 |
97 (0 << OXYGEN_SPI_CODEC_SHIFT) |
98 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
99 (reg << 9) | value);
100 if (reg < ARRAY_SIZE(data->wm8766_regs))
101 data->wm8766_regs[reg] = value;
104 static void wm8766_write_cached(struct oxygen *chip,
105 unsigned int reg, unsigned int value)
107 struct xonar_wm87x6 *data = chip->model_data;
109 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
110 value != data->wm8766_regs[reg]) {
111 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113 value &= ~WM8766_UPDATE;
114 wm8766_write(chip, reg, value);
118 static void wm8776_registers_init(struct oxygen *chip)
120 struct xonar_wm87x6 *data = chip->model_data;
122 wm8776_write(chip, WM8776_RESET, 0);
123 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
124 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
125 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
126 wm8776_write(chip, WM8776_DACIFCTRL,
127 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
128 wm8776_write(chip, WM8776_ADCIFCTRL,
129 data->wm8776_regs[WM8776_ADCIFCTRL]);
130 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
131 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
132 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
133 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
134 WM8776_UPDATE);
135 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
136 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
137 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
138 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
139 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
142 static void wm8766_registers_init(struct oxygen *chip)
144 wm8766_write(chip, WM8766_RESET, 0);
145 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
146 wm8766_write(chip, WM8766_DAC_CTRL2,
147 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
148 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
149 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
150 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
151 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
152 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
153 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
156 static void wm8776_init(struct oxygen *chip)
158 struct xonar_wm87x6 *data = chip->model_data;
160 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
161 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
162 data->wm8776_regs[WM8776_ADCIFCTRL] =
163 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
164 data->wm8776_regs[WM8776_MSTRCTRL] =
165 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
166 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
167 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
168 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
169 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
170 wm8776_registers_init(chip);
173 static void xonar_ds_init(struct oxygen *chip)
175 struct xonar_wm87x6 *data = chip->model_data;
177 data->generic.anti_pop_delay = 300;
178 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
180 wm8776_init(chip);
181 wm8766_registers_init(chip);
183 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
184 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
185 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
186 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
187 chip->interrupt_mask |= OXYGEN_INT_GPIO;
189 xonar_enable_output(chip);
191 snd_component_add(chip->card, "WM8776");
192 snd_component_add(chip->card, "WM8766");
195 static void xonar_ds_cleanup(struct oxygen *chip)
197 xonar_disable_output(chip);
198 wm8776_write(chip, WM8776_RESET, 0);
201 static void xonar_ds_suspend(struct oxygen *chip)
203 xonar_ds_cleanup(chip);
206 static void xonar_ds_resume(struct oxygen *chip)
208 wm8776_registers_init(chip);
209 wm8766_registers_init(chip);
210 xonar_enable_output(chip);
213 static void wm8776_adc_hardware_filter(unsigned int channel,
214 struct snd_pcm_hardware *hardware)
216 if (channel == PCM_A) {
217 hardware->rates = SNDRV_PCM_RATE_32000 |
218 SNDRV_PCM_RATE_44100 |
219 SNDRV_PCM_RATE_48000 |
220 SNDRV_PCM_RATE_64000 |
221 SNDRV_PCM_RATE_88200 |
222 SNDRV_PCM_RATE_96000;
223 hardware->rate_max = 96000;
227 static void set_wm87x6_dac_params(struct oxygen *chip,
228 struct snd_pcm_hw_params *params)
232 static void set_wm8776_adc_params(struct oxygen *chip,
233 struct snd_pcm_hw_params *params)
235 u16 reg;
237 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
238 if (params_rate(params) > 48000)
239 reg |= WM8776_ADCOSR;
240 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
243 static void update_wm8776_volume(struct oxygen *chip)
245 struct xonar_wm87x6 *data = chip->model_data;
246 u8 to_change;
248 if (chip->dac_volume[0] == chip->dac_volume[1]) {
249 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
250 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
251 wm8776_write(chip, WM8776_DACMASTER,
252 chip->dac_volume[0] | WM8776_UPDATE);
253 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
254 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
256 } else {
257 to_change = (chip->dac_volume[0] !=
258 data->wm8776_regs[WM8776_DACLVOL]) << 0;
259 to_change |= (chip->dac_volume[1] !=
260 data->wm8776_regs[WM8776_DACLVOL]) << 1;
261 if (to_change & 1)
262 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
263 ((to_change & 2) ? 0 : WM8776_UPDATE));
264 if (to_change & 2)
265 wm8776_write(chip, WM8776_DACRVOL,
266 chip->dac_volume[1] | WM8776_UPDATE);
270 static void update_wm87x6_volume(struct oxygen *chip)
272 static const u8 wm8766_regs[6] = {
273 WM8766_LDA1, WM8766_RDA1,
274 WM8766_LDA2, WM8766_RDA2,
275 WM8766_LDA3, WM8766_RDA3,
277 struct xonar_wm87x6 *data = chip->model_data;
278 unsigned int i;
279 u8 to_change;
281 update_wm8776_volume(chip);
282 if (chip->dac_volume[2] == chip->dac_volume[3] &&
283 chip->dac_volume[2] == chip->dac_volume[4] &&
284 chip->dac_volume[2] == chip->dac_volume[5] &&
285 chip->dac_volume[2] == chip->dac_volume[6] &&
286 chip->dac_volume[2] == chip->dac_volume[7]) {
287 to_change = 0;
288 for (i = 0; i < 6; ++i)
289 if (chip->dac_volume[2] !=
290 data->wm8766_regs[wm8766_regs[i]])
291 to_change = 1;
292 if (to_change) {
293 wm8766_write(chip, WM8766_MASTDA,
294 chip->dac_volume[2] | WM8766_UPDATE);
295 for (i = 0; i < 6; ++i)
296 data->wm8766_regs[wm8766_regs[i]] =
297 chip->dac_volume[2];
299 } else {
300 to_change = 0;
301 for (i = 0; i < 6; ++i)
302 to_change |= (chip->dac_volume[2 + i] !=
303 data->wm8766_regs[wm8766_regs[i]]) << i;
304 for (i = 0; i < 6; ++i)
305 if (to_change & (1 << i))
306 wm8766_write(chip, wm8766_regs[i],
307 chip->dac_volume[2 + i] |
308 ((to_change & (0x3e << i))
309 ? 0 : WM8766_UPDATE));
313 static void update_wm8776_mute(struct oxygen *chip)
315 wm8776_write_cached(chip, WM8776_DACMUTE,
316 chip->dac_mute ? WM8776_DMUTE : 0);
319 static void update_wm87x6_mute(struct oxygen *chip)
321 update_wm8776_mute(chip);
322 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
323 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
326 static void xonar_ds_gpio_changed(struct oxygen *chip)
328 u16 bits;
330 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
331 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
334 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
335 struct snd_ctl_elem_value *value)
337 struct oxygen *chip = ctl->private_data;
338 struct xonar_wm87x6 *data = chip->model_data;
339 u16 bit = ctl->private_value & 0xffff;
340 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
341 bool invert = (ctl->private_value >> 24) & 1;
343 value->value.integer.value[0] =
344 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
345 return 0;
348 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
349 struct snd_ctl_elem_value *value)
351 struct oxygen *chip = ctl->private_data;
352 struct xonar_wm87x6 *data = chip->model_data;
353 u16 bit = ctl->private_value & 0xffff;
354 u16 reg_value;
355 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
356 bool invert = (ctl->private_value >> 24) & 1;
357 int changed;
359 mutex_lock(&chip->mutex);
360 reg_value = data->wm8776_regs[reg_index] & ~bit;
361 if (value->value.integer.value[0] ^ invert)
362 reg_value |= bit;
363 changed = reg_value != data->wm8776_regs[reg_index];
364 if (changed)
365 wm8776_write(chip, reg_index, reg_value);
366 mutex_unlock(&chip->mutex);
367 return changed;
370 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
371 struct snd_ctl_elem_info *info)
373 static const char *const hld[16] = {
374 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
375 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
376 "341 ms", "683 ms", "1.37 s", "2.73 s",
377 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
379 static const char *const atk_lim[11] = {
380 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
381 "4 ms", "8 ms", "16 ms", "32 ms",
382 "64 ms", "128 ms", "256 ms",
384 static const char *const atk_alc[11] = {
385 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
386 "134 ms", "269 ms", "538 ms", "1.08 s",
387 "2.15 s", "4.3 s", "8.6 s",
389 static const char *const dcy_lim[11] = {
390 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
391 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
392 "307 ms", "614 ms", "1.23 s",
394 static const char *const dcy_alc[11] = {
395 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
396 "536 ms", "1.07 s", "2.14 s", "4.29 s",
397 "8.58 s", "17.2 s", "34.3 s",
399 static const char *const tranwin[8] = {
400 "0 us", "62.5 us", "125 us", "250 us",
401 "500 us", "1 ms", "2 ms", "4 ms",
403 u8 max;
404 const char *const *names;
406 max = (ctl->private_value >> 12) & 0xf;
407 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
408 info->count = 1;
409 info->value.enumerated.items = max + 1;
410 if (info->value.enumerated.item > max)
411 info->value.enumerated.item = max;
412 switch ((ctl->private_value >> 24) & 0x1f) {
413 case WM8776_ALCCTRL2:
414 names = hld;
415 break;
416 case WM8776_ALCCTRL3:
417 if (((ctl->private_value >> 20) & 0xf) == 0) {
418 if (ctl->private_value & LC_CONTROL_LIMITER)
419 names = atk_lim;
420 else
421 names = atk_alc;
422 } else {
423 if (ctl->private_value & LC_CONTROL_LIMITER)
424 names = dcy_lim;
425 else
426 names = dcy_alc;
428 break;
429 case WM8776_LIMITER:
430 names = tranwin;
431 break;
432 default:
433 return -ENXIO;
435 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
436 return 0;
439 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
440 struct snd_ctl_elem_info *info)
442 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
443 info->count = 1;
444 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
445 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
446 return 0;
449 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
451 struct oxygen *chip = ctl->private_data;
452 struct xonar_wm87x6 *data = chip->model_data;
453 unsigned int value, reg_index, mode;
454 u8 min, max, shift;
455 u16 mask, reg_value;
456 bool invert;
458 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
459 WM8776_LCSEL_LIMITER)
460 mode = LC_CONTROL_LIMITER;
461 else
462 mode = LC_CONTROL_ALC;
463 if (!(ctl->private_value & mode))
464 return;
466 value = ctl->private_value & 0xf;
467 min = (ctl->private_value >> 8) & 0xf;
468 max = (ctl->private_value >> 12) & 0xf;
469 mask = (ctl->private_value >> 16) & 0xf;
470 shift = (ctl->private_value >> 20) & 0xf;
471 reg_index = (ctl->private_value >> 24) & 0x1f;
472 invert = (ctl->private_value >> 29) & 0x1;
474 if (invert)
475 value = max - (value - min);
476 reg_value = data->wm8776_regs[reg_index];
477 reg_value &= ~(mask << shift);
478 reg_value |= value << shift;
479 wm8776_write_cached(chip, reg_index, reg_value);
482 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
484 struct oxygen *chip = ctl->private_data;
485 u8 min, max;
486 int changed;
488 min = (ctl->private_value >> 8) & 0xf;
489 max = (ctl->private_value >> 12) & 0xf;
490 if (value < min || value > max)
491 return -EINVAL;
492 mutex_lock(&chip->mutex);
493 changed = value != (ctl->private_value & 0xf);
494 if (changed) {
495 ctl->private_value = (ctl->private_value & ~0xf) | value;
496 wm8776_field_set_from_ctl(ctl);
498 mutex_unlock(&chip->mutex);
499 return changed;
502 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
503 struct snd_ctl_elem_value *value)
505 value->value.enumerated.item[0] = ctl->private_value & 0xf;
506 return 0;
509 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
510 struct snd_ctl_elem_value *value)
512 value->value.integer.value[0] = ctl->private_value & 0xf;
513 return 0;
516 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
517 struct snd_ctl_elem_value *value)
519 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
522 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
523 struct snd_ctl_elem_value *value)
525 return wm8776_field_set(ctl, value->value.integer.value[0]);
528 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
529 struct snd_ctl_elem_info *info)
531 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
532 info->count = 2;
533 info->value.integer.min = 0x79 - 60;
534 info->value.integer.max = 0x7f;
535 return 0;
538 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
539 struct snd_ctl_elem_value *value)
541 struct oxygen *chip = ctl->private_data;
542 struct xonar_wm87x6 *data = chip->model_data;
544 mutex_lock(&chip->mutex);
545 value->value.integer.value[0] =
546 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
547 value->value.integer.value[1] =
548 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
549 mutex_unlock(&chip->mutex);
550 return 0;
553 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
554 struct snd_ctl_elem_value *value)
556 struct oxygen *chip = ctl->private_data;
557 struct xonar_wm87x6 *data = chip->model_data;
558 u8 to_update;
560 mutex_lock(&chip->mutex);
561 to_update = (value->value.integer.value[0] !=
562 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
563 << 0;
564 to_update |= (value->value.integer.value[1] !=
565 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
566 << 1;
567 if (value->value.integer.value[0] == value->value.integer.value[1]) {
568 if (to_update) {
569 wm8776_write(chip, WM8776_HPMASTER,
570 value->value.integer.value[0] |
571 WM8776_HPZCEN | WM8776_UPDATE);
572 data->wm8776_regs[WM8776_HPLVOL] =
573 value->value.integer.value[0] | WM8776_HPZCEN;
574 data->wm8776_regs[WM8776_HPRVOL] =
575 value->value.integer.value[0] | WM8776_HPZCEN;
577 } else {
578 if (to_update & 1)
579 wm8776_write(chip, WM8776_HPLVOL,
580 value->value.integer.value[0] |
581 WM8776_HPZCEN |
582 ((to_update & 2) ? 0 : WM8776_UPDATE));
583 if (to_update & 2)
584 wm8776_write(chip, WM8776_HPRVOL,
585 value->value.integer.value[1] |
586 WM8776_HPZCEN | WM8776_UPDATE);
588 mutex_unlock(&chip->mutex);
589 return to_update != 0;
592 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
593 struct snd_ctl_elem_value *value)
595 struct oxygen *chip = ctl->private_data;
596 struct xonar_wm87x6 *data = chip->model_data;
597 unsigned int mux_bit = ctl->private_value;
599 value->value.integer.value[0] =
600 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
601 return 0;
604 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
605 struct snd_ctl_elem_value *value)
607 struct oxygen *chip = ctl->private_data;
608 struct xonar_wm87x6 *data = chip->model_data;
609 struct snd_kcontrol *other_ctl;
610 unsigned int mux_bit = ctl->private_value;
611 u16 reg;
612 int changed;
614 mutex_lock(&chip->mutex);
615 reg = data->wm8776_regs[WM8776_ADCMUX];
616 if (value->value.integer.value[0]) {
617 reg |= mux_bit;
618 /* line-in and mic-in are exclusive */
619 mux_bit ^= 3;
620 if (reg & mux_bit) {
621 reg &= ~mux_bit;
622 if (mux_bit == 1)
623 other_ctl = data->line_adcmux_control;
624 else
625 other_ctl = data->mic_adcmux_control;
626 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
627 &other_ctl->id);
629 } else
630 reg &= ~mux_bit;
631 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
632 if (changed) {
633 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
634 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
635 GPIO_DS_INPUT_ROUTE);
636 wm8776_write(chip, WM8776_ADCMUX, reg);
638 mutex_unlock(&chip->mutex);
639 return changed;
642 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
643 struct snd_ctl_elem_info *info)
645 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
646 info->count = 2;
647 info->value.integer.min = 0xa5;
648 info->value.integer.max = 0xff;
649 return 0;
652 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
653 struct snd_ctl_elem_value *value)
655 struct oxygen *chip = ctl->private_data;
656 struct xonar_wm87x6 *data = chip->model_data;
658 mutex_lock(&chip->mutex);
659 value->value.integer.value[0] =
660 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
661 value->value.integer.value[1] =
662 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
663 mutex_unlock(&chip->mutex);
664 return 0;
667 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
668 struct snd_ctl_elem_value *value)
670 struct oxygen *chip = ctl->private_data;
671 struct xonar_wm87x6 *data = chip->model_data;
672 int changed = 0;
674 mutex_lock(&chip->mutex);
675 changed = (value->value.integer.value[0] !=
676 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
677 (value->value.integer.value[1] !=
678 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
679 wm8776_write_cached(chip, WM8776_ADCLVOL,
680 value->value.integer.value[0] | WM8776_ZCA);
681 wm8776_write_cached(chip, WM8776_ADCRVOL,
682 value->value.integer.value[1] | WM8776_ZCA);
683 mutex_unlock(&chip->mutex);
684 return changed;
687 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
688 struct snd_ctl_elem_info *info)
690 static const char *const names[3] = {
691 "None", "Peak Limiter", "Automatic Level Control"
693 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
694 info->count = 1;
695 info->value.enumerated.items = 3;
696 if (info->value.enumerated.item >= 3)
697 info->value.enumerated.item = 2;
698 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
699 return 0;
702 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
703 struct snd_ctl_elem_value *value)
705 struct oxygen *chip = ctl->private_data;
706 struct xonar_wm87x6 *data = chip->model_data;
708 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
709 value->value.enumerated.item[0] = 0;
710 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
711 WM8776_LCSEL_LIMITER)
712 value->value.enumerated.item[0] = 1;
713 else
714 value->value.enumerated.item[0] = 2;
715 return 0;
718 static void activate_control(struct oxygen *chip,
719 struct snd_kcontrol *ctl, unsigned int mode)
721 unsigned int access;
723 if (ctl->private_value & mode)
724 access = 0;
725 else
726 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
727 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
728 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
729 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
733 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
734 struct snd_ctl_elem_value *value)
736 struct oxygen *chip = ctl->private_data;
737 struct xonar_wm87x6 *data = chip->model_data;
738 unsigned int mode = 0, i;
739 u16 ctrl1, ctrl2;
740 int changed;
742 if (value->value.enumerated.item[0] >= 3)
743 return -EINVAL;
744 mutex_lock(&chip->mutex);
745 changed = value->value.enumerated.item[0] != ctl->private_value;
746 if (changed) {
747 ctl->private_value = value->value.enumerated.item[0];
748 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
749 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
750 switch (value->value.enumerated.item[0]) {
751 default:
752 wm8776_write_cached(chip, WM8776_ALCCTRL2,
753 ctrl2 & ~WM8776_LCEN);
754 break;
755 case 1:
756 wm8776_write_cached(chip, WM8776_ALCCTRL1,
757 (ctrl1 & ~WM8776_LCSEL_MASK) |
758 WM8776_LCSEL_LIMITER);
759 wm8776_write_cached(chip, WM8776_ALCCTRL2,
760 ctrl2 | WM8776_LCEN);
761 mode = LC_CONTROL_LIMITER;
762 break;
763 case 2:
764 wm8776_write_cached(chip, WM8776_ALCCTRL1,
765 (ctrl1 & ~WM8776_LCSEL_MASK) |
766 WM8776_LCSEL_ALC_STEREO);
767 wm8776_write_cached(chip, WM8776_ALCCTRL2,
768 ctrl2 | WM8776_LCEN);
769 mode = LC_CONTROL_ALC;
770 break;
772 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
773 activate_control(chip, data->lc_controls[i], mode);
775 mutex_unlock(&chip->mutex);
776 return changed;
779 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
781 static const char *const names[2] = {
782 "None", "High-pass Filter"
785 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
786 info->count = 1;
787 info->value.enumerated.items = 2;
788 if (info->value.enumerated.item >= 2)
789 info->value.enumerated.item = 1;
790 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
791 return 0;
794 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
796 struct oxygen *chip = ctl->private_data;
797 struct xonar_wm87x6 *data = chip->model_data;
799 value->value.enumerated.item[0] =
800 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
801 return 0;
804 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
806 struct oxygen *chip = ctl->private_data;
807 struct xonar_wm87x6 *data = chip->model_data;
808 unsigned int reg;
809 int changed;
811 mutex_lock(&chip->mutex);
812 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
813 if (!value->value.enumerated.item[0])
814 reg |= WM8776_ADCHPD;
815 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
816 if (changed)
817 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
818 mutex_unlock(&chip->mutex);
819 return changed;
822 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
824 .name = xname, \
825 .info = snd_ctl_boolean_mono_info, \
826 .get = wm8776_bit_switch_get, \
827 .put = wm8776_bit_switch_put, \
828 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
830 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
832 .name = xname, \
833 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
834 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
835 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
836 _WM8776_FIELD_CTL(xname " Capture Enum", \
837 reg, shift, init, min, max, mask, flags), \
838 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
839 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
840 .info = wm8776_field_enum_info, \
841 .get = wm8776_field_enum_get, \
842 .put = wm8776_field_enum_put, \
844 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
845 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
846 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
847 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
848 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
849 .info = wm8776_field_volume_info, \
850 .get = wm8776_field_volume_get, \
851 .put = wm8776_field_volume_put, \
852 .tlv = { .p = tlv_p }, \
855 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
856 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
857 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
858 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
859 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
860 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
861 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
862 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
864 static const struct snd_kcontrol_new ds_controls[] = {
866 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
867 .name = "Headphone Playback Volume",
868 .info = wm8776_hp_vol_info,
869 .get = wm8776_hp_vol_get,
870 .put = wm8776_hp_vol_put,
871 .tlv = { .p = wm8776_hp_db_scale },
873 WM8776_BIT_SWITCH("Headphone Playback Switch",
874 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877 .name = "Input Capture Volume",
878 .info = wm8776_input_vol_info,
879 .get = wm8776_input_vol_get,
880 .put = wm8776_input_vol_put,
881 .tlv = { .p = wm8776_adc_db_scale },
884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
885 .name = "Line Capture Switch",
886 .info = snd_ctl_boolean_mono_info,
887 .get = wm8776_input_mux_get,
888 .put = wm8776_input_mux_put,
889 .private_value = 1 << 0,
892 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
893 .name = "Mic Capture Switch",
894 .info = snd_ctl_boolean_mono_info,
895 .get = wm8776_input_mux_get,
896 .put = wm8776_input_mux_put,
897 .private_value = 1 << 1,
899 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .name = "ADC Filter Capture Enum",
903 .info = hpf_info,
904 .get = hpf_get,
905 .put = hpf_put,
908 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
909 .name = "Level Control Capture Enum",
910 .info = wm8776_level_control_info,
911 .get = wm8776_level_control_get,
912 .put = wm8776_level_control_put,
913 .private_value = 0,
916 static const struct snd_kcontrol_new lc_controls[] = {
917 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
918 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
919 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
920 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
921 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
922 LC_CONTROL_LIMITER),
923 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
924 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
925 LC_CONTROL_LIMITER),
926 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
927 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
928 LC_CONTROL_LIMITER),
929 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
930 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
931 LC_CONTROL_LIMITER,
932 wm8776_maxatten_lim_db_scale),
933 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
934 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
935 LC_CONTROL_ALC, wm8776_lct_db_scale),
936 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
937 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
938 LC_CONTROL_ALC),
939 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
940 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
941 LC_CONTROL_ALC),
942 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
943 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
944 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
945 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
946 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
947 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
948 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
949 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
950 LC_CONTROL_ALC),
951 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
952 WM8776_NOISEGATE, WM8776_NGAT, 0,
953 LC_CONTROL_ALC),
954 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
955 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
956 LC_CONTROL_ALC, wm8776_ngth_db_scale),
959 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
961 if (!strncmp(template->name, "CD Capture ", 11))
962 return 1; /* no CD input */
963 return 0;
966 static int xonar_ds_mixer_init(struct oxygen *chip)
968 struct xonar_wm87x6 *data = chip->model_data;
969 unsigned int i;
970 struct snd_kcontrol *ctl;
971 int err;
973 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
974 ctl = snd_ctl_new1(&ds_controls[i], chip);
975 if (!ctl)
976 return -ENOMEM;
977 err = snd_ctl_add(chip->card, ctl);
978 if (err < 0)
979 return err;
980 if (!strcmp(ctl->id.name, "Line Capture Switch"))
981 data->line_adcmux_control = ctl;
982 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
983 data->mic_adcmux_control = ctl;
985 if (!data->line_adcmux_control || !data->mic_adcmux_control)
986 return -ENXIO;
987 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
988 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
989 ctl = snd_ctl_new1(&lc_controls[i], chip);
990 if (!ctl)
991 return -ENOMEM;
992 err = snd_ctl_add(chip->card, ctl);
993 if (err < 0)
994 return err;
995 data->lc_controls[i] = ctl;
997 return 0;
1000 static const struct oxygen_model model_xonar_ds = {
1001 .shortname = "Xonar DS",
1002 .longname = "Asus Virtuoso 200",
1003 .chip = "AV200",
1004 .init = xonar_ds_init,
1005 .control_filter = xonar_ds_control_filter,
1006 .mixer_init = xonar_ds_mixer_init,
1007 .cleanup = xonar_ds_cleanup,
1008 .suspend = xonar_ds_suspend,
1009 .resume = xonar_ds_resume,
1010 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1011 .get_i2s_mclk = oxygen_default_i2s_mclk,
1012 .set_dac_params = set_wm87x6_dac_params,
1013 .set_adc_params = set_wm8776_adc_params,
1014 .update_dac_volume = update_wm87x6_volume,
1015 .update_dac_mute = update_wm87x6_mute,
1016 .gpio_changed = xonar_ds_gpio_changed,
1017 .dac_tlv = wm87x6_dac_db_scale,
1018 .model_data_size = sizeof(struct xonar_wm87x6),
1019 .device_config = PLAYBACK_0_TO_I2S |
1020 PLAYBACK_1_TO_SPDIF |
1021 CAPTURE_0_FROM_I2S_1,
1022 .dac_channels = 8,
1023 .dac_volume_min = 255 - 2*60,
1024 .dac_volume_max = 255,
1025 .function_flags = OXYGEN_FUNCTION_SPI,
1026 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1027 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1030 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1031 const struct pci_device_id *id)
1033 switch (id->subdevice) {
1034 case 0x838e:
1035 chip->model = model_xonar_ds;
1036 break;
1037 default:
1038 return -EINVAL;
1040 return 0;