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
34 #include <linux/pci.h>
35 #include <linux/delay.h>
36 #include <sound/control.h>
37 #include <sound/core.h>
38 #include <sound/pcm.h>
39 #include <sound/pcm_params.h>
40 #include <sound/tlv.h>
45 #define GPIO_DS_HP_DETECT 0x0010
46 #define GPIO_DS_INPUT_ROUTE 0x0040
47 #define GPIO_DS_OUTPUT_ENABLE 0x0180
49 #define LC_CONTROL_LIMITER 0x40000000
50 #define LC_CONTROL_ALC 0x20000000
53 struct xonar_generic generic;
54 u16 wm8776_regs[0x17];
55 u16 wm8766_regs[0x10];
56 struct snd_kcontrol *lc_controls[13];
59 static void wm8776_write(struct oxygen *chip,
60 unsigned int reg, unsigned int value)
62 struct xonar_wm87x6 *data = chip->model_data;
64 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
65 OXYGEN_SPI_DATA_LENGTH_2 |
66 OXYGEN_SPI_CLOCK_160 |
67 (1 << OXYGEN_SPI_CODEC_SHIFT) |
68 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
70 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
71 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
72 value &= ~WM8776_UPDATE;
73 data->wm8776_regs[reg] = value;
77 static void wm8776_write_cached(struct oxygen *chip,
78 unsigned int reg, unsigned int value)
80 struct xonar_wm87x6 *data = chip->model_data;
82 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
83 value != data->wm8776_regs[reg])
84 wm8776_write(chip, reg, value);
87 static void wm8766_write(struct oxygen *chip,
88 unsigned int reg, unsigned int value)
90 struct xonar_wm87x6 *data = chip->model_data;
92 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
93 OXYGEN_SPI_DATA_LENGTH_2 |
94 OXYGEN_SPI_CLOCK_160 |
95 (0 << OXYGEN_SPI_CODEC_SHIFT) |
96 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
98 if (reg < ARRAY_SIZE(data->wm8766_regs))
99 data->wm8766_regs[reg] = value;
102 static void wm8766_write_cached(struct oxygen *chip,
103 unsigned int reg, unsigned int value)
105 struct xonar_wm87x6 *data = chip->model_data;
107 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
108 value != data->wm8766_regs[reg]) {
109 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
110 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
111 value &= ~WM8766_UPDATE;
112 wm8766_write(chip, reg, value);
116 static void wm8776_registers_init(struct oxygen *chip)
118 struct xonar_wm87x6 *data = chip->model_data;
120 wm8776_write(chip, WM8776_RESET, 0);
121 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
122 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
123 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
124 wm8776_write(chip, WM8776_DACIFCTRL,
125 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
126 wm8776_write(chip, WM8776_ADCIFCTRL,
127 data->wm8776_regs[WM8776_ADCIFCTRL]);
128 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
129 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
130 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
131 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
133 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
134 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
135 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
136 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
137 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
140 static void wm8766_registers_init(struct oxygen *chip)
142 wm8766_write(chip, WM8766_RESET, 0);
143 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
144 wm8766_write(chip, WM8766_DAC_CTRL2,
145 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
146 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
147 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
148 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
149 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
150 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
151 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
154 static void wm8776_init(struct oxygen *chip)
156 struct xonar_wm87x6 *data = chip->model_data;
158 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
159 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
160 data->wm8776_regs[WM8776_ADCIFCTRL] =
161 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
162 data->wm8776_regs[WM8776_MSTRCTRL] =
163 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
164 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
165 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
166 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
167 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
168 wm8776_registers_init(chip);
171 static void xonar_ds_init(struct oxygen *chip)
173 struct xonar_wm87x6 *data = chip->model_data;
175 data->generic.anti_pop_delay = 300;
176 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
179 wm8766_registers_init(chip);
181 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
182 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
183 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
184 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
185 chip->interrupt_mask |= OXYGEN_INT_GPIO;
187 xonar_enable_output(chip);
189 snd_component_add(chip->card, "WM8776");
190 snd_component_add(chip->card, "WM8766");
193 static void xonar_ds_cleanup(struct oxygen *chip)
195 xonar_disable_output(chip);
196 wm8776_write(chip, WM8776_RESET, 0);
199 static void xonar_ds_suspend(struct oxygen *chip)
201 xonar_ds_cleanup(chip);
204 static void xonar_ds_resume(struct oxygen *chip)
206 wm8776_registers_init(chip);
207 wm8766_registers_init(chip);
208 xonar_enable_output(chip);
211 static void wm8776_adc_hardware_filter(unsigned int channel,
212 struct snd_pcm_hardware *hardware)
214 if (channel == PCM_A) {
215 hardware->rates = SNDRV_PCM_RATE_32000 |
216 SNDRV_PCM_RATE_44100 |
217 SNDRV_PCM_RATE_48000 |
218 SNDRV_PCM_RATE_64000 |
219 SNDRV_PCM_RATE_88200 |
220 SNDRV_PCM_RATE_96000;
221 hardware->rate_max = 96000;
225 static void set_wm87x6_dac_params(struct oxygen *chip,
226 struct snd_pcm_hw_params *params)
230 static void set_wm8776_adc_params(struct oxygen *chip,
231 struct snd_pcm_hw_params *params)
235 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
236 if (params_rate(params) > 48000)
237 reg |= WM8776_ADCOSR;
238 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
241 static void update_wm8776_volume(struct oxygen *chip)
243 struct xonar_wm87x6 *data = chip->model_data;
246 if (chip->dac_volume[0] == chip->dac_volume[1]) {
247 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
248 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
249 wm8776_write(chip, WM8776_DACMASTER,
250 chip->dac_volume[0] | WM8776_UPDATE);
251 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
252 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
255 to_change = (chip->dac_volume[0] !=
256 data->wm8776_regs[WM8776_DACLVOL]) << 0;
257 to_change |= (chip->dac_volume[1] !=
258 data->wm8776_regs[WM8776_DACLVOL]) << 1;
260 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
261 ((to_change & 2) ? 0 : WM8776_UPDATE));
263 wm8776_write(chip, WM8776_DACRVOL,
264 chip->dac_volume[1] | WM8776_UPDATE);
268 static void update_wm87x6_volume(struct oxygen *chip)
270 static const u8 wm8766_regs[6] = {
271 WM8766_LDA1, WM8766_RDA1,
272 WM8766_LDA2, WM8766_RDA2,
273 WM8766_LDA3, WM8766_RDA3,
275 struct xonar_wm87x6 *data = chip->model_data;
279 update_wm8776_volume(chip);
280 if (chip->dac_volume[2] == chip->dac_volume[3] &&
281 chip->dac_volume[2] == chip->dac_volume[4] &&
282 chip->dac_volume[2] == chip->dac_volume[5] &&
283 chip->dac_volume[2] == chip->dac_volume[6] &&
284 chip->dac_volume[2] == chip->dac_volume[7]) {
286 for (i = 0; i < 6; ++i)
287 if (chip->dac_volume[2] !=
288 data->wm8766_regs[wm8766_regs[i]])
291 wm8766_write(chip, WM8766_MASTDA,
292 chip->dac_volume[2] | WM8766_UPDATE);
293 for (i = 0; i < 6; ++i)
294 data->wm8766_regs[wm8766_regs[i]] =
299 for (i = 0; i < 6; ++i)
300 to_change |= (chip->dac_volume[2 + i] !=
301 data->wm8766_regs[wm8766_regs[i]]) << i;
302 for (i = 0; i < 6; ++i)
303 if (to_change & (1 << i))
304 wm8766_write(chip, wm8766_regs[i],
305 chip->dac_volume[2 + i] |
306 ((to_change & (0x3e << i))
307 ? 0 : WM8766_UPDATE));
311 static void update_wm8776_mute(struct oxygen *chip)
313 wm8776_write_cached(chip, WM8776_DACMUTE,
314 chip->dac_mute ? WM8776_DMUTE : 0);
317 static void update_wm87x6_mute(struct oxygen *chip)
319 update_wm8776_mute(chip);
320 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
321 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
324 static void xonar_ds_gpio_changed(struct oxygen *chip)
328 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
329 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
332 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
333 struct snd_ctl_elem_value *value)
335 struct oxygen *chip = ctl->private_data;
336 struct xonar_wm87x6 *data = chip->model_data;
337 u16 bit = ctl->private_value & 0xffff;
338 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
339 bool invert = (ctl->private_value >> 24) & 1;
341 value->value.integer.value[0] =
342 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
346 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
347 struct snd_ctl_elem_value *value)
349 struct oxygen *chip = ctl->private_data;
350 struct xonar_wm87x6 *data = chip->model_data;
351 u16 bit = ctl->private_value & 0xffff;
353 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
354 bool invert = (ctl->private_value >> 24) & 1;
357 mutex_lock(&chip->mutex);
358 reg_value = data->wm8776_regs[reg_index] & ~bit;
359 if (value->value.integer.value[0] ^ invert)
361 changed = reg_value != data->wm8776_regs[reg_index];
363 wm8776_write(chip, reg_index, reg_value);
364 mutex_unlock(&chip->mutex);
368 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
369 struct snd_ctl_elem_info *info)
371 static const char *const hld[16] = {
372 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
373 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
374 "341 ms", "683 ms", "1.37 s", "2.73 s",
375 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
377 static const char *const atk_lim[11] = {
378 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
379 "4 ms", "8 ms", "16 ms", "32 ms",
380 "64 ms", "128 ms", "256 ms",
382 static const char *const atk_alc[11] = {
383 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
384 "134 ms", "269 ms", "538 ms", "1.08 s",
385 "2.15 s", "4.3 s", "8.6 s",
387 static const char *const dcy_lim[11] = {
388 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
389 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
390 "307 ms", "614 ms", "1.23 s",
392 static const char *const dcy_alc[11] = {
393 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
394 "536 ms", "1.07 s", "2.14 s", "4.29 s",
395 "8.58 s", "17.2 s", "34.3 s",
397 static const char *const tranwin[8] = {
398 "0 us", "62.5 us", "125 us", "250 us",
399 "500 us", "1 ms", "2 ms", "4 ms",
402 const char *const *names;
404 max = (ctl->private_value >> 12) & 0xf;
405 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
407 info->value.enumerated.items = max + 1;
408 if (info->value.enumerated.item > max)
409 info->value.enumerated.item = max;
410 switch ((ctl->private_value >> 24) & 0x1f) {
411 case WM8776_ALCCTRL2:
414 case WM8776_ALCCTRL3:
415 if (((ctl->private_value >> 20) & 0xf) == 0) {
416 if (ctl->private_value & LC_CONTROL_LIMITER)
421 if (ctl->private_value & LC_CONTROL_LIMITER)
433 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
437 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
438 struct snd_ctl_elem_info *info)
440 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
442 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
443 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
447 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
449 struct oxygen *chip = ctl->private_data;
450 struct xonar_wm87x6 *data = chip->model_data;
451 unsigned int value, reg_index, mode;
456 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
457 WM8776_LCSEL_LIMITER)
458 mode = LC_CONTROL_LIMITER;
460 mode = LC_CONTROL_ALC;
461 if (!(ctl->private_value & mode))
464 value = ctl->private_value & 0xf;
465 min = (ctl->private_value >> 8) & 0xf;
466 max = (ctl->private_value >> 12) & 0xf;
467 mask = (ctl->private_value >> 16) & 0xf;
468 shift = (ctl->private_value >> 20) & 0xf;
469 reg_index = (ctl->private_value >> 24) & 0x1f;
470 invert = (ctl->private_value >> 29) & 0x1;
473 value = max - (value - min);
474 reg_value = data->wm8776_regs[reg_index];
475 reg_value &= ~(mask << shift);
476 reg_value |= value << shift;
477 wm8776_write_cached(chip, reg_index, reg_value);
480 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
482 struct oxygen *chip = ctl->private_data;
486 min = (ctl->private_value >> 8) & 0xf;
487 max = (ctl->private_value >> 12) & 0xf;
488 if (value < min || value > max)
490 mutex_lock(&chip->mutex);
491 changed = value != (ctl->private_value & 0xf);
493 ctl->private_value = (ctl->private_value & ~0xf) | value;
494 wm8776_field_set_from_ctl(ctl);
496 mutex_unlock(&chip->mutex);
500 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
501 struct snd_ctl_elem_value *value)
503 value->value.enumerated.item[0] = ctl->private_value & 0xf;
507 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
508 struct snd_ctl_elem_value *value)
510 value->value.integer.value[0] = ctl->private_value & 0xf;
514 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
515 struct snd_ctl_elem_value *value)
517 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
520 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
521 struct snd_ctl_elem_value *value)
523 return wm8776_field_set(ctl, value->value.integer.value[0]);
526 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
527 struct snd_ctl_elem_info *info)
529 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
531 info->value.integer.min = 0x79 - 60;
532 info->value.integer.max = 0x7f;
536 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
537 struct snd_ctl_elem_value *value)
539 struct oxygen *chip = ctl->private_data;
540 struct xonar_wm87x6 *data = chip->model_data;
542 mutex_lock(&chip->mutex);
543 value->value.integer.value[0] =
544 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
545 value->value.integer.value[1] =
546 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
547 mutex_unlock(&chip->mutex);
551 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
552 struct snd_ctl_elem_value *value)
554 struct oxygen *chip = ctl->private_data;
555 struct xonar_wm87x6 *data = chip->model_data;
558 mutex_lock(&chip->mutex);
559 to_update = (value->value.integer.value[0] !=
560 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
562 to_update |= (value->value.integer.value[1] !=
563 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
565 if (value->value.integer.value[0] == value->value.integer.value[1]) {
567 wm8776_write(chip, WM8776_HPMASTER,
568 value->value.integer.value[0] |
569 WM8776_HPZCEN | WM8776_UPDATE);
570 data->wm8776_regs[WM8776_HPLVOL] =
571 value->value.integer.value[0] | WM8776_HPZCEN;
572 data->wm8776_regs[WM8776_HPRVOL] =
573 value->value.integer.value[0] | WM8776_HPZCEN;
577 wm8776_write(chip, WM8776_HPLVOL,
578 value->value.integer.value[0] |
580 ((to_update & 2) ? 0 : WM8776_UPDATE));
582 wm8776_write(chip, WM8776_HPRVOL,
583 value->value.integer.value[1] |
584 WM8776_HPZCEN | WM8776_UPDATE);
586 mutex_unlock(&chip->mutex);
587 return to_update != 0;
590 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
591 struct snd_ctl_elem_value *value)
593 struct oxygen *chip = ctl->private_data;
594 struct xonar_wm87x6 *data = chip->model_data;
595 unsigned int mux_bit = ctl->private_value;
597 value->value.integer.value[0] =
598 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
602 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
603 struct snd_ctl_elem_value *value)
605 struct oxygen *chip = ctl->private_data;
606 struct xonar_wm87x6 *data = chip->model_data;
607 unsigned int mux_bit = ctl->private_value;
611 mutex_lock(&chip->mutex);
612 reg = data->wm8776_regs[WM8776_ADCMUX];
613 if (value->value.integer.value[0]) {
618 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
620 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
621 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
622 GPIO_DS_INPUT_ROUTE);
623 wm8776_write(chip, WM8776_ADCMUX, reg);
625 mutex_unlock(&chip->mutex);
629 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
630 struct snd_ctl_elem_info *info)
632 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
634 info->value.integer.min = 0xa5;
635 info->value.integer.max = 0xff;
639 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
640 struct snd_ctl_elem_value *value)
642 struct oxygen *chip = ctl->private_data;
643 struct xonar_wm87x6 *data = chip->model_data;
645 mutex_lock(&chip->mutex);
646 value->value.integer.value[0] =
647 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
648 value->value.integer.value[1] =
649 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
650 mutex_unlock(&chip->mutex);
654 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
655 struct snd_ctl_elem_value *value)
657 struct oxygen *chip = ctl->private_data;
658 struct xonar_wm87x6 *data = chip->model_data;
661 mutex_lock(&chip->mutex);
662 changed = (value->value.integer.value[0] !=
663 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
664 (value->value.integer.value[1] !=
665 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
666 wm8776_write_cached(chip, WM8776_ADCLVOL,
667 value->value.integer.value[0] | WM8776_ZCA);
668 wm8776_write_cached(chip, WM8776_ADCRVOL,
669 value->value.integer.value[1] | WM8776_ZCA);
670 mutex_unlock(&chip->mutex);
674 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
675 struct snd_ctl_elem_info *info)
677 static const char *const names[3] = {
678 "None", "Peak Limiter", "Automatic Level Control"
680 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
682 info->value.enumerated.items = 3;
683 if (info->value.enumerated.item >= 3)
684 info->value.enumerated.item = 2;
685 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
689 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
690 struct snd_ctl_elem_value *value)
692 struct oxygen *chip = ctl->private_data;
693 struct xonar_wm87x6 *data = chip->model_data;
695 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
696 value->value.enumerated.item[0] = 0;
697 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
698 WM8776_LCSEL_LIMITER)
699 value->value.enumerated.item[0] = 1;
701 value->value.enumerated.item[0] = 2;
705 static void activate_control(struct oxygen *chip,
706 struct snd_kcontrol *ctl, unsigned int mode)
710 if (ctl->private_value & mode)
713 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
714 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
715 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
716 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
720 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
721 struct snd_ctl_elem_value *value)
723 struct oxygen *chip = ctl->private_data;
724 struct xonar_wm87x6 *data = chip->model_data;
725 unsigned int mode = 0, i;
729 if (value->value.enumerated.item[0] >= 3)
731 mutex_lock(&chip->mutex);
732 changed = value->value.enumerated.item[0] != ctl->private_value;
734 ctl->private_value = value->value.enumerated.item[0];
735 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
736 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
737 switch (value->value.enumerated.item[0]) {
739 wm8776_write_cached(chip, WM8776_ALCCTRL2,
740 ctrl2 & ~WM8776_LCEN);
743 wm8776_write_cached(chip, WM8776_ALCCTRL1,
744 (ctrl1 & ~WM8776_LCSEL_MASK) |
745 WM8776_LCSEL_LIMITER);
746 wm8776_write_cached(chip, WM8776_ALCCTRL2,
747 ctrl2 | WM8776_LCEN);
748 mode = LC_CONTROL_LIMITER;
751 wm8776_write_cached(chip, WM8776_ALCCTRL1,
752 (ctrl1 & ~WM8776_LCSEL_MASK) |
753 WM8776_LCSEL_ALC_STEREO);
754 wm8776_write_cached(chip, WM8776_ALCCTRL2,
755 ctrl2 | WM8776_LCEN);
756 mode = LC_CONTROL_ALC;
759 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
760 activate_control(chip, data->lc_controls[i], mode);
762 mutex_unlock(&chip->mutex);
766 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
768 static const char *const names[2] = {
769 "None", "High-pass Filter"
772 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
774 info->value.enumerated.items = 2;
775 if (info->value.enumerated.item >= 2)
776 info->value.enumerated.item = 1;
777 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
781 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
783 struct oxygen *chip = ctl->private_data;
784 struct xonar_wm87x6 *data = chip->model_data;
786 value->value.enumerated.item[0] =
787 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
791 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
793 struct oxygen *chip = ctl->private_data;
794 struct xonar_wm87x6 *data = chip->model_data;
798 mutex_lock(&chip->mutex);
799 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
800 if (!value->value.enumerated.item[0])
801 reg |= WM8776_ADCHPD;
802 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
804 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
805 mutex_unlock(&chip->mutex);
809 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
810 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
812 .info = snd_ctl_boolean_mono_info, \
813 .get = wm8776_bit_switch_get, \
814 .put = wm8776_bit_switch_put, \
815 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
817 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
818 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
820 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
821 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
822 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
823 _WM8776_FIELD_CTL(xname " Capture Enum", \
824 reg, shift, init, min, max, mask, flags), \
825 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
826 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
827 .info = wm8776_field_enum_info, \
828 .get = wm8776_field_enum_get, \
829 .put = wm8776_field_enum_put, \
831 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
832 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
833 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
834 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
835 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
836 .info = wm8776_field_volume_info, \
837 .get = wm8776_field_volume_get, \
838 .put = wm8776_field_volume_put, \
839 .tlv = { .p = tlv_p }, \
842 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
843 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
844 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
845 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
846 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
847 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
848 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
849 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
851 static const struct snd_kcontrol_new ds_controls[] = {
853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
854 .name = "Headphone Playback Volume",
855 .info = wm8776_hp_vol_info,
856 .get = wm8776_hp_vol_get,
857 .put = wm8776_hp_vol_put,
858 .tlv = { .p = wm8776_hp_db_scale },
860 WM8776_BIT_SWITCH("Headphone Playback Switch",
861 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
863 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
864 .name = "Input Capture Volume",
865 .info = wm8776_input_vol_info,
866 .get = wm8776_input_vol_get,
867 .put = wm8776_input_vol_put,
868 .tlv = { .p = wm8776_adc_db_scale },
871 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
872 .name = "Line Capture Switch",
873 .info = snd_ctl_boolean_mono_info,
874 .get = wm8776_input_mux_get,
875 .put = wm8776_input_mux_put,
876 .private_value = 1 << 0,
879 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
880 .name = "Mic Capture Switch",
881 .info = snd_ctl_boolean_mono_info,
882 .get = wm8776_input_mux_get,
883 .put = wm8776_input_mux_put,
884 .private_value = 1 << 1,
886 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
888 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
889 .name = "ADC Filter Capture Enum",
895 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
896 .name = "Level Control Capture Enum",
897 .info = wm8776_level_control_info,
898 .get = wm8776_level_control_get,
899 .put = wm8776_level_control_put,
903 static const struct snd_kcontrol_new lc_controls[] = {
904 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
905 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
906 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
907 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
908 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
910 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
911 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
913 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
914 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
916 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
917 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
919 wm8776_maxatten_lim_db_scale),
920 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
921 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
922 LC_CONTROL_ALC, wm8776_lct_db_scale),
923 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
924 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
926 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
927 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
929 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
930 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
931 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
932 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
933 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
934 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
935 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
936 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
938 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
939 WM8776_NOISEGATE, WM8776_NGAT, 0,
941 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
942 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
943 LC_CONTROL_ALC, wm8776_ngth_db_scale),
946 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
948 if (!strncmp(template->name, "CD Capture ", 11))
949 return 1; /* no CD input */
953 static int xonar_ds_mixer_init(struct oxygen *chip)
955 struct xonar_wm87x6 *data = chip->model_data;
957 struct snd_kcontrol *ctl;
960 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
961 ctl = snd_ctl_new1(&ds_controls[i], chip);
964 err = snd_ctl_add(chip->card, ctl);
968 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
969 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
970 ctl = snd_ctl_new1(&lc_controls[i], chip);
973 err = snd_ctl_add(chip->card, ctl);
976 data->lc_controls[i] = ctl;
981 static const struct oxygen_model model_xonar_ds = {
982 .shortname = "Xonar DS",
983 .longname = "Asus Virtuoso 200",
985 .init = xonar_ds_init,
986 .control_filter = xonar_ds_control_filter,
987 .mixer_init = xonar_ds_mixer_init,
988 .cleanup = xonar_ds_cleanup,
989 .suspend = xonar_ds_suspend,
990 .resume = xonar_ds_resume,
991 .pcm_hardware_filter = wm8776_adc_hardware_filter,
992 .get_i2s_mclk = oxygen_default_i2s_mclk,
993 .set_dac_params = set_wm87x6_dac_params,
994 .set_adc_params = set_wm8776_adc_params,
995 .update_dac_volume = update_wm87x6_volume,
996 .update_dac_mute = update_wm87x6_mute,
997 .gpio_changed = xonar_ds_gpio_changed,
998 .dac_tlv = wm87x6_dac_db_scale,
999 .model_data_size = sizeof(struct xonar_wm87x6),
1000 .device_config = PLAYBACK_0_TO_I2S |
1001 PLAYBACK_1_TO_SPDIF |
1002 CAPTURE_0_FROM_I2S_1,
1004 .dac_volume_min = 255 - 2*60,
1005 .dac_volume_max = 255,
1006 .function_flags = OXYGEN_FUNCTION_SPI,
1007 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1008 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1011 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1012 const struct pci_device_id *id)
1014 switch (id->subdevice) {
1016 chip->model = model_xonar_ds;