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/>.
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
37 * input 3 <- front mic
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>
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
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,
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,
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] |
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;
201 mutex_lock(&chip->mutex);
203 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
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;
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;
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,
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)
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;
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];
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;
316 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
317 ((to_change & 2) ? 0 : WM8776_UPDATE));
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;
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]) {
342 for (i = 0; i < 6; ++i)
343 if (chip->dac_volume[2] !=
344 data->wm8766_regs[wm8766_regs[i]])
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]] =
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;
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;
406 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
407 bool invert = (ctl->private_value >> 24) & 1;
410 mutex_lock(&chip->mutex);
411 reg_value = data->wm8776_regs[reg_index] & ~bit;
412 if (value->value.integer.value[0] ^ invert)
414 changed = reg_value != data->wm8776_regs[reg_index];
416 wm8776_write(chip, reg_index, reg_value);
417 mutex_unlock(&chip->mutex);
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",
455 const char *const *names;
457 max = (ctl->private_value >> 12) & 0xf;
458 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
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:
467 case WM8776_ALCCTRL3:
468 if (((ctl->private_value >> 20) & 0xf) == 0) {
469 if (ctl->private_value & LC_CONTROL_LIMITER)
474 if (ctl->private_value & LC_CONTROL_LIMITER)
486 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
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;
495 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
496 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
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;
509 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
510 WM8776_LCSEL_LIMITER)
511 mode = LC_CONTROL_LIMITER;
513 mode = LC_CONTROL_ALC;
514 if (!(ctl->private_value & mode))
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;
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;
539 min = (ctl->private_value >> 8) & 0xf;
540 max = (ctl->private_value >> 12) & 0xf;
541 if (value < min || value > max)
543 mutex_lock(&chip->mutex);
544 changed = value != (ctl->private_value & 0xf);
546 ctl->private_value = (ctl->private_value & ~0xf) | value;
547 wm8776_field_set_from_ctl(ctl);
549 mutex_unlock(&chip->mutex);
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;
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;
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;
584 info->value.integer.min = 0x79 - 60;
585 info->value.integer.max = 0x7f;
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);
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;
611 mutex_lock(&chip->mutex);
612 to_update = (value->value.integer.value[0] !=
613 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
615 to_update |= (value->value.integer.value[1] !=
616 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
618 if (value->value.integer.value[0] == value->value.integer.value[1]) {
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;
630 wm8776_write(chip, WM8776_HPLVOL,
631 value->value.integer.value[0] |
633 ((to_update & 2) ? 0 : WM8776_UPDATE));
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);
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;
665 mutex_lock(&chip->mutex);
666 reg = data->wm8776_regs[WM8776_ADCMUX];
667 if (value->value.integer.value[0]) {
669 /* line-in and mic-in are exclusive */
674 other_ctl = data->line_adcmux_control;
676 other_ctl = data->mic_adcmux_control;
677 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
682 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
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);
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;
698 info->value.integer.min = 0xa5;
699 info->value.integer.max = 0xff;
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);
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;
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);
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;
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]);
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;
765 value->value.enumerated.item[0] = 2;
769 static void activate_control(struct oxygen *chip,
770 struct snd_kcontrol *ctl, unsigned int mode)
774 if (ctl->private_value & mode)
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;
793 if (value->value.enumerated.item[0] >= 3)
795 mutex_lock(&chip->mutex);
796 changed = value->value.enumerated.item[0] != ctl->private_value;
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]) {
803 wm8776_write_cached(chip, WM8776_ALCCTRL2,
804 ctrl2 & ~WM8776_LCEN);
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;
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;
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);
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;
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]);
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);
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;
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];
868 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
869 mutex_unlock(&chip->mutex);
873 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
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, \
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",
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,
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,
977 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
978 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
980 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
981 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
983 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
984 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
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,
993 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
994 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
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,
1005 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1006 WM8776_NOISEGATE, WM8776_NGAT, 0,
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 */
1020 static int xonar_ds_mixer_init(struct oxygen *chip)
1022 struct xonar_wm87x6 *data = chip->model_data;
1024 struct snd_kcontrol *ctl;
1027 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1028 ctl = snd_ctl_new1(&ds_controls[i], chip);
1031 err = snd_ctl_add(chip->card, ctl);
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)
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);
1046 err = snd_ctl_add(chip->card, ctl);
1049 data->lc_controls[i] = ctl;
1054 static const struct oxygen_model model_xonar_ds = {
1055 .shortname = "Xonar DS",
1056 .longname = "Asus Virtuoso 200",
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,
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) {
1089 chip->model = model_xonar_ds;