ALSA: virtuoso: automatically handle Xonar DS headphone routing
[firewire-audio.git] / sound / pci / oxygen / xonar_wm87x6.c
blobcee07fe3aa3640cb093ec1d1c00d3ec38c169bff
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, 0 = plugged
29 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
30 * GPIO 7 -> enable output to front L/R speaker channels
31 * GPIO 8 -> enable output to other speaker channels and front panel headphone
33 * WM8766:
35 * input 1 <- line
36 * input 2 <- mic
37 * input 3 <- front mic
38 * input 4 <- aux
41 #include <linux/pci.h>
42 #include <linux/delay.h>
43 #include <sound/control.h>
44 #include <sound/core.h>
45 #include <sound/jack.h>
46 #include <sound/pcm.h>
47 #include <sound/pcm_params.h>
48 #include <sound/tlv.h>
49 #include "xonar.h"
50 #include "wm8776.h"
51 #include "wm8766.h"
53 #define GPIO_DS_HP_DETECT 0x0010
54 #define GPIO_DS_INPUT_ROUTE 0x0040
55 #define GPIO_DS_OUTPUT_FRONTLR 0x0080
56 #define GPIO_DS_OUTPUT_ENABLE 0x0100
58 #define LC_CONTROL_LIMITER 0x40000000
59 #define LC_CONTROL_ALC 0x20000000
61 struct xonar_wm87x6 {
62 struct xonar_generic generic;
63 u16 wm8776_regs[0x17];
64 u16 wm8766_regs[0x10];
65 struct snd_kcontrol *line_adcmux_control;
66 struct snd_kcontrol *mic_adcmux_control;
67 struct snd_kcontrol *lc_controls[13];
68 struct snd_jack *hp_jack;
71 static void wm8776_write(struct oxygen *chip,
72 unsigned int reg, unsigned int value)
74 struct xonar_wm87x6 *data = chip->model_data;
76 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
77 OXYGEN_SPI_DATA_LENGTH_2 |
78 OXYGEN_SPI_CLOCK_160 |
79 (1 << OXYGEN_SPI_CODEC_SHIFT) |
80 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
81 (reg << 9) | value);
82 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
83 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
84 value &= ~WM8776_UPDATE;
85 data->wm8776_regs[reg] = value;
89 static void wm8776_write_cached(struct oxygen *chip,
90 unsigned int reg, unsigned int value)
92 struct xonar_wm87x6 *data = chip->model_data;
94 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
95 value != data->wm8776_regs[reg])
96 wm8776_write(chip, reg, value);
99 static void wm8766_write(struct oxygen *chip,
100 unsigned int reg, unsigned int value)
102 struct xonar_wm87x6 *data = chip->model_data;
104 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
105 OXYGEN_SPI_DATA_LENGTH_2 |
106 OXYGEN_SPI_CLOCK_160 |
107 (0 << OXYGEN_SPI_CODEC_SHIFT) |
108 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
109 (reg << 9) | value);
110 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
111 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113 value &= ~WM8766_UPDATE;
114 data->wm8766_regs[reg] = value;
118 static void wm8766_write_cached(struct oxygen *chip,
119 unsigned int reg, unsigned int value)
121 struct xonar_wm87x6 *data = chip->model_data;
123 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
124 value != data->wm8766_regs[reg])
125 wm8766_write(chip, reg, value);
128 static void wm8776_registers_init(struct oxygen *chip)
130 struct xonar_wm87x6 *data = chip->model_data;
132 wm8776_write(chip, WM8776_RESET, 0);
133 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
134 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
135 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
136 wm8776_write(chip, WM8776_DACIFCTRL,
137 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
138 wm8776_write(chip, WM8776_ADCIFCTRL,
139 data->wm8776_regs[WM8776_ADCIFCTRL]);
140 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
141 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
142 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
143 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
144 WM8776_UPDATE);
145 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
146 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
147 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
148 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
149 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
152 static void wm8766_registers_init(struct oxygen *chip)
154 struct xonar_wm87x6 *data = chip->model_data;
156 wm8766_write(chip, WM8766_RESET, 0);
157 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
158 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
159 wm8766_write(chip, WM8766_DAC_CTRL2,
160 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
161 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
162 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
163 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
164 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
165 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
166 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
169 static void wm8776_init(struct oxygen *chip)
171 struct xonar_wm87x6 *data = chip->model_data;
173 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
174 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
175 data->wm8776_regs[WM8776_ADCIFCTRL] =
176 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
177 data->wm8776_regs[WM8776_MSTRCTRL] =
178 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
179 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
180 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
181 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
182 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
183 wm8776_registers_init(chip);
186 static void wm8766_init(struct oxygen *chip)
188 struct xonar_wm87x6 *data = chip->model_data;
190 data->wm8766_regs[WM8766_DAC_CTRL] =
191 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
192 wm8766_registers_init(chip);
195 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
197 struct xonar_wm87x6 *data = chip->model_data;
198 bool hp_plugged;
199 unsigned int reg;
201 mutex_lock(&chip->mutex);
203 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
204 GPIO_DS_HP_DETECT);
206 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
207 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
208 GPIO_DS_OUTPUT_FRONTLR);
210 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
211 if (hp_plugged)
212 reg |= WM8766_MUTEALL;
213 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
215 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
217 mutex_unlock(&chip->mutex);
220 static void xonar_ds_init(struct oxygen *chip)
222 struct xonar_wm87x6 *data = chip->model_data;
224 data->generic.anti_pop_delay = 300;
225 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
227 wm8776_init(chip);
228 wm8766_init(chip);
230 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
231 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
232 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
233 GPIO_DS_HP_DETECT);
234 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
235 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
236 chip->interrupt_mask |= OXYGEN_INT_GPIO;
238 xonar_enable_output(chip);
240 snd_jack_new(chip->card, "Headphone",
241 SND_JACK_HEADPHONE, &data->hp_jack);
242 xonar_ds_handle_hp_jack(chip);
244 snd_component_add(chip->card, "WM8776");
245 snd_component_add(chip->card, "WM8766");
248 static void xonar_ds_cleanup(struct oxygen *chip)
250 xonar_disable_output(chip);
251 wm8776_write(chip, WM8776_RESET, 0);
254 static void xonar_ds_suspend(struct oxygen *chip)
256 xonar_ds_cleanup(chip);
259 static void xonar_ds_resume(struct oxygen *chip)
261 wm8776_registers_init(chip);
262 wm8766_registers_init(chip);
263 xonar_enable_output(chip);
264 xonar_ds_handle_hp_jack(chip);
267 static void wm8776_adc_hardware_filter(unsigned int channel,
268 struct snd_pcm_hardware *hardware)
270 if (channel == PCM_A) {
271 hardware->rates = SNDRV_PCM_RATE_32000 |
272 SNDRV_PCM_RATE_44100 |
273 SNDRV_PCM_RATE_48000 |
274 SNDRV_PCM_RATE_64000 |
275 SNDRV_PCM_RATE_88200 |
276 SNDRV_PCM_RATE_96000;
277 hardware->rate_max = 96000;
281 static void set_wm87x6_dac_params(struct oxygen *chip,
282 struct snd_pcm_hw_params *params)
286 static void set_wm8776_adc_params(struct oxygen *chip,
287 struct snd_pcm_hw_params *params)
289 u16 reg;
291 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
292 if (params_rate(params) > 48000)
293 reg |= WM8776_ADCOSR;
294 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
297 static void update_wm8776_volume(struct oxygen *chip)
299 struct xonar_wm87x6 *data = chip->model_data;
300 u8 to_change;
302 if (chip->dac_volume[0] == chip->dac_volume[1]) {
303 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
304 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
305 wm8776_write(chip, WM8776_DACMASTER,
306 chip->dac_volume[0] | WM8776_UPDATE);
307 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
308 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
310 } else {
311 to_change = (chip->dac_volume[0] !=
312 data->wm8776_regs[WM8776_DACLVOL]) << 0;
313 to_change |= (chip->dac_volume[1] !=
314 data->wm8776_regs[WM8776_DACLVOL]) << 1;
315 if (to_change & 1)
316 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
317 ((to_change & 2) ? 0 : WM8776_UPDATE));
318 if (to_change & 2)
319 wm8776_write(chip, WM8776_DACRVOL,
320 chip->dac_volume[1] | WM8776_UPDATE);
324 static void update_wm87x6_volume(struct oxygen *chip)
326 static const u8 wm8766_regs[6] = {
327 WM8766_LDA1, WM8766_RDA1,
328 WM8766_LDA2, WM8766_RDA2,
329 WM8766_LDA3, WM8766_RDA3,
331 struct xonar_wm87x6 *data = chip->model_data;
332 unsigned int i;
333 u8 to_change;
335 update_wm8776_volume(chip);
336 if (chip->dac_volume[2] == chip->dac_volume[3] &&
337 chip->dac_volume[2] == chip->dac_volume[4] &&
338 chip->dac_volume[2] == chip->dac_volume[5] &&
339 chip->dac_volume[2] == chip->dac_volume[6] &&
340 chip->dac_volume[2] == chip->dac_volume[7]) {
341 to_change = 0;
342 for (i = 0; i < 6; ++i)
343 if (chip->dac_volume[2] !=
344 data->wm8766_regs[wm8766_regs[i]])
345 to_change = 1;
346 if (to_change) {
347 wm8766_write(chip, WM8766_MASTDA,
348 chip->dac_volume[2] | WM8766_UPDATE);
349 for (i = 0; i < 6; ++i)
350 data->wm8766_regs[wm8766_regs[i]] =
351 chip->dac_volume[2];
353 } else {
354 to_change = 0;
355 for (i = 0; i < 6; ++i)
356 to_change |= (chip->dac_volume[2 + i] !=
357 data->wm8766_regs[wm8766_regs[i]]) << i;
358 for (i = 0; i < 6; ++i)
359 if (to_change & (1 << i))
360 wm8766_write(chip, wm8766_regs[i],
361 chip->dac_volume[2 + i] |
362 ((to_change & (0x3e << i))
363 ? 0 : WM8766_UPDATE));
367 static void update_wm8776_mute(struct oxygen *chip)
369 wm8776_write_cached(chip, WM8776_DACMUTE,
370 chip->dac_mute ? WM8776_DMUTE : 0);
373 static void update_wm87x6_mute(struct oxygen *chip)
375 update_wm8776_mute(chip);
376 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
377 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
380 static void xonar_ds_gpio_changed(struct oxygen *chip)
382 xonar_ds_handle_hp_jack(chip);
385 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
386 struct snd_ctl_elem_value *value)
388 struct oxygen *chip = ctl->private_data;
389 struct xonar_wm87x6 *data = chip->model_data;
390 u16 bit = ctl->private_value & 0xffff;
391 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
392 bool invert = (ctl->private_value >> 24) & 1;
394 value->value.integer.value[0] =
395 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
396 return 0;
399 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
400 struct snd_ctl_elem_value *value)
402 struct oxygen *chip = ctl->private_data;
403 struct xonar_wm87x6 *data = chip->model_data;
404 u16 bit = ctl->private_value & 0xffff;
405 u16 reg_value;
406 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
407 bool invert = (ctl->private_value >> 24) & 1;
408 int changed;
410 mutex_lock(&chip->mutex);
411 reg_value = data->wm8776_regs[reg_index] & ~bit;
412 if (value->value.integer.value[0] ^ invert)
413 reg_value |= bit;
414 changed = reg_value != data->wm8776_regs[reg_index];
415 if (changed)
416 wm8776_write(chip, reg_index, reg_value);
417 mutex_unlock(&chip->mutex);
418 return changed;
421 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
422 struct snd_ctl_elem_info *info)
424 static const char *const hld[16] = {
425 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
426 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
427 "341 ms", "683 ms", "1.37 s", "2.73 s",
428 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
430 static const char *const atk_lim[11] = {
431 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
432 "4 ms", "8 ms", "16 ms", "32 ms",
433 "64 ms", "128 ms", "256 ms",
435 static const char *const atk_alc[11] = {
436 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
437 "134 ms", "269 ms", "538 ms", "1.08 s",
438 "2.15 s", "4.3 s", "8.6 s",
440 static const char *const dcy_lim[11] = {
441 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
442 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
443 "307 ms", "614 ms", "1.23 s",
445 static const char *const dcy_alc[11] = {
446 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
447 "536 ms", "1.07 s", "2.14 s", "4.29 s",
448 "8.58 s", "17.2 s", "34.3 s",
450 static const char *const tranwin[8] = {
451 "0 us", "62.5 us", "125 us", "250 us",
452 "500 us", "1 ms", "2 ms", "4 ms",
454 u8 max;
455 const char *const *names;
457 max = (ctl->private_value >> 12) & 0xf;
458 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
459 info->count = 1;
460 info->value.enumerated.items = max + 1;
461 if (info->value.enumerated.item > max)
462 info->value.enumerated.item = max;
463 switch ((ctl->private_value >> 24) & 0x1f) {
464 case WM8776_ALCCTRL2:
465 names = hld;
466 break;
467 case WM8776_ALCCTRL3:
468 if (((ctl->private_value >> 20) & 0xf) == 0) {
469 if (ctl->private_value & LC_CONTROL_LIMITER)
470 names = atk_lim;
471 else
472 names = atk_alc;
473 } else {
474 if (ctl->private_value & LC_CONTROL_LIMITER)
475 names = dcy_lim;
476 else
477 names = dcy_alc;
479 break;
480 case WM8776_LIMITER:
481 names = tranwin;
482 break;
483 default:
484 return -ENXIO;
486 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
487 return 0;
490 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
491 struct snd_ctl_elem_info *info)
493 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
494 info->count = 1;
495 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
496 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
497 return 0;
500 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
502 struct oxygen *chip = ctl->private_data;
503 struct xonar_wm87x6 *data = chip->model_data;
504 unsigned int value, reg_index, mode;
505 u8 min, max, shift;
506 u16 mask, reg_value;
507 bool invert;
509 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
510 WM8776_LCSEL_LIMITER)
511 mode = LC_CONTROL_LIMITER;
512 else
513 mode = LC_CONTROL_ALC;
514 if (!(ctl->private_value & mode))
515 return;
517 value = ctl->private_value & 0xf;
518 min = (ctl->private_value >> 8) & 0xf;
519 max = (ctl->private_value >> 12) & 0xf;
520 mask = (ctl->private_value >> 16) & 0xf;
521 shift = (ctl->private_value >> 20) & 0xf;
522 reg_index = (ctl->private_value >> 24) & 0x1f;
523 invert = (ctl->private_value >> 29) & 0x1;
525 if (invert)
526 value = max - (value - min);
527 reg_value = data->wm8776_regs[reg_index];
528 reg_value &= ~(mask << shift);
529 reg_value |= value << shift;
530 wm8776_write_cached(chip, reg_index, reg_value);
533 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
535 struct oxygen *chip = ctl->private_data;
536 u8 min, max;
537 int changed;
539 min = (ctl->private_value >> 8) & 0xf;
540 max = (ctl->private_value >> 12) & 0xf;
541 if (value < min || value > max)
542 return -EINVAL;
543 mutex_lock(&chip->mutex);
544 changed = value != (ctl->private_value & 0xf);
545 if (changed) {
546 ctl->private_value = (ctl->private_value & ~0xf) | value;
547 wm8776_field_set_from_ctl(ctl);
549 mutex_unlock(&chip->mutex);
550 return changed;
553 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
554 struct snd_ctl_elem_value *value)
556 value->value.enumerated.item[0] = ctl->private_value & 0xf;
557 return 0;
560 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
561 struct snd_ctl_elem_value *value)
563 value->value.integer.value[0] = ctl->private_value & 0xf;
564 return 0;
567 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
568 struct snd_ctl_elem_value *value)
570 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
573 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
574 struct snd_ctl_elem_value *value)
576 return wm8776_field_set(ctl, value->value.integer.value[0]);
579 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
580 struct snd_ctl_elem_info *info)
582 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
583 info->count = 2;
584 info->value.integer.min = 0x79 - 60;
585 info->value.integer.max = 0x7f;
586 return 0;
589 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
590 struct snd_ctl_elem_value *value)
592 struct oxygen *chip = ctl->private_data;
593 struct xonar_wm87x6 *data = chip->model_data;
595 mutex_lock(&chip->mutex);
596 value->value.integer.value[0] =
597 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
598 value->value.integer.value[1] =
599 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
600 mutex_unlock(&chip->mutex);
601 return 0;
604 static int wm8776_hp_vol_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 u8 to_update;
611 mutex_lock(&chip->mutex);
612 to_update = (value->value.integer.value[0] !=
613 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
614 << 0;
615 to_update |= (value->value.integer.value[1] !=
616 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
617 << 1;
618 if (value->value.integer.value[0] == value->value.integer.value[1]) {
619 if (to_update) {
620 wm8776_write(chip, WM8776_HPMASTER,
621 value->value.integer.value[0] |
622 WM8776_HPZCEN | WM8776_UPDATE);
623 data->wm8776_regs[WM8776_HPLVOL] =
624 value->value.integer.value[0] | WM8776_HPZCEN;
625 data->wm8776_regs[WM8776_HPRVOL] =
626 value->value.integer.value[0] | WM8776_HPZCEN;
628 } else {
629 if (to_update & 1)
630 wm8776_write(chip, WM8776_HPLVOL,
631 value->value.integer.value[0] |
632 WM8776_HPZCEN |
633 ((to_update & 2) ? 0 : WM8776_UPDATE));
634 if (to_update & 2)
635 wm8776_write(chip, WM8776_HPRVOL,
636 value->value.integer.value[1] |
637 WM8776_HPZCEN | WM8776_UPDATE);
639 mutex_unlock(&chip->mutex);
640 return to_update != 0;
643 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
644 struct snd_ctl_elem_value *value)
646 struct oxygen *chip = ctl->private_data;
647 struct xonar_wm87x6 *data = chip->model_data;
648 unsigned int mux_bit = ctl->private_value;
650 value->value.integer.value[0] =
651 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
652 return 0;
655 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
656 struct snd_ctl_elem_value *value)
658 struct oxygen *chip = ctl->private_data;
659 struct xonar_wm87x6 *data = chip->model_data;
660 struct snd_kcontrol *other_ctl;
661 unsigned int mux_bit = ctl->private_value;
662 u16 reg;
663 int changed;
665 mutex_lock(&chip->mutex);
666 reg = data->wm8776_regs[WM8776_ADCMUX];
667 if (value->value.integer.value[0]) {
668 reg |= mux_bit;
669 /* line-in and mic-in are exclusive */
670 mux_bit ^= 3;
671 if (reg & mux_bit) {
672 reg &= ~mux_bit;
673 if (mux_bit == 1)
674 other_ctl = data->line_adcmux_control;
675 else
676 other_ctl = data->mic_adcmux_control;
677 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
678 &other_ctl->id);
680 } else
681 reg &= ~mux_bit;
682 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
683 if (changed) {
684 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
685 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
686 GPIO_DS_INPUT_ROUTE);
687 wm8776_write(chip, WM8776_ADCMUX, reg);
689 mutex_unlock(&chip->mutex);
690 return changed;
693 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
694 struct snd_ctl_elem_info *info)
696 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
697 info->count = 2;
698 info->value.integer.min = 0xa5;
699 info->value.integer.max = 0xff;
700 return 0;
703 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
704 struct snd_ctl_elem_value *value)
706 struct oxygen *chip = ctl->private_data;
707 struct xonar_wm87x6 *data = chip->model_data;
709 mutex_lock(&chip->mutex);
710 value->value.integer.value[0] =
711 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
712 value->value.integer.value[1] =
713 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
714 mutex_unlock(&chip->mutex);
715 return 0;
718 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
719 struct snd_ctl_elem_value *value)
721 struct oxygen *chip = ctl->private_data;
722 struct xonar_wm87x6 *data = chip->model_data;
723 int changed = 0;
725 mutex_lock(&chip->mutex);
726 changed = (value->value.integer.value[0] !=
727 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
728 (value->value.integer.value[1] !=
729 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
730 wm8776_write_cached(chip, WM8776_ADCLVOL,
731 value->value.integer.value[0] | WM8776_ZCA);
732 wm8776_write_cached(chip, WM8776_ADCRVOL,
733 value->value.integer.value[1] | WM8776_ZCA);
734 mutex_unlock(&chip->mutex);
735 return changed;
738 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
739 struct snd_ctl_elem_info *info)
741 static const char *const names[3] = {
742 "None", "Peak Limiter", "Automatic Level Control"
744 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
745 info->count = 1;
746 info->value.enumerated.items = 3;
747 if (info->value.enumerated.item >= 3)
748 info->value.enumerated.item = 2;
749 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
750 return 0;
753 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
754 struct snd_ctl_elem_value *value)
756 struct oxygen *chip = ctl->private_data;
757 struct xonar_wm87x6 *data = chip->model_data;
759 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
760 value->value.enumerated.item[0] = 0;
761 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
762 WM8776_LCSEL_LIMITER)
763 value->value.enumerated.item[0] = 1;
764 else
765 value->value.enumerated.item[0] = 2;
766 return 0;
769 static void activate_control(struct oxygen *chip,
770 struct snd_kcontrol *ctl, unsigned int mode)
772 unsigned int access;
774 if (ctl->private_value & mode)
775 access = 0;
776 else
777 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
778 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
779 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
780 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
784 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
785 struct snd_ctl_elem_value *value)
787 struct oxygen *chip = ctl->private_data;
788 struct xonar_wm87x6 *data = chip->model_data;
789 unsigned int mode = 0, i;
790 u16 ctrl1, ctrl2;
791 int changed;
793 if (value->value.enumerated.item[0] >= 3)
794 return -EINVAL;
795 mutex_lock(&chip->mutex);
796 changed = value->value.enumerated.item[0] != ctl->private_value;
797 if (changed) {
798 ctl->private_value = value->value.enumerated.item[0];
799 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
800 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
801 switch (value->value.enumerated.item[0]) {
802 default:
803 wm8776_write_cached(chip, WM8776_ALCCTRL2,
804 ctrl2 & ~WM8776_LCEN);
805 break;
806 case 1:
807 wm8776_write_cached(chip, WM8776_ALCCTRL1,
808 (ctrl1 & ~WM8776_LCSEL_MASK) |
809 WM8776_LCSEL_LIMITER);
810 wm8776_write_cached(chip, WM8776_ALCCTRL2,
811 ctrl2 | WM8776_LCEN);
812 mode = LC_CONTROL_LIMITER;
813 break;
814 case 2:
815 wm8776_write_cached(chip, WM8776_ALCCTRL1,
816 (ctrl1 & ~WM8776_LCSEL_MASK) |
817 WM8776_LCSEL_ALC_STEREO);
818 wm8776_write_cached(chip, WM8776_ALCCTRL2,
819 ctrl2 | WM8776_LCEN);
820 mode = LC_CONTROL_ALC;
821 break;
823 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
824 activate_control(chip, data->lc_controls[i], mode);
826 mutex_unlock(&chip->mutex);
827 return changed;
830 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
832 static const char *const names[2] = {
833 "None", "High-pass Filter"
836 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
837 info->count = 1;
838 info->value.enumerated.items = 2;
839 if (info->value.enumerated.item >= 2)
840 info->value.enumerated.item = 1;
841 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
842 return 0;
845 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
847 struct oxygen *chip = ctl->private_data;
848 struct xonar_wm87x6 *data = chip->model_data;
850 value->value.enumerated.item[0] =
851 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
852 return 0;
855 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
857 struct oxygen *chip = ctl->private_data;
858 struct xonar_wm87x6 *data = chip->model_data;
859 unsigned int reg;
860 int changed;
862 mutex_lock(&chip->mutex);
863 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
864 if (!value->value.enumerated.item[0])
865 reg |= WM8776_ADCHPD;
866 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
867 if (changed)
868 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
869 mutex_unlock(&chip->mutex);
870 return changed;
873 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
875 .name = xname, \
876 .info = snd_ctl_boolean_mono_info, \
877 .get = wm8776_bit_switch_get, \
878 .put = wm8776_bit_switch_put, \
879 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
881 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
882 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
883 .name = xname, \
884 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
885 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
886 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
887 _WM8776_FIELD_CTL(xname " Capture Enum", \
888 reg, shift, init, min, max, mask, flags), \
889 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
890 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
891 .info = wm8776_field_enum_info, \
892 .get = wm8776_field_enum_get, \
893 .put = wm8776_field_enum_put, \
895 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
896 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
897 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
898 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
899 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
900 .info = wm8776_field_volume_info, \
901 .get = wm8776_field_volume_get, \
902 .put = wm8776_field_volume_put, \
903 .tlv = { .p = tlv_p }, \
906 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
907 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
908 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
909 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
910 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
911 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
912 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
913 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
915 static const struct snd_kcontrol_new ds_controls[] = {
917 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
918 .name = "Headphone Playback Volume",
919 .info = wm8776_hp_vol_info,
920 .get = wm8776_hp_vol_get,
921 .put = wm8776_hp_vol_put,
922 .tlv = { .p = wm8776_hp_db_scale },
924 WM8776_BIT_SWITCH("Headphone Playback Switch",
925 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
927 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
928 .name = "Input Capture Volume",
929 .info = wm8776_input_vol_info,
930 .get = wm8776_input_vol_get,
931 .put = wm8776_input_vol_put,
932 .tlv = { .p = wm8776_adc_db_scale },
935 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
936 .name = "Line Capture Switch",
937 .info = snd_ctl_boolean_mono_info,
938 .get = wm8776_input_mux_get,
939 .put = wm8776_input_mux_put,
940 .private_value = 1 << 0,
943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
944 .name = "Mic Capture Switch",
945 .info = snd_ctl_boolean_mono_info,
946 .get = wm8776_input_mux_get,
947 .put = wm8776_input_mux_put,
948 .private_value = 1 << 1,
950 WM8776_BIT_SWITCH("Front Mic Capture Switch",
951 WM8776_ADCMUX, 1 << 2, 0, 0),
952 WM8776_BIT_SWITCH("Aux Capture Switch",
953 WM8776_ADCMUX, 1 << 3, 0, 0),
955 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
956 .name = "ADC Filter Capture Enum",
957 .info = hpf_info,
958 .get = hpf_get,
959 .put = hpf_put,
962 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
963 .name = "Level Control Capture Enum",
964 .info = wm8776_level_control_info,
965 .get = wm8776_level_control_get,
966 .put = wm8776_level_control_put,
967 .private_value = 0,
970 static const struct snd_kcontrol_new lc_controls[] = {
971 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
972 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
973 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
974 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
975 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
976 LC_CONTROL_LIMITER),
977 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
978 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
979 LC_CONTROL_LIMITER),
980 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
981 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
982 LC_CONTROL_LIMITER),
983 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
984 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
985 LC_CONTROL_LIMITER,
986 wm8776_maxatten_lim_db_scale),
987 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
988 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
989 LC_CONTROL_ALC, wm8776_lct_db_scale),
990 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
991 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
992 LC_CONTROL_ALC),
993 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
994 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
995 LC_CONTROL_ALC),
996 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
997 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
998 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
999 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1000 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1001 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1002 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1003 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1004 LC_CONTROL_ALC),
1005 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1006 WM8776_NOISEGATE, WM8776_NGAT, 0,
1007 LC_CONTROL_ALC),
1008 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1009 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1010 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1013 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
1015 if (!strncmp(template->name, "CD Capture ", 11))
1016 return 1; /* no CD input */
1017 return 0;
1020 static int xonar_ds_mixer_init(struct oxygen *chip)
1022 struct xonar_wm87x6 *data = chip->model_data;
1023 unsigned int i;
1024 struct snd_kcontrol *ctl;
1025 int err;
1027 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1028 ctl = snd_ctl_new1(&ds_controls[i], chip);
1029 if (!ctl)
1030 return -ENOMEM;
1031 err = snd_ctl_add(chip->card, ctl);
1032 if (err < 0)
1033 return err;
1034 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1035 data->line_adcmux_control = ctl;
1036 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1037 data->mic_adcmux_control = ctl;
1039 if (!data->line_adcmux_control || !data->mic_adcmux_control)
1040 return -ENXIO;
1041 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1042 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1043 ctl = snd_ctl_new1(&lc_controls[i], chip);
1044 if (!ctl)
1045 return -ENOMEM;
1046 err = snd_ctl_add(chip->card, ctl);
1047 if (err < 0)
1048 return err;
1049 data->lc_controls[i] = ctl;
1051 return 0;
1054 static const struct oxygen_model model_xonar_ds = {
1055 .shortname = "Xonar DS",
1056 .longname = "Asus Virtuoso 200",
1057 .chip = "AV200",
1058 .init = xonar_ds_init,
1059 .control_filter = xonar_ds_control_filter,
1060 .mixer_init = xonar_ds_mixer_init,
1061 .cleanup = xonar_ds_cleanup,
1062 .suspend = xonar_ds_suspend,
1063 .resume = xonar_ds_resume,
1064 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1065 .get_i2s_mclk = oxygen_default_i2s_mclk,
1066 .set_dac_params = set_wm87x6_dac_params,
1067 .set_adc_params = set_wm8776_adc_params,
1068 .update_dac_volume = update_wm87x6_volume,
1069 .update_dac_mute = update_wm87x6_mute,
1070 .gpio_changed = xonar_ds_gpio_changed,
1071 .dac_tlv = wm87x6_dac_db_scale,
1072 .model_data_size = sizeof(struct xonar_wm87x6),
1073 .device_config = PLAYBACK_0_TO_I2S |
1074 PLAYBACK_1_TO_SPDIF |
1075 CAPTURE_0_FROM_I2S_1,
1076 .dac_channels = 8,
1077 .dac_volume_min = 255 - 2*60,
1078 .dac_volume_max = 255,
1079 .function_flags = OXYGEN_FUNCTION_SPI,
1080 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1081 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1084 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1085 const struct pci_device_id *id)
1087 switch (id->subdevice) {
1088 case 0x838e:
1089 chip->model = model_xonar_ds;
1090 break;
1091 default:
1092 return -EINVAL;
1094 return 0;