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 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/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_ENABLE 0x0180
57 #define LC_CONTROL_LIMITER 0x40000000
58 #define LC_CONTROL_ALC 0x20000000
61 struct xonar_generic generic;
62 u16 wm8776_regs[0x17];
63 u16 wm8766_regs[0x10];
64 struct snd_kcontrol *line_adcmux_control;
65 struct snd_kcontrol *mic_adcmux_control;
66 struct snd_kcontrol *lc_controls[13];
67 struct snd_jack *hp_jack;
70 static void wm8776_write(struct oxygen *chip,
71 unsigned int reg, unsigned int value)
73 struct xonar_wm87x6 *data = chip->model_data;
75 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
76 OXYGEN_SPI_DATA_LENGTH_2 |
77 OXYGEN_SPI_CLOCK_160 |
78 (1 << OXYGEN_SPI_CODEC_SHIFT) |
79 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
81 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
82 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
83 value &= ~WM8776_UPDATE;
84 data->wm8776_regs[reg] = value;
88 static void wm8776_write_cached(struct oxygen *chip,
89 unsigned int reg, unsigned int value)
91 struct xonar_wm87x6 *data = chip->model_data;
93 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
94 value != data->wm8776_regs[reg])
95 wm8776_write(chip, reg, value);
98 static void wm8766_write(struct oxygen *chip,
99 unsigned int reg, unsigned int value)
101 struct xonar_wm87x6 *data = chip->model_data;
103 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
104 OXYGEN_SPI_DATA_LENGTH_2 |
105 OXYGEN_SPI_CLOCK_160 |
106 (0 << OXYGEN_SPI_CODEC_SHIFT) |
107 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
109 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
110 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
111 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
112 value &= ~WM8766_UPDATE;
113 data->wm8766_regs[reg] = value;
117 static void wm8766_write_cached(struct oxygen *chip,
118 unsigned int reg, unsigned int value)
120 struct xonar_wm87x6 *data = chip->model_data;
122 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
123 value != data->wm8766_regs[reg])
124 wm8766_write(chip, reg, value);
127 static void wm8776_registers_init(struct oxygen *chip)
129 struct xonar_wm87x6 *data = chip->model_data;
131 wm8776_write(chip, WM8776_RESET, 0);
132 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
133 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
134 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
135 wm8776_write(chip, WM8776_DACIFCTRL,
136 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
137 wm8776_write(chip, WM8776_ADCIFCTRL,
138 data->wm8776_regs[WM8776_ADCIFCTRL]);
139 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
140 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
141 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
142 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
144 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
145 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
146 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
147 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
148 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
151 static void wm8766_registers_init(struct oxygen *chip)
153 wm8766_write(chip, WM8766_RESET, 0);
154 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
155 wm8766_write(chip, WM8766_DAC_CTRL2,
156 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
157 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
158 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
159 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
160 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
161 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
162 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
165 static void wm8776_init(struct oxygen *chip)
167 struct xonar_wm87x6 *data = chip->model_data;
169 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
170 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
171 data->wm8776_regs[WM8776_ADCIFCTRL] =
172 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
173 data->wm8776_regs[WM8776_MSTRCTRL] =
174 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
175 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
176 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
177 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
178 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
179 wm8776_registers_init(chip);
182 static void xonar_ds_report_hp_jack(struct oxygen *chip)
184 struct xonar_wm87x6 *data = chip->model_data;
187 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
188 snd_jack_report(data->hp_jack,
189 bits & GPIO_DS_HP_DETECT ? 0 : SND_JACK_HEADPHONE);
192 static void xonar_ds_init(struct oxygen *chip)
194 struct xonar_wm87x6 *data = chip->model_data;
196 data->generic.anti_pop_delay = 300;
197 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
200 wm8766_registers_init(chip);
202 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
203 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
204 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
205 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
206 chip->interrupt_mask |= OXYGEN_INT_GPIO;
208 xonar_enable_output(chip);
210 snd_jack_new(chip->card, "Headphone",
211 SND_JACK_HEADPHONE, &data->hp_jack);
212 xonar_ds_report_hp_jack(chip);
214 snd_component_add(chip->card, "WM8776");
215 snd_component_add(chip->card, "WM8766");
218 static void xonar_ds_cleanup(struct oxygen *chip)
220 xonar_disable_output(chip);
221 wm8776_write(chip, WM8776_RESET, 0);
224 static void xonar_ds_suspend(struct oxygen *chip)
226 xonar_ds_cleanup(chip);
229 static void xonar_ds_resume(struct oxygen *chip)
231 wm8776_registers_init(chip);
232 wm8766_registers_init(chip);
233 xonar_enable_output(chip);
236 static void wm8776_adc_hardware_filter(unsigned int channel,
237 struct snd_pcm_hardware *hardware)
239 if (channel == PCM_A) {
240 hardware->rates = SNDRV_PCM_RATE_32000 |
241 SNDRV_PCM_RATE_44100 |
242 SNDRV_PCM_RATE_48000 |
243 SNDRV_PCM_RATE_64000 |
244 SNDRV_PCM_RATE_88200 |
245 SNDRV_PCM_RATE_96000;
246 hardware->rate_max = 96000;
250 static void set_wm87x6_dac_params(struct oxygen *chip,
251 struct snd_pcm_hw_params *params)
255 static void set_wm8776_adc_params(struct oxygen *chip,
256 struct snd_pcm_hw_params *params)
260 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
261 if (params_rate(params) > 48000)
262 reg |= WM8776_ADCOSR;
263 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
266 static void update_wm8776_volume(struct oxygen *chip)
268 struct xonar_wm87x6 *data = chip->model_data;
271 if (chip->dac_volume[0] == chip->dac_volume[1]) {
272 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
273 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
274 wm8776_write(chip, WM8776_DACMASTER,
275 chip->dac_volume[0] | WM8776_UPDATE);
276 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
277 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
280 to_change = (chip->dac_volume[0] !=
281 data->wm8776_regs[WM8776_DACLVOL]) << 0;
282 to_change |= (chip->dac_volume[1] !=
283 data->wm8776_regs[WM8776_DACLVOL]) << 1;
285 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
286 ((to_change & 2) ? 0 : WM8776_UPDATE));
288 wm8776_write(chip, WM8776_DACRVOL,
289 chip->dac_volume[1] | WM8776_UPDATE);
293 static void update_wm87x6_volume(struct oxygen *chip)
295 static const u8 wm8766_regs[6] = {
296 WM8766_LDA1, WM8766_RDA1,
297 WM8766_LDA2, WM8766_RDA2,
298 WM8766_LDA3, WM8766_RDA3,
300 struct xonar_wm87x6 *data = chip->model_data;
304 update_wm8776_volume(chip);
305 if (chip->dac_volume[2] == chip->dac_volume[3] &&
306 chip->dac_volume[2] == chip->dac_volume[4] &&
307 chip->dac_volume[2] == chip->dac_volume[5] &&
308 chip->dac_volume[2] == chip->dac_volume[6] &&
309 chip->dac_volume[2] == chip->dac_volume[7]) {
311 for (i = 0; i < 6; ++i)
312 if (chip->dac_volume[2] !=
313 data->wm8766_regs[wm8766_regs[i]])
316 wm8766_write(chip, WM8766_MASTDA,
317 chip->dac_volume[2] | WM8766_UPDATE);
318 for (i = 0; i < 6; ++i)
319 data->wm8766_regs[wm8766_regs[i]] =
324 for (i = 0; i < 6; ++i)
325 to_change |= (chip->dac_volume[2 + i] !=
326 data->wm8766_regs[wm8766_regs[i]]) << i;
327 for (i = 0; i < 6; ++i)
328 if (to_change & (1 << i))
329 wm8766_write(chip, wm8766_regs[i],
330 chip->dac_volume[2 + i] |
331 ((to_change & (0x3e << i))
332 ? 0 : WM8766_UPDATE));
336 static void update_wm8776_mute(struct oxygen *chip)
338 wm8776_write_cached(chip, WM8776_DACMUTE,
339 chip->dac_mute ? WM8776_DMUTE : 0);
342 static void update_wm87x6_mute(struct oxygen *chip)
344 update_wm8776_mute(chip);
345 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
346 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
349 static void xonar_ds_gpio_changed(struct oxygen *chip)
351 xonar_ds_report_hp_jack(chip);
354 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
355 struct snd_ctl_elem_value *value)
357 struct oxygen *chip = ctl->private_data;
358 struct xonar_wm87x6 *data = chip->model_data;
359 u16 bit = ctl->private_value & 0xffff;
360 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
361 bool invert = (ctl->private_value >> 24) & 1;
363 value->value.integer.value[0] =
364 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
368 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
369 struct snd_ctl_elem_value *value)
371 struct oxygen *chip = ctl->private_data;
372 struct xonar_wm87x6 *data = chip->model_data;
373 u16 bit = ctl->private_value & 0xffff;
375 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
376 bool invert = (ctl->private_value >> 24) & 1;
379 mutex_lock(&chip->mutex);
380 reg_value = data->wm8776_regs[reg_index] & ~bit;
381 if (value->value.integer.value[0] ^ invert)
383 changed = reg_value != data->wm8776_regs[reg_index];
385 wm8776_write(chip, reg_index, reg_value);
386 mutex_unlock(&chip->mutex);
390 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
391 struct snd_ctl_elem_info *info)
393 static const char *const hld[16] = {
394 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
395 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
396 "341 ms", "683 ms", "1.37 s", "2.73 s",
397 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
399 static const char *const atk_lim[11] = {
400 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
401 "4 ms", "8 ms", "16 ms", "32 ms",
402 "64 ms", "128 ms", "256 ms",
404 static const char *const atk_alc[11] = {
405 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
406 "134 ms", "269 ms", "538 ms", "1.08 s",
407 "2.15 s", "4.3 s", "8.6 s",
409 static const char *const dcy_lim[11] = {
410 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
411 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
412 "307 ms", "614 ms", "1.23 s",
414 static const char *const dcy_alc[11] = {
415 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
416 "536 ms", "1.07 s", "2.14 s", "4.29 s",
417 "8.58 s", "17.2 s", "34.3 s",
419 static const char *const tranwin[8] = {
420 "0 us", "62.5 us", "125 us", "250 us",
421 "500 us", "1 ms", "2 ms", "4 ms",
424 const char *const *names;
426 max = (ctl->private_value >> 12) & 0xf;
427 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
429 info->value.enumerated.items = max + 1;
430 if (info->value.enumerated.item > max)
431 info->value.enumerated.item = max;
432 switch ((ctl->private_value >> 24) & 0x1f) {
433 case WM8776_ALCCTRL2:
436 case WM8776_ALCCTRL3:
437 if (((ctl->private_value >> 20) & 0xf) == 0) {
438 if (ctl->private_value & LC_CONTROL_LIMITER)
443 if (ctl->private_value & LC_CONTROL_LIMITER)
455 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
459 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
460 struct snd_ctl_elem_info *info)
462 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
464 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
465 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
469 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
471 struct oxygen *chip = ctl->private_data;
472 struct xonar_wm87x6 *data = chip->model_data;
473 unsigned int value, reg_index, mode;
478 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
479 WM8776_LCSEL_LIMITER)
480 mode = LC_CONTROL_LIMITER;
482 mode = LC_CONTROL_ALC;
483 if (!(ctl->private_value & mode))
486 value = ctl->private_value & 0xf;
487 min = (ctl->private_value >> 8) & 0xf;
488 max = (ctl->private_value >> 12) & 0xf;
489 mask = (ctl->private_value >> 16) & 0xf;
490 shift = (ctl->private_value >> 20) & 0xf;
491 reg_index = (ctl->private_value >> 24) & 0x1f;
492 invert = (ctl->private_value >> 29) & 0x1;
495 value = max - (value - min);
496 reg_value = data->wm8776_regs[reg_index];
497 reg_value &= ~(mask << shift);
498 reg_value |= value << shift;
499 wm8776_write_cached(chip, reg_index, reg_value);
502 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
504 struct oxygen *chip = ctl->private_data;
508 min = (ctl->private_value >> 8) & 0xf;
509 max = (ctl->private_value >> 12) & 0xf;
510 if (value < min || value > max)
512 mutex_lock(&chip->mutex);
513 changed = value != (ctl->private_value & 0xf);
515 ctl->private_value = (ctl->private_value & ~0xf) | value;
516 wm8776_field_set_from_ctl(ctl);
518 mutex_unlock(&chip->mutex);
522 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
523 struct snd_ctl_elem_value *value)
525 value->value.enumerated.item[0] = ctl->private_value & 0xf;
529 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
530 struct snd_ctl_elem_value *value)
532 value->value.integer.value[0] = ctl->private_value & 0xf;
536 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
537 struct snd_ctl_elem_value *value)
539 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
542 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
543 struct snd_ctl_elem_value *value)
545 return wm8776_field_set(ctl, value->value.integer.value[0]);
548 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
549 struct snd_ctl_elem_info *info)
551 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
553 info->value.integer.min = 0x79 - 60;
554 info->value.integer.max = 0x7f;
558 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
559 struct snd_ctl_elem_value *value)
561 struct oxygen *chip = ctl->private_data;
562 struct xonar_wm87x6 *data = chip->model_data;
564 mutex_lock(&chip->mutex);
565 value->value.integer.value[0] =
566 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
567 value->value.integer.value[1] =
568 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
569 mutex_unlock(&chip->mutex);
573 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
574 struct snd_ctl_elem_value *value)
576 struct oxygen *chip = ctl->private_data;
577 struct xonar_wm87x6 *data = chip->model_data;
580 mutex_lock(&chip->mutex);
581 to_update = (value->value.integer.value[0] !=
582 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
584 to_update |= (value->value.integer.value[1] !=
585 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
587 if (value->value.integer.value[0] == value->value.integer.value[1]) {
589 wm8776_write(chip, WM8776_HPMASTER,
590 value->value.integer.value[0] |
591 WM8776_HPZCEN | WM8776_UPDATE);
592 data->wm8776_regs[WM8776_HPLVOL] =
593 value->value.integer.value[0] | WM8776_HPZCEN;
594 data->wm8776_regs[WM8776_HPRVOL] =
595 value->value.integer.value[0] | WM8776_HPZCEN;
599 wm8776_write(chip, WM8776_HPLVOL,
600 value->value.integer.value[0] |
602 ((to_update & 2) ? 0 : WM8776_UPDATE));
604 wm8776_write(chip, WM8776_HPRVOL,
605 value->value.integer.value[1] |
606 WM8776_HPZCEN | WM8776_UPDATE);
608 mutex_unlock(&chip->mutex);
609 return to_update != 0;
612 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
613 struct snd_ctl_elem_value *value)
615 struct oxygen *chip = ctl->private_data;
616 struct xonar_wm87x6 *data = chip->model_data;
617 unsigned int mux_bit = ctl->private_value;
619 value->value.integer.value[0] =
620 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
624 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
625 struct snd_ctl_elem_value *value)
627 struct oxygen *chip = ctl->private_data;
628 struct xonar_wm87x6 *data = chip->model_data;
629 struct snd_kcontrol *other_ctl;
630 unsigned int mux_bit = ctl->private_value;
634 mutex_lock(&chip->mutex);
635 reg = data->wm8776_regs[WM8776_ADCMUX];
636 if (value->value.integer.value[0]) {
638 /* line-in and mic-in are exclusive */
643 other_ctl = data->line_adcmux_control;
645 other_ctl = data->mic_adcmux_control;
646 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
651 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
653 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
654 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
655 GPIO_DS_INPUT_ROUTE);
656 wm8776_write(chip, WM8776_ADCMUX, reg);
658 mutex_unlock(&chip->mutex);
662 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
663 struct snd_ctl_elem_info *info)
665 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
667 info->value.integer.min = 0xa5;
668 info->value.integer.max = 0xff;
672 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
673 struct snd_ctl_elem_value *value)
675 struct oxygen *chip = ctl->private_data;
676 struct xonar_wm87x6 *data = chip->model_data;
678 mutex_lock(&chip->mutex);
679 value->value.integer.value[0] =
680 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
681 value->value.integer.value[1] =
682 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
683 mutex_unlock(&chip->mutex);
687 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
688 struct snd_ctl_elem_value *value)
690 struct oxygen *chip = ctl->private_data;
691 struct xonar_wm87x6 *data = chip->model_data;
694 mutex_lock(&chip->mutex);
695 changed = (value->value.integer.value[0] !=
696 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
697 (value->value.integer.value[1] !=
698 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
699 wm8776_write_cached(chip, WM8776_ADCLVOL,
700 value->value.integer.value[0] | WM8776_ZCA);
701 wm8776_write_cached(chip, WM8776_ADCRVOL,
702 value->value.integer.value[1] | WM8776_ZCA);
703 mutex_unlock(&chip->mutex);
707 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
708 struct snd_ctl_elem_info *info)
710 static const char *const names[3] = {
711 "None", "Peak Limiter", "Automatic Level Control"
713 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
715 info->value.enumerated.items = 3;
716 if (info->value.enumerated.item >= 3)
717 info->value.enumerated.item = 2;
718 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
722 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
723 struct snd_ctl_elem_value *value)
725 struct oxygen *chip = ctl->private_data;
726 struct xonar_wm87x6 *data = chip->model_data;
728 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
729 value->value.enumerated.item[0] = 0;
730 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
731 WM8776_LCSEL_LIMITER)
732 value->value.enumerated.item[0] = 1;
734 value->value.enumerated.item[0] = 2;
738 static void activate_control(struct oxygen *chip,
739 struct snd_kcontrol *ctl, unsigned int mode)
743 if (ctl->private_value & mode)
746 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
747 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
748 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
749 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
753 static int wm8776_level_control_put(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;
758 unsigned int mode = 0, i;
762 if (value->value.enumerated.item[0] >= 3)
764 mutex_lock(&chip->mutex);
765 changed = value->value.enumerated.item[0] != ctl->private_value;
767 ctl->private_value = value->value.enumerated.item[0];
768 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
769 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
770 switch (value->value.enumerated.item[0]) {
772 wm8776_write_cached(chip, WM8776_ALCCTRL2,
773 ctrl2 & ~WM8776_LCEN);
776 wm8776_write_cached(chip, WM8776_ALCCTRL1,
777 (ctrl1 & ~WM8776_LCSEL_MASK) |
778 WM8776_LCSEL_LIMITER);
779 wm8776_write_cached(chip, WM8776_ALCCTRL2,
780 ctrl2 | WM8776_LCEN);
781 mode = LC_CONTROL_LIMITER;
784 wm8776_write_cached(chip, WM8776_ALCCTRL1,
785 (ctrl1 & ~WM8776_LCSEL_MASK) |
786 WM8776_LCSEL_ALC_STEREO);
787 wm8776_write_cached(chip, WM8776_ALCCTRL2,
788 ctrl2 | WM8776_LCEN);
789 mode = LC_CONTROL_ALC;
792 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
793 activate_control(chip, data->lc_controls[i], mode);
795 mutex_unlock(&chip->mutex);
799 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
801 static const char *const names[2] = {
802 "None", "High-pass Filter"
805 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
807 info->value.enumerated.items = 2;
808 if (info->value.enumerated.item >= 2)
809 info->value.enumerated.item = 1;
810 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
814 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
816 struct oxygen *chip = ctl->private_data;
817 struct xonar_wm87x6 *data = chip->model_data;
819 value->value.enumerated.item[0] =
820 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
824 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
826 struct oxygen *chip = ctl->private_data;
827 struct xonar_wm87x6 *data = chip->model_data;
831 mutex_lock(&chip->mutex);
832 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
833 if (!value->value.enumerated.item[0])
834 reg |= WM8776_ADCHPD;
835 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
837 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
838 mutex_unlock(&chip->mutex);
842 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
843 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
845 .info = snd_ctl_boolean_mono_info, \
846 .get = wm8776_bit_switch_get, \
847 .put = wm8776_bit_switch_put, \
848 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
850 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
851 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
853 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
854 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
855 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
856 _WM8776_FIELD_CTL(xname " Capture Enum", \
857 reg, shift, init, min, max, mask, flags), \
858 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
859 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
860 .info = wm8776_field_enum_info, \
861 .get = wm8776_field_enum_get, \
862 .put = wm8776_field_enum_put, \
864 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
865 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
866 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
867 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
868 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
869 .info = wm8776_field_volume_info, \
870 .get = wm8776_field_volume_get, \
871 .put = wm8776_field_volume_put, \
872 .tlv = { .p = tlv_p }, \
875 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
876 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
877 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
878 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
879 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
880 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
881 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
882 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
884 static const struct snd_kcontrol_new ds_controls[] = {
886 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
887 .name = "Headphone Playback Volume",
888 .info = wm8776_hp_vol_info,
889 .get = wm8776_hp_vol_get,
890 .put = wm8776_hp_vol_put,
891 .tlv = { .p = wm8776_hp_db_scale },
893 WM8776_BIT_SWITCH("Headphone Playback Switch",
894 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
896 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
897 .name = "Input Capture Volume",
898 .info = wm8776_input_vol_info,
899 .get = wm8776_input_vol_get,
900 .put = wm8776_input_vol_put,
901 .tlv = { .p = wm8776_adc_db_scale },
904 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
905 .name = "Line Capture Switch",
906 .info = snd_ctl_boolean_mono_info,
907 .get = wm8776_input_mux_get,
908 .put = wm8776_input_mux_put,
909 .private_value = 1 << 0,
912 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
913 .name = "Mic Capture Switch",
914 .info = snd_ctl_boolean_mono_info,
915 .get = wm8776_input_mux_get,
916 .put = wm8776_input_mux_put,
917 .private_value = 1 << 1,
919 WM8776_BIT_SWITCH("Front Mic Capture Switch",
920 WM8776_ADCMUX, 1 << 2, 0, 0),
921 WM8776_BIT_SWITCH("Aux Capture Switch",
922 WM8776_ADCMUX, 1 << 3, 0, 0),
924 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
925 .name = "ADC Filter Capture Enum",
931 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
932 .name = "Level Control Capture Enum",
933 .info = wm8776_level_control_info,
934 .get = wm8776_level_control_get,
935 .put = wm8776_level_control_put,
939 static const struct snd_kcontrol_new lc_controls[] = {
940 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
941 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
942 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
943 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
944 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
946 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
947 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
949 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
950 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
952 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
953 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
955 wm8776_maxatten_lim_db_scale),
956 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
957 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
958 LC_CONTROL_ALC, wm8776_lct_db_scale),
959 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
960 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
962 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
963 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
965 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
966 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
967 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
968 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
969 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
970 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
971 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
972 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
974 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
975 WM8776_NOISEGATE, WM8776_NGAT, 0,
977 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
978 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
979 LC_CONTROL_ALC, wm8776_ngth_db_scale),
982 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
984 if (!strncmp(template->name, "CD Capture ", 11))
985 return 1; /* no CD input */
989 static int xonar_ds_mixer_init(struct oxygen *chip)
991 struct xonar_wm87x6 *data = chip->model_data;
993 struct snd_kcontrol *ctl;
996 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
997 ctl = snd_ctl_new1(&ds_controls[i], chip);
1000 err = snd_ctl_add(chip->card, ctl);
1003 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1004 data->line_adcmux_control = ctl;
1005 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1006 data->mic_adcmux_control = ctl;
1008 if (!data->line_adcmux_control || !data->mic_adcmux_control)
1010 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1011 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1012 ctl = snd_ctl_new1(&lc_controls[i], chip);
1015 err = snd_ctl_add(chip->card, ctl);
1018 data->lc_controls[i] = ctl;
1023 static const struct oxygen_model model_xonar_ds = {
1024 .shortname = "Xonar DS",
1025 .longname = "Asus Virtuoso 200",
1027 .init = xonar_ds_init,
1028 .control_filter = xonar_ds_control_filter,
1029 .mixer_init = xonar_ds_mixer_init,
1030 .cleanup = xonar_ds_cleanup,
1031 .suspend = xonar_ds_suspend,
1032 .resume = xonar_ds_resume,
1033 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1034 .get_i2s_mclk = oxygen_default_i2s_mclk,
1035 .set_dac_params = set_wm87x6_dac_params,
1036 .set_adc_params = set_wm8776_adc_params,
1037 .update_dac_volume = update_wm87x6_volume,
1038 .update_dac_mute = update_wm87x6_mute,
1039 .gpio_changed = xonar_ds_gpio_changed,
1040 .dac_tlv = wm87x6_dac_db_scale,
1041 .model_data_size = sizeof(struct xonar_wm87x6),
1042 .device_config = PLAYBACK_0_TO_I2S |
1043 PLAYBACK_1_TO_SPDIF |
1044 CAPTURE_0_FROM_I2S_1,
1046 .dac_volume_min = 255 - 2*60,
1047 .dac_volume_max = 255,
1048 .function_flags = OXYGEN_FUNCTION_SPI,
1049 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1050 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1053 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1054 const struct pci_device_id *id)
1056 switch (id->subdevice) {
1058 chip->model = model_xonar_ds;