1 // SPDX-License-Identifier: GPL-2.0-only
3 * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim)
5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
14 * SPI 0 -> WM8766 (surround, center/LFE, back)
15 * SPI 1 -> WM8776 (front, input)
17 * GPIO 4 <- headphone detect, 0 = plugged
18 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
19 * GPIO 7 -> enable output to front L/R speaker channels
20 * GPIO 8 -> enable output to other speaker channels and front panel headphone
26 * input 3 <- front mic
36 * I²C <-> WM8776 (addr 0011010)
38 * GPIO 0 -> disable HDMI output
39 * GPIO 1 -> enable HP output
40 * GPIO 6 -> firmware EEPROM I²C clock
41 * GPIO 7 <-> firmware EEPROM I²C data
43 * UART <-> HDMI controller
51 #include <linux/pci.h>
52 #include <linux/delay.h>
53 #include <sound/control.h>
54 #include <sound/core.h>
55 #include <sound/info.h>
56 #include <sound/jack.h>
57 #include <sound/pcm.h>
58 #include <sound/pcm_params.h>
59 #include <sound/tlv.h>
64 #define GPIO_DS_HP_DETECT 0x0010
65 #define GPIO_DS_INPUT_ROUTE 0x0040
66 #define GPIO_DS_OUTPUT_FRONTLR 0x0080
67 #define GPIO_DS_OUTPUT_ENABLE 0x0100
69 #define GPIO_SLIM_HDMI_DISABLE 0x0001
70 #define GPIO_SLIM_OUTPUT_ENABLE 0x0002
71 #define GPIO_SLIM_FIRMWARE_CLK 0x0040
72 #define GPIO_SLIM_FIRMWARE_DATA 0x0080
74 #define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */
76 #define LC_CONTROL_LIMITER 0x40000000
77 #define LC_CONTROL_ALC 0x20000000
80 struct xonar_generic generic;
81 u16 wm8776_regs[0x17];
82 u16 wm8766_regs[0x10];
83 struct snd_kcontrol *line_adcmux_control;
84 struct snd_kcontrol *mic_adcmux_control;
85 struct snd_kcontrol *lc_controls[13];
86 struct snd_jack *hp_jack;
87 struct xonar_hdmi hdmi;
90 static void wm8776_write_spi(struct oxygen *chip,
91 unsigned int reg, unsigned int value)
93 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
94 OXYGEN_SPI_DATA_LENGTH_2 |
95 OXYGEN_SPI_CLOCK_160 |
96 (1 << OXYGEN_SPI_CODEC_SHIFT) |
97 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
101 static void wm8776_write_i2c(struct oxygen *chip,
102 unsigned int reg, unsigned int value)
104 oxygen_write_i2c(chip, I2C_DEVICE_WM8776,
105 (reg << 1) | (value >> 8), value);
108 static void wm8776_write(struct oxygen *chip,
109 unsigned int reg, unsigned int value)
111 struct xonar_wm87x6 *data = chip->model_data;
113 if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) ==
115 wm8776_write_spi(chip, reg, value);
117 wm8776_write_i2c(chip, reg, value);
118 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
119 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
120 value &= ~WM8776_UPDATE;
121 data->wm8776_regs[reg] = value;
125 static void wm8776_write_cached(struct oxygen *chip,
126 unsigned int reg, unsigned int value)
128 struct xonar_wm87x6 *data = chip->model_data;
130 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
131 value != data->wm8776_regs[reg])
132 wm8776_write(chip, reg, value);
135 static void wm8766_write(struct oxygen *chip,
136 unsigned int reg, unsigned int value)
138 struct xonar_wm87x6 *data = chip->model_data;
140 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
141 OXYGEN_SPI_DATA_LENGTH_2 |
142 OXYGEN_SPI_CLOCK_160 |
143 (0 << OXYGEN_SPI_CODEC_SHIFT) |
144 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
146 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
147 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
148 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
149 value &= ~WM8766_UPDATE;
150 data->wm8766_regs[reg] = value;
154 static void wm8766_write_cached(struct oxygen *chip,
155 unsigned int reg, unsigned int value)
157 struct xonar_wm87x6 *data = chip->model_data;
159 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
160 value != data->wm8766_regs[reg])
161 wm8766_write(chip, reg, value);
164 static void wm8776_registers_init(struct oxygen *chip)
166 struct xonar_wm87x6 *data = chip->model_data;
168 wm8776_write(chip, WM8776_RESET, 0);
169 wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
170 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
171 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
172 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
173 wm8776_write(chip, WM8776_DACIFCTRL,
174 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
175 wm8776_write(chip, WM8776_ADCIFCTRL,
176 data->wm8776_regs[WM8776_ADCIFCTRL]);
177 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
178 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
179 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
180 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
182 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
183 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
184 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
185 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
186 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
189 static void wm8766_registers_init(struct oxygen *chip)
191 struct xonar_wm87x6 *data = chip->model_data;
193 wm8766_write(chip, WM8766_RESET, 0);
194 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
195 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
196 wm8766_write(chip, WM8766_DAC_CTRL2,
197 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
198 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
199 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
200 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
201 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
202 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
203 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
206 static void wm8776_init(struct oxygen *chip)
208 struct xonar_wm87x6 *data = chip->model_data;
210 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
211 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
212 data->wm8776_regs[WM8776_ADCIFCTRL] =
213 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
214 data->wm8776_regs[WM8776_MSTRCTRL] =
215 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
216 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
217 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
218 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
219 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
220 wm8776_registers_init(chip);
223 static void wm8766_init(struct oxygen *chip)
225 struct xonar_wm87x6 *data = chip->model_data;
227 data->wm8766_regs[WM8766_DAC_CTRL] =
228 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
229 wm8766_registers_init(chip);
232 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
234 struct xonar_wm87x6 *data = chip->model_data;
238 mutex_lock(&chip->mutex);
240 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
243 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
244 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
245 GPIO_DS_OUTPUT_FRONTLR);
247 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
249 reg |= WM8766_MUTEALL;
250 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
252 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
254 mutex_unlock(&chip->mutex);
257 static void xonar_ds_init(struct oxygen *chip)
259 struct xonar_wm87x6 *data = chip->model_data;
261 data->generic.anti_pop_delay = 300;
262 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
267 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
268 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
269 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
271 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
272 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
273 chip->interrupt_mask |= OXYGEN_INT_GPIO;
275 xonar_enable_output(chip);
277 snd_jack_new(chip->card, "Headphone",
278 SND_JACK_HEADPHONE, &data->hp_jack, false, false);
279 xonar_ds_handle_hp_jack(chip);
281 snd_component_add(chip->card, "WM8776");
282 snd_component_add(chip->card, "WM8766");
285 static void xonar_hdav_slim_init(struct oxygen *chip)
287 struct xonar_wm87x6 *data = chip->model_data;
289 data->generic.anti_pop_delay = 300;
290 data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE;
294 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
295 GPIO_SLIM_HDMI_DISABLE |
296 GPIO_SLIM_FIRMWARE_CLK |
297 GPIO_SLIM_FIRMWARE_DATA);
299 xonar_hdmi_init(chip, &data->hdmi);
300 xonar_enable_output(chip);
302 snd_component_add(chip->card, "WM8776");
305 static void xonar_ds_cleanup(struct oxygen *chip)
307 xonar_disable_output(chip);
308 wm8776_write(chip, WM8776_RESET, 0);
311 static void xonar_hdav_slim_cleanup(struct oxygen *chip)
313 xonar_hdmi_cleanup(chip);
314 xonar_disable_output(chip);
315 wm8776_write(chip, WM8776_RESET, 0);
319 static void xonar_ds_suspend(struct oxygen *chip)
321 xonar_ds_cleanup(chip);
324 static void xonar_hdav_slim_suspend(struct oxygen *chip)
326 xonar_hdav_slim_cleanup(chip);
329 static void xonar_ds_resume(struct oxygen *chip)
331 wm8776_registers_init(chip);
332 wm8766_registers_init(chip);
333 xonar_enable_output(chip);
334 xonar_ds_handle_hp_jack(chip);
337 static void xonar_hdav_slim_resume(struct oxygen *chip)
339 struct xonar_wm87x6 *data = chip->model_data;
341 wm8776_registers_init(chip);
342 xonar_hdmi_resume(chip, &data->hdmi);
343 xonar_enable_output(chip);
346 static void wm8776_adc_hardware_filter(unsigned int channel,
347 struct snd_pcm_hardware *hardware)
349 if (channel == PCM_A) {
350 hardware->rates = SNDRV_PCM_RATE_32000 |
351 SNDRV_PCM_RATE_44100 |
352 SNDRV_PCM_RATE_48000 |
353 SNDRV_PCM_RATE_64000 |
354 SNDRV_PCM_RATE_88200 |
355 SNDRV_PCM_RATE_96000;
356 hardware->rate_max = 96000;
360 static void xonar_hdav_slim_hardware_filter(unsigned int channel,
361 struct snd_pcm_hardware *hardware)
363 wm8776_adc_hardware_filter(channel, hardware);
364 xonar_hdmi_pcm_hardware_filter(channel, hardware);
367 static void set_wm87x6_dac_params(struct oxygen *chip,
368 struct snd_pcm_hw_params *params)
372 static void set_wm8776_adc_params(struct oxygen *chip,
373 struct snd_pcm_hw_params *params)
377 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
378 if (params_rate(params) > 48000)
379 reg |= WM8776_ADCOSR;
380 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
383 static void set_hdav_slim_dac_params(struct oxygen *chip,
384 struct snd_pcm_hw_params *params)
386 struct xonar_wm87x6 *data = chip->model_data;
388 xonar_set_hdmi_params(chip, &data->hdmi, params);
391 static void update_wm8776_volume(struct oxygen *chip)
393 struct xonar_wm87x6 *data = chip->model_data;
396 if (chip->dac_volume[0] == chip->dac_volume[1]) {
397 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
398 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
399 wm8776_write(chip, WM8776_DACMASTER,
400 chip->dac_volume[0] | WM8776_UPDATE);
401 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
402 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
405 to_change = (chip->dac_volume[0] !=
406 data->wm8776_regs[WM8776_DACLVOL]) << 0;
407 to_change |= (chip->dac_volume[1] !=
408 data->wm8776_regs[WM8776_DACLVOL]) << 1;
410 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
411 ((to_change & 2) ? 0 : WM8776_UPDATE));
413 wm8776_write(chip, WM8776_DACRVOL,
414 chip->dac_volume[1] | WM8776_UPDATE);
418 static void update_wm87x6_volume(struct oxygen *chip)
420 static const u8 wm8766_regs[6] = {
421 WM8766_LDA1, WM8766_RDA1,
422 WM8766_LDA2, WM8766_RDA2,
423 WM8766_LDA3, WM8766_RDA3,
425 struct xonar_wm87x6 *data = chip->model_data;
429 update_wm8776_volume(chip);
430 if (chip->dac_volume[2] == chip->dac_volume[3] &&
431 chip->dac_volume[2] == chip->dac_volume[4] &&
432 chip->dac_volume[2] == chip->dac_volume[5] &&
433 chip->dac_volume[2] == chip->dac_volume[6] &&
434 chip->dac_volume[2] == chip->dac_volume[7]) {
436 for (i = 0; i < 6; ++i)
437 if (chip->dac_volume[2] !=
438 data->wm8766_regs[wm8766_regs[i]])
441 wm8766_write(chip, WM8766_MASTDA,
442 chip->dac_volume[2] | WM8766_UPDATE);
443 for (i = 0; i < 6; ++i)
444 data->wm8766_regs[wm8766_regs[i]] =
449 for (i = 0; i < 6; ++i)
450 to_change |= (chip->dac_volume[2 + i] !=
451 data->wm8766_regs[wm8766_regs[i]]) << i;
452 for (i = 0; i < 6; ++i)
453 if (to_change & (1 << i))
454 wm8766_write(chip, wm8766_regs[i],
455 chip->dac_volume[2 + i] |
456 ((to_change & (0x3e << i))
457 ? 0 : WM8766_UPDATE));
461 static void update_wm8776_mute(struct oxygen *chip)
463 wm8776_write_cached(chip, WM8776_DACMUTE,
464 chip->dac_mute ? WM8776_DMUTE : 0);
467 static void update_wm87x6_mute(struct oxygen *chip)
469 update_wm8776_mute(chip);
470 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
471 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
474 static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
476 struct xonar_wm87x6 *data = chip->model_data;
480 * The WM8766 can mix left and right channels, but this setting
481 * applies to all three stereo pairs.
483 reg = data->wm8766_regs[WM8766_DAC_CTRL] &
484 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
486 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
488 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
489 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
492 static void xonar_ds_gpio_changed(struct oxygen *chip)
494 xonar_ds_handle_hp_jack(chip);
497 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
498 struct snd_ctl_elem_value *value)
500 struct oxygen *chip = ctl->private_data;
501 struct xonar_wm87x6 *data = chip->model_data;
502 u16 bit = ctl->private_value & 0xffff;
503 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
504 bool invert = (ctl->private_value >> 24) & 1;
506 value->value.integer.value[0] =
507 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
511 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
512 struct snd_ctl_elem_value *value)
514 struct oxygen *chip = ctl->private_data;
515 struct xonar_wm87x6 *data = chip->model_data;
516 u16 bit = ctl->private_value & 0xffff;
518 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
519 bool invert = (ctl->private_value >> 24) & 1;
522 mutex_lock(&chip->mutex);
523 reg_value = data->wm8776_regs[reg_index] & ~bit;
524 if (value->value.integer.value[0] ^ invert)
526 changed = reg_value != data->wm8776_regs[reg_index];
528 wm8776_write(chip, reg_index, reg_value);
529 mutex_unlock(&chip->mutex);
533 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
534 struct snd_ctl_elem_info *info)
536 static const char *const hld[16] = {
537 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
538 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
539 "341 ms", "683 ms", "1.37 s", "2.73 s",
540 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
542 static const char *const atk_lim[11] = {
543 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
544 "4 ms", "8 ms", "16 ms", "32 ms",
545 "64 ms", "128 ms", "256 ms",
547 static const char *const atk_alc[11] = {
548 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
549 "134 ms", "269 ms", "538 ms", "1.08 s",
550 "2.15 s", "4.3 s", "8.6 s",
552 static const char *const dcy_lim[11] = {
553 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
554 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
555 "307 ms", "614 ms", "1.23 s",
557 static const char *const dcy_alc[11] = {
558 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
559 "536 ms", "1.07 s", "2.14 s", "4.29 s",
560 "8.58 s", "17.2 s", "34.3 s",
562 static const char *const tranwin[8] = {
563 "0 us", "62.5 us", "125 us", "250 us",
564 "500 us", "1 ms", "2 ms", "4 ms",
567 const char *const *names;
569 max = (ctl->private_value >> 12) & 0xf;
570 switch ((ctl->private_value >> 24) & 0x1f) {
571 case WM8776_ALCCTRL2:
574 case WM8776_ALCCTRL3:
575 if (((ctl->private_value >> 20) & 0xf) == 0) {
576 if (ctl->private_value & LC_CONTROL_LIMITER)
581 if (ctl->private_value & LC_CONTROL_LIMITER)
593 return snd_ctl_enum_info(info, 1, max + 1, names);
596 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
597 struct snd_ctl_elem_info *info)
599 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
601 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
602 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
606 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
608 struct oxygen *chip = ctl->private_data;
609 struct xonar_wm87x6 *data = chip->model_data;
610 unsigned int value, reg_index, mode;
615 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
616 WM8776_LCSEL_LIMITER)
617 mode = LC_CONTROL_LIMITER;
619 mode = LC_CONTROL_ALC;
620 if (!(ctl->private_value & mode))
623 value = ctl->private_value & 0xf;
624 min = (ctl->private_value >> 8) & 0xf;
625 max = (ctl->private_value >> 12) & 0xf;
626 mask = (ctl->private_value >> 16) & 0xf;
627 shift = (ctl->private_value >> 20) & 0xf;
628 reg_index = (ctl->private_value >> 24) & 0x1f;
629 invert = (ctl->private_value >> 29) & 0x1;
632 value = max - (value - min);
633 reg_value = data->wm8776_regs[reg_index];
634 reg_value &= ~(mask << shift);
635 reg_value |= value << shift;
636 wm8776_write_cached(chip, reg_index, reg_value);
639 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
641 struct oxygen *chip = ctl->private_data;
645 min = (ctl->private_value >> 8) & 0xf;
646 max = (ctl->private_value >> 12) & 0xf;
647 if (value < min || value > max)
649 mutex_lock(&chip->mutex);
650 changed = value != (ctl->private_value & 0xf);
652 ctl->private_value = (ctl->private_value & ~0xf) | value;
653 wm8776_field_set_from_ctl(ctl);
655 mutex_unlock(&chip->mutex);
659 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
660 struct snd_ctl_elem_value *value)
662 value->value.enumerated.item[0] = ctl->private_value & 0xf;
666 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
667 struct snd_ctl_elem_value *value)
669 value->value.integer.value[0] = ctl->private_value & 0xf;
673 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
674 struct snd_ctl_elem_value *value)
676 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
679 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
680 struct snd_ctl_elem_value *value)
682 return wm8776_field_set(ctl, value->value.integer.value[0]);
685 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
686 struct snd_ctl_elem_info *info)
688 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
690 info->value.integer.min = 0x79 - 60;
691 info->value.integer.max = 0x7f;
695 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
696 struct snd_ctl_elem_value *value)
698 struct oxygen *chip = ctl->private_data;
699 struct xonar_wm87x6 *data = chip->model_data;
701 mutex_lock(&chip->mutex);
702 value->value.integer.value[0] =
703 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
704 value->value.integer.value[1] =
705 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
706 mutex_unlock(&chip->mutex);
710 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
711 struct snd_ctl_elem_value *value)
713 struct oxygen *chip = ctl->private_data;
714 struct xonar_wm87x6 *data = chip->model_data;
717 mutex_lock(&chip->mutex);
718 to_update = (value->value.integer.value[0] !=
719 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
721 to_update |= (value->value.integer.value[1] !=
722 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
724 if (value->value.integer.value[0] == value->value.integer.value[1]) {
726 wm8776_write(chip, WM8776_HPMASTER,
727 value->value.integer.value[0] |
728 WM8776_HPZCEN | WM8776_UPDATE);
729 data->wm8776_regs[WM8776_HPLVOL] =
730 value->value.integer.value[0] | WM8776_HPZCEN;
731 data->wm8776_regs[WM8776_HPRVOL] =
732 value->value.integer.value[0] | WM8776_HPZCEN;
736 wm8776_write(chip, WM8776_HPLVOL,
737 value->value.integer.value[0] |
739 ((to_update & 2) ? 0 : WM8776_UPDATE));
741 wm8776_write(chip, WM8776_HPRVOL,
742 value->value.integer.value[1] |
743 WM8776_HPZCEN | WM8776_UPDATE);
745 mutex_unlock(&chip->mutex);
746 return to_update != 0;
749 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
750 struct snd_ctl_elem_value *value)
752 struct oxygen *chip = ctl->private_data;
753 struct xonar_wm87x6 *data = chip->model_data;
754 unsigned int mux_bit = ctl->private_value;
756 value->value.integer.value[0] =
757 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
761 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
762 struct snd_ctl_elem_value *value)
764 struct oxygen *chip = ctl->private_data;
765 struct xonar_wm87x6 *data = chip->model_data;
766 struct snd_kcontrol *other_ctl;
767 unsigned int mux_bit = ctl->private_value;
771 mutex_lock(&chip->mutex);
772 reg = data->wm8776_regs[WM8776_ADCMUX];
773 if (value->value.integer.value[0]) {
775 /* line-in and mic-in are exclusive */
780 other_ctl = data->line_adcmux_control;
782 other_ctl = data->mic_adcmux_control;
783 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
788 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
790 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
791 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
792 GPIO_DS_INPUT_ROUTE);
793 wm8776_write(chip, WM8776_ADCMUX, reg);
795 mutex_unlock(&chip->mutex);
799 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
800 struct snd_ctl_elem_info *info)
802 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
804 info->value.integer.min = 0xa5;
805 info->value.integer.max = 0xff;
809 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
810 struct snd_ctl_elem_value *value)
812 struct oxygen *chip = ctl->private_data;
813 struct xonar_wm87x6 *data = chip->model_data;
815 mutex_lock(&chip->mutex);
816 value->value.integer.value[0] =
817 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
818 value->value.integer.value[1] =
819 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
820 mutex_unlock(&chip->mutex);
824 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
825 struct snd_ctl_elem_value *value)
827 struct oxygen *chip = ctl->private_data;
828 struct xonar_wm87x6 *data = chip->model_data;
831 mutex_lock(&chip->mutex);
832 changed = (value->value.integer.value[0] !=
833 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
834 (value->value.integer.value[1] !=
835 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
836 wm8776_write_cached(chip, WM8776_ADCLVOL,
837 value->value.integer.value[0] | WM8776_ZCA);
838 wm8776_write_cached(chip, WM8776_ADCRVOL,
839 value->value.integer.value[1] | WM8776_ZCA);
840 mutex_unlock(&chip->mutex);
844 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
845 struct snd_ctl_elem_info *info)
847 static const char *const names[3] = {
848 "None", "Peak Limiter", "Automatic Level Control"
851 return snd_ctl_enum_info(info, 1, 3, names);
854 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
855 struct snd_ctl_elem_value *value)
857 struct oxygen *chip = ctl->private_data;
858 struct xonar_wm87x6 *data = chip->model_data;
860 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
861 value->value.enumerated.item[0] = 0;
862 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
863 WM8776_LCSEL_LIMITER)
864 value->value.enumerated.item[0] = 1;
866 value->value.enumerated.item[0] = 2;
870 static void activate_control(struct oxygen *chip,
871 struct snd_kcontrol *ctl, unsigned int mode)
875 if (ctl->private_value & mode)
878 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
879 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
880 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
881 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
885 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
886 struct snd_ctl_elem_value *value)
888 struct oxygen *chip = ctl->private_data;
889 struct xonar_wm87x6 *data = chip->model_data;
890 unsigned int mode = 0, i;
894 if (value->value.enumerated.item[0] >= 3)
896 mutex_lock(&chip->mutex);
897 changed = value->value.enumerated.item[0] != ctl->private_value;
899 ctl->private_value = value->value.enumerated.item[0];
900 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
901 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
902 switch (value->value.enumerated.item[0]) {
904 wm8776_write_cached(chip, WM8776_ALCCTRL2,
905 ctrl2 & ~WM8776_LCEN);
908 wm8776_write_cached(chip, WM8776_ALCCTRL1,
909 (ctrl1 & ~WM8776_LCSEL_MASK) |
910 WM8776_LCSEL_LIMITER);
911 wm8776_write_cached(chip, WM8776_ALCCTRL2,
912 ctrl2 | WM8776_LCEN);
913 mode = LC_CONTROL_LIMITER;
916 wm8776_write_cached(chip, WM8776_ALCCTRL1,
917 (ctrl1 & ~WM8776_LCSEL_MASK) |
918 WM8776_LCSEL_ALC_STEREO);
919 wm8776_write_cached(chip, WM8776_ALCCTRL2,
920 ctrl2 | WM8776_LCEN);
921 mode = LC_CONTROL_ALC;
924 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
925 activate_control(chip, data->lc_controls[i], mode);
927 mutex_unlock(&chip->mutex);
931 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
933 static const char *const names[2] = {
934 "None", "High-pass Filter"
937 return snd_ctl_enum_info(info, 1, 2, names);
940 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
942 struct oxygen *chip = ctl->private_data;
943 struct xonar_wm87x6 *data = chip->model_data;
945 value->value.enumerated.item[0] =
946 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
950 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
952 struct oxygen *chip = ctl->private_data;
953 struct xonar_wm87x6 *data = chip->model_data;
957 mutex_lock(&chip->mutex);
958 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
959 if (!value->value.enumerated.item[0])
960 reg |= WM8776_ADCHPD;
961 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
963 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
964 mutex_unlock(&chip->mutex);
968 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
969 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
971 .info = snd_ctl_boolean_mono_info, \
972 .get = wm8776_bit_switch_get, \
973 .put = wm8776_bit_switch_put, \
974 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
976 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
977 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
979 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
980 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
981 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
982 _WM8776_FIELD_CTL(xname " Capture Enum", \
983 reg, shift, init, min, max, mask, flags), \
984 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
985 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
986 .info = wm8776_field_enum_info, \
987 .get = wm8776_field_enum_get, \
988 .put = wm8776_field_enum_put, \
990 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
991 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
992 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
993 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
994 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
995 .info = wm8776_field_volume_info, \
996 .get = wm8776_field_volume_get, \
997 .put = wm8776_field_volume_put, \
998 .tlv = { .p = tlv_p }, \
1001 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
1002 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
1003 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
1004 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
1005 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
1006 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
1007 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
1008 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
1010 static const struct snd_kcontrol_new ds_controls[] = {
1012 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1013 .name = "Headphone Playback Volume",
1014 .info = wm8776_hp_vol_info,
1015 .get = wm8776_hp_vol_get,
1016 .put = wm8776_hp_vol_put,
1017 .tlv = { .p = wm8776_hp_db_scale },
1019 WM8776_BIT_SWITCH("Headphone Playback Switch",
1020 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1022 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1023 .name = "Input Capture Volume",
1024 .info = wm8776_input_vol_info,
1025 .get = wm8776_input_vol_get,
1026 .put = wm8776_input_vol_put,
1027 .tlv = { .p = wm8776_adc_db_scale },
1030 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1031 .name = "Line Capture Switch",
1032 .info = snd_ctl_boolean_mono_info,
1033 .get = wm8776_input_mux_get,
1034 .put = wm8776_input_mux_put,
1035 .private_value = 1 << 0,
1038 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1039 .name = "Mic Capture Switch",
1040 .info = snd_ctl_boolean_mono_info,
1041 .get = wm8776_input_mux_get,
1042 .put = wm8776_input_mux_put,
1043 .private_value = 1 << 1,
1045 WM8776_BIT_SWITCH("Front Mic Capture Switch",
1046 WM8776_ADCMUX, 1 << 2, 0, 0),
1047 WM8776_BIT_SWITCH("Aux Capture Switch",
1048 WM8776_ADCMUX, 1 << 3, 0, 0),
1050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1051 .name = "ADC Filter Capture Enum",
1057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1058 .name = "Level Control Capture Enum",
1059 .info = wm8776_level_control_info,
1060 .get = wm8776_level_control_get,
1061 .put = wm8776_level_control_put,
1065 static const struct snd_kcontrol_new hdav_slim_controls[] = {
1067 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1068 .name = "HDMI Playback Switch",
1069 .info = snd_ctl_boolean_mono_info,
1070 .get = xonar_gpio_bit_switch_get,
1071 .put = xonar_gpio_bit_switch_put,
1072 .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT,
1075 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1076 .name = "Headphone Playback Volume",
1077 .info = wm8776_hp_vol_info,
1078 .get = wm8776_hp_vol_get,
1079 .put = wm8776_hp_vol_put,
1080 .tlv = { .p = wm8776_hp_db_scale },
1082 WM8776_BIT_SWITCH("Headphone Playback Switch",
1083 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1085 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1086 .name = "Input Capture Volume",
1087 .info = wm8776_input_vol_info,
1088 .get = wm8776_input_vol_get,
1089 .put = wm8776_input_vol_put,
1090 .tlv = { .p = wm8776_adc_db_scale },
1092 WM8776_BIT_SWITCH("Mic Capture Switch",
1093 WM8776_ADCMUX, 1 << 0, 0, 0),
1094 WM8776_BIT_SWITCH("Aux Capture Switch",
1095 WM8776_ADCMUX, 1 << 1, 0, 0),
1097 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1098 .name = "ADC Filter Capture Enum",
1104 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1105 .name = "Level Control Capture Enum",
1106 .info = wm8776_level_control_info,
1107 .get = wm8776_level_control_get,
1108 .put = wm8776_level_control_put,
1112 static const struct snd_kcontrol_new lc_controls[] = {
1113 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
1114 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1115 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
1116 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
1117 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1118 LC_CONTROL_LIMITER),
1119 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
1120 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1121 LC_CONTROL_LIMITER),
1122 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
1123 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
1124 LC_CONTROL_LIMITER),
1125 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
1126 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
1128 wm8776_maxatten_lim_db_scale),
1129 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
1130 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1131 LC_CONTROL_ALC, wm8776_lct_db_scale),
1132 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
1133 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1135 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1136 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1138 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
1139 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
1140 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
1141 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1142 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1143 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1144 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1145 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1147 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1148 WM8776_NOISEGATE, WM8776_NGAT, 0,
1150 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1151 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1152 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1155 static int add_lc_controls(struct oxygen *chip)
1157 struct xonar_wm87x6 *data = chip->model_data;
1159 struct snd_kcontrol *ctl;
1162 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1163 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1164 ctl = snd_ctl_new1(&lc_controls[i], chip);
1167 err = snd_ctl_add(chip->card, ctl);
1170 data->lc_controls[i] = ctl;
1175 static int xonar_ds_mixer_init(struct oxygen *chip)
1177 struct xonar_wm87x6 *data = chip->model_data;
1179 struct snd_kcontrol *ctl;
1182 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1183 ctl = snd_ctl_new1(&ds_controls[i], chip);
1186 err = snd_ctl_add(chip->card, ctl);
1189 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1190 data->line_adcmux_control = ctl;
1191 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1192 data->mic_adcmux_control = ctl;
1194 if (!data->line_adcmux_control || !data->mic_adcmux_control)
1197 return add_lc_controls(chip);
1200 static int xonar_hdav_slim_mixer_init(struct oxygen *chip)
1203 struct snd_kcontrol *ctl;
1206 for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) {
1207 ctl = snd_ctl_new1(&hdav_slim_controls[i], chip);
1210 err = snd_ctl_add(chip->card, ctl);
1215 return add_lc_controls(chip);
1218 static void dump_wm8776_registers(struct oxygen *chip,
1219 struct snd_info_buffer *buffer)
1221 struct xonar_wm87x6 *data = chip->model_data;
1224 snd_iprintf(buffer, "\nWM8776:\n00:");
1225 for (i = 0; i < 0x10; ++i)
1226 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1227 snd_iprintf(buffer, "\n10:");
1228 for (i = 0x10; i < 0x17; ++i)
1229 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1230 snd_iprintf(buffer, "\n");
1233 static void dump_wm87x6_registers(struct oxygen *chip,
1234 struct snd_info_buffer *buffer)
1236 struct xonar_wm87x6 *data = chip->model_data;
1239 dump_wm8776_registers(chip, buffer);
1240 snd_iprintf(buffer, "\nWM8766:\n00:");
1241 for (i = 0; i < 0x10; ++i)
1242 snd_iprintf(buffer, " %03x", data->wm8766_regs[i]);
1243 snd_iprintf(buffer, "\n");
1246 static const struct oxygen_model model_xonar_ds = {
1247 .longname = "Asus Virtuoso 66",
1249 .init = xonar_ds_init,
1250 .mixer_init = xonar_ds_mixer_init,
1251 .cleanup = xonar_ds_cleanup,
1252 .suspend = xonar_ds_suspend,
1253 .resume = xonar_ds_resume,
1254 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1255 .set_dac_params = set_wm87x6_dac_params,
1256 .set_adc_params = set_wm8776_adc_params,
1257 .update_dac_volume = update_wm87x6_volume,
1258 .update_dac_mute = update_wm87x6_mute,
1259 .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1260 .gpio_changed = xonar_ds_gpio_changed,
1261 .dump_registers = dump_wm87x6_registers,
1262 .dac_tlv = wm87x6_dac_db_scale,
1263 .model_data_size = sizeof(struct xonar_wm87x6),
1264 .device_config = PLAYBACK_0_TO_I2S |
1265 PLAYBACK_1_TO_SPDIF |
1266 CAPTURE_0_FROM_I2S_1 |
1267 CAPTURE_1_FROM_SPDIF,
1268 .dac_channels_pcm = 8,
1269 .dac_channels_mixer = 8,
1270 .dac_volume_min = 255 - 2*60,
1271 .dac_volume_max = 255,
1272 .function_flags = OXYGEN_FUNCTION_SPI,
1273 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1274 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1275 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1276 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1279 static const struct oxygen_model model_xonar_hdav_slim = {
1280 .shortname = "Xonar HDAV1.3 Slim",
1281 .longname = "Asus Virtuoso 200",
1283 .init = xonar_hdav_slim_init,
1284 .mixer_init = xonar_hdav_slim_mixer_init,
1285 .cleanup = xonar_hdav_slim_cleanup,
1286 .suspend = xonar_hdav_slim_suspend,
1287 .resume = xonar_hdav_slim_resume,
1288 .pcm_hardware_filter = xonar_hdav_slim_hardware_filter,
1289 .set_dac_params = set_hdav_slim_dac_params,
1290 .set_adc_params = set_wm8776_adc_params,
1291 .update_dac_volume = update_wm8776_volume,
1292 .update_dac_mute = update_wm8776_mute,
1293 .uart_input = xonar_hdmi_uart_input,
1294 .dump_registers = dump_wm8776_registers,
1295 .dac_tlv = wm87x6_dac_db_scale,
1296 .model_data_size = sizeof(struct xonar_wm87x6),
1297 .device_config = PLAYBACK_0_TO_I2S |
1298 PLAYBACK_1_TO_SPDIF |
1299 CAPTURE_0_FROM_I2S_1 |
1300 CAPTURE_1_FROM_SPDIF,
1301 .dac_channels_pcm = 8,
1302 .dac_channels_mixer = 2,
1303 .dac_volume_min = 255 - 2*60,
1304 .dac_volume_max = 255,
1305 .function_flags = OXYGEN_FUNCTION_2WIRE,
1306 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1307 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1308 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1309 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1312 int get_xonar_wm87x6_model(struct oxygen *chip,
1313 const struct pci_device_id *id)
1315 switch (id->subdevice) {
1317 chip->model = model_xonar_ds;
1318 chip->model.shortname = "Xonar DS";
1321 chip->model = model_xonar_ds;
1322 chip->model.shortname = "Xonar DSX";
1325 chip->model = model_xonar_hdav_slim;