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
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
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/pcm.h>
46 #include <sound/pcm_params.h>
47 #include <sound/tlv.h>
52 #define GPIO_DS_HP_DETECT 0x0010
53 #define GPIO_DS_INPUT_ROUTE 0x0040
54 #define GPIO_DS_OUTPUT_ENABLE 0x0180
56 #define LC_CONTROL_LIMITER 0x40000000
57 #define LC_CONTROL_ALC 0x20000000
60 struct xonar_generic generic;
61 u16 wm8776_regs[0x17];
62 u16 wm8766_regs[0x10];
63 struct snd_kcontrol *line_adcmux_control;
64 struct snd_kcontrol *mic_adcmux_control;
65 struct snd_kcontrol *lc_controls[13];
68 static void wm8776_write(struct oxygen *chip,
69 unsigned int reg, unsigned int value)
71 struct xonar_wm87x6 *data = chip->model_data;
73 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
74 OXYGEN_SPI_DATA_LENGTH_2 |
75 OXYGEN_SPI_CLOCK_160 |
76 (1 << OXYGEN_SPI_CODEC_SHIFT) |
77 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
79 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
80 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
81 value &= ~WM8776_UPDATE;
82 data->wm8776_regs[reg] = value;
86 static void wm8776_write_cached(struct oxygen *chip,
87 unsigned int reg, unsigned int value)
89 struct xonar_wm87x6 *data = chip->model_data;
91 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
92 value != data->wm8776_regs[reg])
93 wm8776_write(chip, reg, value);
96 static void wm8766_write(struct oxygen *chip,
97 unsigned int reg, unsigned int value)
99 struct xonar_wm87x6 *data = chip->model_data;
101 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
102 OXYGEN_SPI_DATA_LENGTH_2 |
103 OXYGEN_SPI_CLOCK_160 |
104 (0 << OXYGEN_SPI_CODEC_SHIFT) |
105 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
107 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
108 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
109 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
110 value &= ~WM8766_UPDATE;
111 data->wm8766_regs[reg] = value;
115 static void wm8766_write_cached(struct oxygen *chip,
116 unsigned int reg, unsigned int value)
118 struct xonar_wm87x6 *data = chip->model_data;
120 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
121 value != data->wm8766_regs[reg])
122 wm8766_write(chip, reg, value);
125 static void wm8776_registers_init(struct oxygen *chip)
127 struct xonar_wm87x6 *data = chip->model_data;
129 wm8776_write(chip, WM8776_RESET, 0);
130 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
131 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
132 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
133 wm8776_write(chip, WM8776_DACIFCTRL,
134 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
135 wm8776_write(chip, WM8776_ADCIFCTRL,
136 data->wm8776_regs[WM8776_ADCIFCTRL]);
137 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
138 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
139 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
140 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
142 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
143 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
144 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
145 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
146 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
149 static void wm8766_registers_init(struct oxygen *chip)
151 wm8766_write(chip, WM8766_RESET, 0);
152 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
153 wm8766_write(chip, WM8766_DAC_CTRL2,
154 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
155 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
156 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
157 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
158 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
159 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
160 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
163 static void wm8776_init(struct oxygen *chip)
165 struct xonar_wm87x6 *data = chip->model_data;
167 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
168 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
169 data->wm8776_regs[WM8776_ADCIFCTRL] =
170 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
171 data->wm8776_regs[WM8776_MSTRCTRL] =
172 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
173 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
174 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
175 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
176 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
177 wm8776_registers_init(chip);
180 static void xonar_ds_init(struct oxygen *chip)
182 struct xonar_wm87x6 *data = chip->model_data;
184 data->generic.anti_pop_delay = 300;
185 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
188 wm8766_registers_init(chip);
190 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
191 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
192 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
193 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
194 chip->interrupt_mask |= OXYGEN_INT_GPIO;
196 xonar_enable_output(chip);
198 snd_component_add(chip->card, "WM8776");
199 snd_component_add(chip->card, "WM8766");
202 static void xonar_ds_cleanup(struct oxygen *chip)
204 xonar_disable_output(chip);
205 wm8776_write(chip, WM8776_RESET, 0);
208 static void xonar_ds_suspend(struct oxygen *chip)
210 xonar_ds_cleanup(chip);
213 static void xonar_ds_resume(struct oxygen *chip)
215 wm8776_registers_init(chip);
216 wm8766_registers_init(chip);
217 xonar_enable_output(chip);
220 static void wm8776_adc_hardware_filter(unsigned int channel,
221 struct snd_pcm_hardware *hardware)
223 if (channel == PCM_A) {
224 hardware->rates = SNDRV_PCM_RATE_32000 |
225 SNDRV_PCM_RATE_44100 |
226 SNDRV_PCM_RATE_48000 |
227 SNDRV_PCM_RATE_64000 |
228 SNDRV_PCM_RATE_88200 |
229 SNDRV_PCM_RATE_96000;
230 hardware->rate_max = 96000;
234 static void set_wm87x6_dac_params(struct oxygen *chip,
235 struct snd_pcm_hw_params *params)
239 static void set_wm8776_adc_params(struct oxygen *chip,
240 struct snd_pcm_hw_params *params)
244 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
245 if (params_rate(params) > 48000)
246 reg |= WM8776_ADCOSR;
247 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
250 static void update_wm8776_volume(struct oxygen *chip)
252 struct xonar_wm87x6 *data = chip->model_data;
255 if (chip->dac_volume[0] == chip->dac_volume[1]) {
256 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
257 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
258 wm8776_write(chip, WM8776_DACMASTER,
259 chip->dac_volume[0] | WM8776_UPDATE);
260 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
261 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
264 to_change = (chip->dac_volume[0] !=
265 data->wm8776_regs[WM8776_DACLVOL]) << 0;
266 to_change |= (chip->dac_volume[1] !=
267 data->wm8776_regs[WM8776_DACLVOL]) << 1;
269 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
270 ((to_change & 2) ? 0 : WM8776_UPDATE));
272 wm8776_write(chip, WM8776_DACRVOL,
273 chip->dac_volume[1] | WM8776_UPDATE);
277 static void update_wm87x6_volume(struct oxygen *chip)
279 static const u8 wm8766_regs[6] = {
280 WM8766_LDA1, WM8766_RDA1,
281 WM8766_LDA2, WM8766_RDA2,
282 WM8766_LDA3, WM8766_RDA3,
284 struct xonar_wm87x6 *data = chip->model_data;
288 update_wm8776_volume(chip);
289 if (chip->dac_volume[2] == chip->dac_volume[3] &&
290 chip->dac_volume[2] == chip->dac_volume[4] &&
291 chip->dac_volume[2] == chip->dac_volume[5] &&
292 chip->dac_volume[2] == chip->dac_volume[6] &&
293 chip->dac_volume[2] == chip->dac_volume[7]) {
295 for (i = 0; i < 6; ++i)
296 if (chip->dac_volume[2] !=
297 data->wm8766_regs[wm8766_regs[i]])
300 wm8766_write(chip, WM8766_MASTDA,
301 chip->dac_volume[2] | WM8766_UPDATE);
302 for (i = 0; i < 6; ++i)
303 data->wm8766_regs[wm8766_regs[i]] =
308 for (i = 0; i < 6; ++i)
309 to_change |= (chip->dac_volume[2 + i] !=
310 data->wm8766_regs[wm8766_regs[i]]) << i;
311 for (i = 0; i < 6; ++i)
312 if (to_change & (1 << i))
313 wm8766_write(chip, wm8766_regs[i],
314 chip->dac_volume[2 + i] |
315 ((to_change & (0x3e << i))
316 ? 0 : WM8766_UPDATE));
320 static void update_wm8776_mute(struct oxygen *chip)
322 wm8776_write_cached(chip, WM8776_DACMUTE,
323 chip->dac_mute ? WM8776_DMUTE : 0);
326 static void update_wm87x6_mute(struct oxygen *chip)
328 update_wm8776_mute(chip);
329 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
330 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
333 static void xonar_ds_gpio_changed(struct oxygen *chip)
337 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
338 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
341 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
342 struct snd_ctl_elem_value *value)
344 struct oxygen *chip = ctl->private_data;
345 struct xonar_wm87x6 *data = chip->model_data;
346 u16 bit = ctl->private_value & 0xffff;
347 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
348 bool invert = (ctl->private_value >> 24) & 1;
350 value->value.integer.value[0] =
351 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
355 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
356 struct snd_ctl_elem_value *value)
358 struct oxygen *chip = ctl->private_data;
359 struct xonar_wm87x6 *data = chip->model_data;
360 u16 bit = ctl->private_value & 0xffff;
362 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
363 bool invert = (ctl->private_value >> 24) & 1;
366 mutex_lock(&chip->mutex);
367 reg_value = data->wm8776_regs[reg_index] & ~bit;
368 if (value->value.integer.value[0] ^ invert)
370 changed = reg_value != data->wm8776_regs[reg_index];
372 wm8776_write(chip, reg_index, reg_value);
373 mutex_unlock(&chip->mutex);
377 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
378 struct snd_ctl_elem_info *info)
380 static const char *const hld[16] = {
381 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
382 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
383 "341 ms", "683 ms", "1.37 s", "2.73 s",
384 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
386 static const char *const atk_lim[11] = {
387 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
388 "4 ms", "8 ms", "16 ms", "32 ms",
389 "64 ms", "128 ms", "256 ms",
391 static const char *const atk_alc[11] = {
392 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
393 "134 ms", "269 ms", "538 ms", "1.08 s",
394 "2.15 s", "4.3 s", "8.6 s",
396 static const char *const dcy_lim[11] = {
397 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
398 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
399 "307 ms", "614 ms", "1.23 s",
401 static const char *const dcy_alc[11] = {
402 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
403 "536 ms", "1.07 s", "2.14 s", "4.29 s",
404 "8.58 s", "17.2 s", "34.3 s",
406 static const char *const tranwin[8] = {
407 "0 us", "62.5 us", "125 us", "250 us",
408 "500 us", "1 ms", "2 ms", "4 ms",
411 const char *const *names;
413 max = (ctl->private_value >> 12) & 0xf;
414 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
416 info->value.enumerated.items = max + 1;
417 if (info->value.enumerated.item > max)
418 info->value.enumerated.item = max;
419 switch ((ctl->private_value >> 24) & 0x1f) {
420 case WM8776_ALCCTRL2:
423 case WM8776_ALCCTRL3:
424 if (((ctl->private_value >> 20) & 0xf) == 0) {
425 if (ctl->private_value & LC_CONTROL_LIMITER)
430 if (ctl->private_value & LC_CONTROL_LIMITER)
442 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
446 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
447 struct snd_ctl_elem_info *info)
449 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
451 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
452 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
456 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
458 struct oxygen *chip = ctl->private_data;
459 struct xonar_wm87x6 *data = chip->model_data;
460 unsigned int value, reg_index, mode;
465 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
466 WM8776_LCSEL_LIMITER)
467 mode = LC_CONTROL_LIMITER;
469 mode = LC_CONTROL_ALC;
470 if (!(ctl->private_value & mode))
473 value = ctl->private_value & 0xf;
474 min = (ctl->private_value >> 8) & 0xf;
475 max = (ctl->private_value >> 12) & 0xf;
476 mask = (ctl->private_value >> 16) & 0xf;
477 shift = (ctl->private_value >> 20) & 0xf;
478 reg_index = (ctl->private_value >> 24) & 0x1f;
479 invert = (ctl->private_value >> 29) & 0x1;
482 value = max - (value - min);
483 reg_value = data->wm8776_regs[reg_index];
484 reg_value &= ~(mask << shift);
485 reg_value |= value << shift;
486 wm8776_write_cached(chip, reg_index, reg_value);
489 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
491 struct oxygen *chip = ctl->private_data;
495 min = (ctl->private_value >> 8) & 0xf;
496 max = (ctl->private_value >> 12) & 0xf;
497 if (value < min || value > max)
499 mutex_lock(&chip->mutex);
500 changed = value != (ctl->private_value & 0xf);
502 ctl->private_value = (ctl->private_value & ~0xf) | value;
503 wm8776_field_set_from_ctl(ctl);
505 mutex_unlock(&chip->mutex);
509 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
510 struct snd_ctl_elem_value *value)
512 value->value.enumerated.item[0] = ctl->private_value & 0xf;
516 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
517 struct snd_ctl_elem_value *value)
519 value->value.integer.value[0] = ctl->private_value & 0xf;
523 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
524 struct snd_ctl_elem_value *value)
526 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
529 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
530 struct snd_ctl_elem_value *value)
532 return wm8776_field_set(ctl, value->value.integer.value[0]);
535 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
536 struct snd_ctl_elem_info *info)
538 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
540 info->value.integer.min = 0x79 - 60;
541 info->value.integer.max = 0x7f;
545 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
546 struct snd_ctl_elem_value *value)
548 struct oxygen *chip = ctl->private_data;
549 struct xonar_wm87x6 *data = chip->model_data;
551 mutex_lock(&chip->mutex);
552 value->value.integer.value[0] =
553 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
554 value->value.integer.value[1] =
555 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
556 mutex_unlock(&chip->mutex);
560 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
561 struct snd_ctl_elem_value *value)
563 struct oxygen *chip = ctl->private_data;
564 struct xonar_wm87x6 *data = chip->model_data;
567 mutex_lock(&chip->mutex);
568 to_update = (value->value.integer.value[0] !=
569 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
571 to_update |= (value->value.integer.value[1] !=
572 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
574 if (value->value.integer.value[0] == value->value.integer.value[1]) {
576 wm8776_write(chip, WM8776_HPMASTER,
577 value->value.integer.value[0] |
578 WM8776_HPZCEN | WM8776_UPDATE);
579 data->wm8776_regs[WM8776_HPLVOL] =
580 value->value.integer.value[0] | WM8776_HPZCEN;
581 data->wm8776_regs[WM8776_HPRVOL] =
582 value->value.integer.value[0] | WM8776_HPZCEN;
586 wm8776_write(chip, WM8776_HPLVOL,
587 value->value.integer.value[0] |
589 ((to_update & 2) ? 0 : WM8776_UPDATE));
591 wm8776_write(chip, WM8776_HPRVOL,
592 value->value.integer.value[1] |
593 WM8776_HPZCEN | WM8776_UPDATE);
595 mutex_unlock(&chip->mutex);
596 return to_update != 0;
599 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
600 struct snd_ctl_elem_value *value)
602 struct oxygen *chip = ctl->private_data;
603 struct xonar_wm87x6 *data = chip->model_data;
604 unsigned int mux_bit = ctl->private_value;
606 value->value.integer.value[0] =
607 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
611 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
612 struct snd_ctl_elem_value *value)
614 struct oxygen *chip = ctl->private_data;
615 struct xonar_wm87x6 *data = chip->model_data;
616 struct snd_kcontrol *other_ctl;
617 unsigned int mux_bit = ctl->private_value;
621 mutex_lock(&chip->mutex);
622 reg = data->wm8776_regs[WM8776_ADCMUX];
623 if (value->value.integer.value[0]) {
625 /* line-in and mic-in are exclusive */
630 other_ctl = data->line_adcmux_control;
632 other_ctl = data->mic_adcmux_control;
633 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
638 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
640 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
641 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
642 GPIO_DS_INPUT_ROUTE);
643 wm8776_write(chip, WM8776_ADCMUX, reg);
645 mutex_unlock(&chip->mutex);
649 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
650 struct snd_ctl_elem_info *info)
652 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
654 info->value.integer.min = 0xa5;
655 info->value.integer.max = 0xff;
659 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
660 struct snd_ctl_elem_value *value)
662 struct oxygen *chip = ctl->private_data;
663 struct xonar_wm87x6 *data = chip->model_data;
665 mutex_lock(&chip->mutex);
666 value->value.integer.value[0] =
667 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
668 value->value.integer.value[1] =
669 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
670 mutex_unlock(&chip->mutex);
674 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
675 struct snd_ctl_elem_value *value)
677 struct oxygen *chip = ctl->private_data;
678 struct xonar_wm87x6 *data = chip->model_data;
681 mutex_lock(&chip->mutex);
682 changed = (value->value.integer.value[0] !=
683 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
684 (value->value.integer.value[1] !=
685 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
686 wm8776_write_cached(chip, WM8776_ADCLVOL,
687 value->value.integer.value[0] | WM8776_ZCA);
688 wm8776_write_cached(chip, WM8776_ADCRVOL,
689 value->value.integer.value[1] | WM8776_ZCA);
690 mutex_unlock(&chip->mutex);
694 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
695 struct snd_ctl_elem_info *info)
697 static const char *const names[3] = {
698 "None", "Peak Limiter", "Automatic Level Control"
700 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
702 info->value.enumerated.items = 3;
703 if (info->value.enumerated.item >= 3)
704 info->value.enumerated.item = 2;
705 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
709 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
710 struct snd_ctl_elem_value *value)
712 struct oxygen *chip = ctl->private_data;
713 struct xonar_wm87x6 *data = chip->model_data;
715 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
716 value->value.enumerated.item[0] = 0;
717 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
718 WM8776_LCSEL_LIMITER)
719 value->value.enumerated.item[0] = 1;
721 value->value.enumerated.item[0] = 2;
725 static void activate_control(struct oxygen *chip,
726 struct snd_kcontrol *ctl, unsigned int mode)
730 if (ctl->private_value & mode)
733 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
734 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
735 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
736 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
740 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
741 struct snd_ctl_elem_value *value)
743 struct oxygen *chip = ctl->private_data;
744 struct xonar_wm87x6 *data = chip->model_data;
745 unsigned int mode = 0, i;
749 if (value->value.enumerated.item[0] >= 3)
751 mutex_lock(&chip->mutex);
752 changed = value->value.enumerated.item[0] != ctl->private_value;
754 ctl->private_value = value->value.enumerated.item[0];
755 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
756 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
757 switch (value->value.enumerated.item[0]) {
759 wm8776_write_cached(chip, WM8776_ALCCTRL2,
760 ctrl2 & ~WM8776_LCEN);
763 wm8776_write_cached(chip, WM8776_ALCCTRL1,
764 (ctrl1 & ~WM8776_LCSEL_MASK) |
765 WM8776_LCSEL_LIMITER);
766 wm8776_write_cached(chip, WM8776_ALCCTRL2,
767 ctrl2 | WM8776_LCEN);
768 mode = LC_CONTROL_LIMITER;
771 wm8776_write_cached(chip, WM8776_ALCCTRL1,
772 (ctrl1 & ~WM8776_LCSEL_MASK) |
773 WM8776_LCSEL_ALC_STEREO);
774 wm8776_write_cached(chip, WM8776_ALCCTRL2,
775 ctrl2 | WM8776_LCEN);
776 mode = LC_CONTROL_ALC;
779 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
780 activate_control(chip, data->lc_controls[i], mode);
782 mutex_unlock(&chip->mutex);
786 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
788 static const char *const names[2] = {
789 "None", "High-pass Filter"
792 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
794 info->value.enumerated.items = 2;
795 if (info->value.enumerated.item >= 2)
796 info->value.enumerated.item = 1;
797 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
801 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
803 struct oxygen *chip = ctl->private_data;
804 struct xonar_wm87x6 *data = chip->model_data;
806 value->value.enumerated.item[0] =
807 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
811 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
813 struct oxygen *chip = ctl->private_data;
814 struct xonar_wm87x6 *data = chip->model_data;
818 mutex_lock(&chip->mutex);
819 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
820 if (!value->value.enumerated.item[0])
821 reg |= WM8776_ADCHPD;
822 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
824 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
825 mutex_unlock(&chip->mutex);
829 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
830 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
832 .info = snd_ctl_boolean_mono_info, \
833 .get = wm8776_bit_switch_get, \
834 .put = wm8776_bit_switch_put, \
835 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
837 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
838 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
840 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
841 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
842 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
843 _WM8776_FIELD_CTL(xname " Capture Enum", \
844 reg, shift, init, min, max, mask, flags), \
845 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
846 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
847 .info = wm8776_field_enum_info, \
848 .get = wm8776_field_enum_get, \
849 .put = wm8776_field_enum_put, \
851 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
852 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
853 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
854 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
855 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
856 .info = wm8776_field_volume_info, \
857 .get = wm8776_field_volume_get, \
858 .put = wm8776_field_volume_put, \
859 .tlv = { .p = tlv_p }, \
862 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
863 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
864 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
865 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
866 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
867 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
868 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
869 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
871 static const struct snd_kcontrol_new ds_controls[] = {
873 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
874 .name = "Headphone Playback Volume",
875 .info = wm8776_hp_vol_info,
876 .get = wm8776_hp_vol_get,
877 .put = wm8776_hp_vol_put,
878 .tlv = { .p = wm8776_hp_db_scale },
880 WM8776_BIT_SWITCH("Headphone Playback Switch",
881 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
883 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
884 .name = "Input Capture Volume",
885 .info = wm8776_input_vol_info,
886 .get = wm8776_input_vol_get,
887 .put = wm8776_input_vol_put,
888 .tlv = { .p = wm8776_adc_db_scale },
891 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
892 .name = "Line Capture Switch",
893 .info = snd_ctl_boolean_mono_info,
894 .get = wm8776_input_mux_get,
895 .put = wm8776_input_mux_put,
896 .private_value = 1 << 0,
899 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
900 .name = "Mic Capture Switch",
901 .info = snd_ctl_boolean_mono_info,
902 .get = wm8776_input_mux_get,
903 .put = wm8776_input_mux_put,
904 .private_value = 1 << 1,
906 WM8776_BIT_SWITCH("Front Mic Capture Switch",
907 WM8776_ADCMUX, 1 << 2, 0, 0),
908 WM8776_BIT_SWITCH("Aux Capture Switch",
909 WM8776_ADCMUX, 1 << 3, 0, 0),
911 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
912 .name = "ADC Filter Capture Enum",
918 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
919 .name = "Level Control Capture Enum",
920 .info = wm8776_level_control_info,
921 .get = wm8776_level_control_get,
922 .put = wm8776_level_control_put,
926 static const struct snd_kcontrol_new lc_controls[] = {
927 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
928 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
929 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
930 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
931 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
933 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
934 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
936 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
937 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
939 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
940 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
942 wm8776_maxatten_lim_db_scale),
943 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
944 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
945 LC_CONTROL_ALC, wm8776_lct_db_scale),
946 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
947 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
949 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
950 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
952 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
953 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
954 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
955 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
956 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
957 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
958 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
959 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
961 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
962 WM8776_NOISEGATE, WM8776_NGAT, 0,
964 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
965 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
966 LC_CONTROL_ALC, wm8776_ngth_db_scale),
969 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
971 if (!strncmp(template->name, "CD Capture ", 11))
972 return 1; /* no CD input */
976 static int xonar_ds_mixer_init(struct oxygen *chip)
978 struct xonar_wm87x6 *data = chip->model_data;
980 struct snd_kcontrol *ctl;
983 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
984 ctl = snd_ctl_new1(&ds_controls[i], chip);
987 err = snd_ctl_add(chip->card, ctl);
990 if (!strcmp(ctl->id.name, "Line Capture Switch"))
991 data->line_adcmux_control = ctl;
992 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
993 data->mic_adcmux_control = ctl;
995 if (!data->line_adcmux_control || !data->mic_adcmux_control)
997 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
998 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
999 ctl = snd_ctl_new1(&lc_controls[i], chip);
1002 err = snd_ctl_add(chip->card, ctl);
1005 data->lc_controls[i] = ctl;
1010 static const struct oxygen_model model_xonar_ds = {
1011 .shortname = "Xonar DS",
1012 .longname = "Asus Virtuoso 200",
1014 .init = xonar_ds_init,
1015 .control_filter = xonar_ds_control_filter,
1016 .mixer_init = xonar_ds_mixer_init,
1017 .cleanup = xonar_ds_cleanup,
1018 .suspend = xonar_ds_suspend,
1019 .resume = xonar_ds_resume,
1020 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1021 .get_i2s_mclk = oxygen_default_i2s_mclk,
1022 .set_dac_params = set_wm87x6_dac_params,
1023 .set_adc_params = set_wm8776_adc_params,
1024 .update_dac_volume = update_wm87x6_volume,
1025 .update_dac_mute = update_wm87x6_mute,
1026 .gpio_changed = xonar_ds_gpio_changed,
1027 .dac_tlv = wm87x6_dac_db_scale,
1028 .model_data_size = sizeof(struct xonar_wm87x6),
1029 .device_config = PLAYBACK_0_TO_I2S |
1030 PLAYBACK_1_TO_SPDIF |
1031 CAPTURE_0_FROM_I2S_1,
1033 .dac_volume_min = 255 - 2*60,
1034 .dac_volume_max = 255,
1035 .function_flags = OXYGEN_FUNCTION_SPI,
1036 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1037 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1040 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1041 const struct pci_device_id *id)
1043 switch (id->subdevice) {
1045 chip->model = model_xonar_ds;