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 *line_adcmux_control;
57 struct snd_kcontrol *mic_adcmux_control;
58 struct snd_kcontrol *lc_controls[13];
61 static void wm8776_write(struct oxygen *chip,
62 unsigned int reg, unsigned int value)
64 struct xonar_wm87x6 *data = chip->model_data;
66 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
67 OXYGEN_SPI_DATA_LENGTH_2 |
68 OXYGEN_SPI_CLOCK_160 |
69 (1 << OXYGEN_SPI_CODEC_SHIFT) |
70 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
72 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
73 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
74 value &= ~WM8776_UPDATE;
75 data->wm8776_regs[reg] = value;
79 static void wm8776_write_cached(struct oxygen *chip,
80 unsigned int reg, unsigned int value)
82 struct xonar_wm87x6 *data = chip->model_data;
84 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
85 value != data->wm8776_regs[reg])
86 wm8776_write(chip, reg, value);
89 static void wm8766_write(struct oxygen *chip,
90 unsigned int reg, unsigned int value)
92 struct xonar_wm87x6 *data = chip->model_data;
94 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
95 OXYGEN_SPI_DATA_LENGTH_2 |
96 OXYGEN_SPI_CLOCK_160 |
97 (0 << OXYGEN_SPI_CODEC_SHIFT) |
98 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
100 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
101 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
102 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
103 value &= ~WM8766_UPDATE;
104 data->wm8766_regs[reg] = value;
108 static void wm8766_write_cached(struct oxygen *chip,
109 unsigned int reg, unsigned int value)
111 struct xonar_wm87x6 *data = chip->model_data;
113 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
114 value != data->wm8766_regs[reg])
115 wm8766_write(chip, reg, value);
118 static void wm8776_registers_init(struct oxygen *chip)
120 struct xonar_wm87x6 *data = chip->model_data;
122 wm8776_write(chip, WM8776_RESET, 0);
123 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
124 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
125 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
126 wm8776_write(chip, WM8776_DACIFCTRL,
127 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
128 wm8776_write(chip, WM8776_ADCIFCTRL,
129 data->wm8776_regs[WM8776_ADCIFCTRL]);
130 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
131 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
132 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
133 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
135 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
136 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
137 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
138 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
139 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
142 static void wm8766_registers_init(struct oxygen *chip)
144 wm8766_write(chip, WM8766_RESET, 0);
145 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
146 wm8766_write(chip, WM8766_DAC_CTRL2,
147 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
148 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
149 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
150 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
151 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
152 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
153 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
156 static void wm8776_init(struct oxygen *chip)
158 struct xonar_wm87x6 *data = chip->model_data;
160 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
161 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
162 data->wm8776_regs[WM8776_ADCIFCTRL] =
163 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
164 data->wm8776_regs[WM8776_MSTRCTRL] =
165 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
166 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
167 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
168 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
169 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
170 wm8776_registers_init(chip);
173 static void xonar_ds_init(struct oxygen *chip)
175 struct xonar_wm87x6 *data = chip->model_data;
177 data->generic.anti_pop_delay = 300;
178 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
181 wm8766_registers_init(chip);
183 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
184 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
185 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
186 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
187 chip->interrupt_mask |= OXYGEN_INT_GPIO;
189 xonar_enable_output(chip);
191 snd_component_add(chip->card, "WM8776");
192 snd_component_add(chip->card, "WM8766");
195 static void xonar_ds_cleanup(struct oxygen *chip)
197 xonar_disable_output(chip);
198 wm8776_write(chip, WM8776_RESET, 0);
201 static void xonar_ds_suspend(struct oxygen *chip)
203 xonar_ds_cleanup(chip);
206 static void xonar_ds_resume(struct oxygen *chip)
208 wm8776_registers_init(chip);
209 wm8766_registers_init(chip);
210 xonar_enable_output(chip);
213 static void wm8776_adc_hardware_filter(unsigned int channel,
214 struct snd_pcm_hardware *hardware)
216 if (channel == PCM_A) {
217 hardware->rates = SNDRV_PCM_RATE_32000 |
218 SNDRV_PCM_RATE_44100 |
219 SNDRV_PCM_RATE_48000 |
220 SNDRV_PCM_RATE_64000 |
221 SNDRV_PCM_RATE_88200 |
222 SNDRV_PCM_RATE_96000;
223 hardware->rate_max = 96000;
227 static void set_wm87x6_dac_params(struct oxygen *chip,
228 struct snd_pcm_hw_params *params)
232 static void set_wm8776_adc_params(struct oxygen *chip,
233 struct snd_pcm_hw_params *params)
237 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
238 if (params_rate(params) > 48000)
239 reg |= WM8776_ADCOSR;
240 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
243 static void update_wm8776_volume(struct oxygen *chip)
245 struct xonar_wm87x6 *data = chip->model_data;
248 if (chip->dac_volume[0] == chip->dac_volume[1]) {
249 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
250 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
251 wm8776_write(chip, WM8776_DACMASTER,
252 chip->dac_volume[0] | WM8776_UPDATE);
253 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
254 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
257 to_change = (chip->dac_volume[0] !=
258 data->wm8776_regs[WM8776_DACLVOL]) << 0;
259 to_change |= (chip->dac_volume[1] !=
260 data->wm8776_regs[WM8776_DACLVOL]) << 1;
262 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
263 ((to_change & 2) ? 0 : WM8776_UPDATE));
265 wm8776_write(chip, WM8776_DACRVOL,
266 chip->dac_volume[1] | WM8776_UPDATE);
270 static void update_wm87x6_volume(struct oxygen *chip)
272 static const u8 wm8766_regs[6] = {
273 WM8766_LDA1, WM8766_RDA1,
274 WM8766_LDA2, WM8766_RDA2,
275 WM8766_LDA3, WM8766_RDA3,
277 struct xonar_wm87x6 *data = chip->model_data;
281 update_wm8776_volume(chip);
282 if (chip->dac_volume[2] == chip->dac_volume[3] &&
283 chip->dac_volume[2] == chip->dac_volume[4] &&
284 chip->dac_volume[2] == chip->dac_volume[5] &&
285 chip->dac_volume[2] == chip->dac_volume[6] &&
286 chip->dac_volume[2] == chip->dac_volume[7]) {
288 for (i = 0; i < 6; ++i)
289 if (chip->dac_volume[2] !=
290 data->wm8766_regs[wm8766_regs[i]])
293 wm8766_write(chip, WM8766_MASTDA,
294 chip->dac_volume[2] | WM8766_UPDATE);
295 for (i = 0; i < 6; ++i)
296 data->wm8766_regs[wm8766_regs[i]] =
301 for (i = 0; i < 6; ++i)
302 to_change |= (chip->dac_volume[2 + i] !=
303 data->wm8766_regs[wm8766_regs[i]]) << i;
304 for (i = 0; i < 6; ++i)
305 if (to_change & (1 << i))
306 wm8766_write(chip, wm8766_regs[i],
307 chip->dac_volume[2 + i] |
308 ((to_change & (0x3e << i))
309 ? 0 : WM8766_UPDATE));
313 static void update_wm8776_mute(struct oxygen *chip)
315 wm8776_write_cached(chip, WM8776_DACMUTE,
316 chip->dac_mute ? WM8776_DMUTE : 0);
319 static void update_wm87x6_mute(struct oxygen *chip)
321 update_wm8776_mute(chip);
322 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
323 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
326 static void xonar_ds_gpio_changed(struct oxygen *chip)
330 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
331 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
334 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
335 struct snd_ctl_elem_value *value)
337 struct oxygen *chip = ctl->private_data;
338 struct xonar_wm87x6 *data = chip->model_data;
339 u16 bit = ctl->private_value & 0xffff;
340 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
341 bool invert = (ctl->private_value >> 24) & 1;
343 value->value.integer.value[0] =
344 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
348 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
349 struct snd_ctl_elem_value *value)
351 struct oxygen *chip = ctl->private_data;
352 struct xonar_wm87x6 *data = chip->model_data;
353 u16 bit = ctl->private_value & 0xffff;
355 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
356 bool invert = (ctl->private_value >> 24) & 1;
359 mutex_lock(&chip->mutex);
360 reg_value = data->wm8776_regs[reg_index] & ~bit;
361 if (value->value.integer.value[0] ^ invert)
363 changed = reg_value != data->wm8776_regs[reg_index];
365 wm8776_write(chip, reg_index, reg_value);
366 mutex_unlock(&chip->mutex);
370 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
371 struct snd_ctl_elem_info *info)
373 static const char *const hld[16] = {
374 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
375 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
376 "341 ms", "683 ms", "1.37 s", "2.73 s",
377 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
379 static const char *const atk_lim[11] = {
380 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
381 "4 ms", "8 ms", "16 ms", "32 ms",
382 "64 ms", "128 ms", "256 ms",
384 static const char *const atk_alc[11] = {
385 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
386 "134 ms", "269 ms", "538 ms", "1.08 s",
387 "2.15 s", "4.3 s", "8.6 s",
389 static const char *const dcy_lim[11] = {
390 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
391 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
392 "307 ms", "614 ms", "1.23 s",
394 static const char *const dcy_alc[11] = {
395 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
396 "536 ms", "1.07 s", "2.14 s", "4.29 s",
397 "8.58 s", "17.2 s", "34.3 s",
399 static const char *const tranwin[8] = {
400 "0 us", "62.5 us", "125 us", "250 us",
401 "500 us", "1 ms", "2 ms", "4 ms",
404 const char *const *names;
406 max = (ctl->private_value >> 12) & 0xf;
407 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
409 info->value.enumerated.items = max + 1;
410 if (info->value.enumerated.item > max)
411 info->value.enumerated.item = max;
412 switch ((ctl->private_value >> 24) & 0x1f) {
413 case WM8776_ALCCTRL2:
416 case WM8776_ALCCTRL3:
417 if (((ctl->private_value >> 20) & 0xf) == 0) {
418 if (ctl->private_value & LC_CONTROL_LIMITER)
423 if (ctl->private_value & LC_CONTROL_LIMITER)
435 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
439 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
440 struct snd_ctl_elem_info *info)
442 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
444 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
445 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
449 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
451 struct oxygen *chip = ctl->private_data;
452 struct xonar_wm87x6 *data = chip->model_data;
453 unsigned int value, reg_index, mode;
458 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
459 WM8776_LCSEL_LIMITER)
460 mode = LC_CONTROL_LIMITER;
462 mode = LC_CONTROL_ALC;
463 if (!(ctl->private_value & mode))
466 value = ctl->private_value & 0xf;
467 min = (ctl->private_value >> 8) & 0xf;
468 max = (ctl->private_value >> 12) & 0xf;
469 mask = (ctl->private_value >> 16) & 0xf;
470 shift = (ctl->private_value >> 20) & 0xf;
471 reg_index = (ctl->private_value >> 24) & 0x1f;
472 invert = (ctl->private_value >> 29) & 0x1;
475 value = max - (value - min);
476 reg_value = data->wm8776_regs[reg_index];
477 reg_value &= ~(mask << shift);
478 reg_value |= value << shift;
479 wm8776_write_cached(chip, reg_index, reg_value);
482 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
484 struct oxygen *chip = ctl->private_data;
488 min = (ctl->private_value >> 8) & 0xf;
489 max = (ctl->private_value >> 12) & 0xf;
490 if (value < min || value > max)
492 mutex_lock(&chip->mutex);
493 changed = value != (ctl->private_value & 0xf);
495 ctl->private_value = (ctl->private_value & ~0xf) | value;
496 wm8776_field_set_from_ctl(ctl);
498 mutex_unlock(&chip->mutex);
502 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
503 struct snd_ctl_elem_value *value)
505 value->value.enumerated.item[0] = ctl->private_value & 0xf;
509 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
510 struct snd_ctl_elem_value *value)
512 value->value.integer.value[0] = ctl->private_value & 0xf;
516 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
517 struct snd_ctl_elem_value *value)
519 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
522 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
523 struct snd_ctl_elem_value *value)
525 return wm8776_field_set(ctl, value->value.integer.value[0]);
528 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
529 struct snd_ctl_elem_info *info)
531 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
533 info->value.integer.min = 0x79 - 60;
534 info->value.integer.max = 0x7f;
538 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
539 struct snd_ctl_elem_value *value)
541 struct oxygen *chip = ctl->private_data;
542 struct xonar_wm87x6 *data = chip->model_data;
544 mutex_lock(&chip->mutex);
545 value->value.integer.value[0] =
546 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
547 value->value.integer.value[1] =
548 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
549 mutex_unlock(&chip->mutex);
553 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
554 struct snd_ctl_elem_value *value)
556 struct oxygen *chip = ctl->private_data;
557 struct xonar_wm87x6 *data = chip->model_data;
560 mutex_lock(&chip->mutex);
561 to_update = (value->value.integer.value[0] !=
562 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
564 to_update |= (value->value.integer.value[1] !=
565 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
567 if (value->value.integer.value[0] == value->value.integer.value[1]) {
569 wm8776_write(chip, WM8776_HPMASTER,
570 value->value.integer.value[0] |
571 WM8776_HPZCEN | WM8776_UPDATE);
572 data->wm8776_regs[WM8776_HPLVOL] =
573 value->value.integer.value[0] | WM8776_HPZCEN;
574 data->wm8776_regs[WM8776_HPRVOL] =
575 value->value.integer.value[0] | WM8776_HPZCEN;
579 wm8776_write(chip, WM8776_HPLVOL,
580 value->value.integer.value[0] |
582 ((to_update & 2) ? 0 : WM8776_UPDATE));
584 wm8776_write(chip, WM8776_HPRVOL,
585 value->value.integer.value[1] |
586 WM8776_HPZCEN | WM8776_UPDATE);
588 mutex_unlock(&chip->mutex);
589 return to_update != 0;
592 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
593 struct snd_ctl_elem_value *value)
595 struct oxygen *chip = ctl->private_data;
596 struct xonar_wm87x6 *data = chip->model_data;
597 unsigned int mux_bit = ctl->private_value;
599 value->value.integer.value[0] =
600 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
604 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
605 struct snd_ctl_elem_value *value)
607 struct oxygen *chip = ctl->private_data;
608 struct xonar_wm87x6 *data = chip->model_data;
609 struct snd_kcontrol *other_ctl;
610 unsigned int mux_bit = ctl->private_value;
614 mutex_lock(&chip->mutex);
615 reg = data->wm8776_regs[WM8776_ADCMUX];
616 if (value->value.integer.value[0]) {
618 /* line-in and mic-in are exclusive */
623 other_ctl = data->line_adcmux_control;
625 other_ctl = data->mic_adcmux_control;
626 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
631 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
633 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
634 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
635 GPIO_DS_INPUT_ROUTE);
636 wm8776_write(chip, WM8776_ADCMUX, reg);
638 mutex_unlock(&chip->mutex);
642 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
643 struct snd_ctl_elem_info *info)
645 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
647 info->value.integer.min = 0xa5;
648 info->value.integer.max = 0xff;
652 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
653 struct snd_ctl_elem_value *value)
655 struct oxygen *chip = ctl->private_data;
656 struct xonar_wm87x6 *data = chip->model_data;
658 mutex_lock(&chip->mutex);
659 value->value.integer.value[0] =
660 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
661 value->value.integer.value[1] =
662 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
663 mutex_unlock(&chip->mutex);
667 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
668 struct snd_ctl_elem_value *value)
670 struct oxygen *chip = ctl->private_data;
671 struct xonar_wm87x6 *data = chip->model_data;
674 mutex_lock(&chip->mutex);
675 changed = (value->value.integer.value[0] !=
676 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
677 (value->value.integer.value[1] !=
678 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
679 wm8776_write_cached(chip, WM8776_ADCLVOL,
680 value->value.integer.value[0] | WM8776_ZCA);
681 wm8776_write_cached(chip, WM8776_ADCRVOL,
682 value->value.integer.value[1] | WM8776_ZCA);
683 mutex_unlock(&chip->mutex);
687 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
688 struct snd_ctl_elem_info *info)
690 static const char *const names[3] = {
691 "None", "Peak Limiter", "Automatic Level Control"
693 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
695 info->value.enumerated.items = 3;
696 if (info->value.enumerated.item >= 3)
697 info->value.enumerated.item = 2;
698 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
702 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
703 struct snd_ctl_elem_value *value)
705 struct oxygen *chip = ctl->private_data;
706 struct xonar_wm87x6 *data = chip->model_data;
708 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
709 value->value.enumerated.item[0] = 0;
710 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
711 WM8776_LCSEL_LIMITER)
712 value->value.enumerated.item[0] = 1;
714 value->value.enumerated.item[0] = 2;
718 static void activate_control(struct oxygen *chip,
719 struct snd_kcontrol *ctl, unsigned int mode)
723 if (ctl->private_value & mode)
726 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
727 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
728 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
729 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
733 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
734 struct snd_ctl_elem_value *value)
736 struct oxygen *chip = ctl->private_data;
737 struct xonar_wm87x6 *data = chip->model_data;
738 unsigned int mode = 0, i;
742 if (value->value.enumerated.item[0] >= 3)
744 mutex_lock(&chip->mutex);
745 changed = value->value.enumerated.item[0] != ctl->private_value;
747 ctl->private_value = value->value.enumerated.item[0];
748 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
749 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
750 switch (value->value.enumerated.item[0]) {
752 wm8776_write_cached(chip, WM8776_ALCCTRL2,
753 ctrl2 & ~WM8776_LCEN);
756 wm8776_write_cached(chip, WM8776_ALCCTRL1,
757 (ctrl1 & ~WM8776_LCSEL_MASK) |
758 WM8776_LCSEL_LIMITER);
759 wm8776_write_cached(chip, WM8776_ALCCTRL2,
760 ctrl2 | WM8776_LCEN);
761 mode = LC_CONTROL_LIMITER;
764 wm8776_write_cached(chip, WM8776_ALCCTRL1,
765 (ctrl1 & ~WM8776_LCSEL_MASK) |
766 WM8776_LCSEL_ALC_STEREO);
767 wm8776_write_cached(chip, WM8776_ALCCTRL2,
768 ctrl2 | WM8776_LCEN);
769 mode = LC_CONTROL_ALC;
772 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
773 activate_control(chip, data->lc_controls[i], mode);
775 mutex_unlock(&chip->mutex);
779 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
781 static const char *const names[2] = {
782 "None", "High-pass Filter"
785 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
787 info->value.enumerated.items = 2;
788 if (info->value.enumerated.item >= 2)
789 info->value.enumerated.item = 1;
790 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
794 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
796 struct oxygen *chip = ctl->private_data;
797 struct xonar_wm87x6 *data = chip->model_data;
799 value->value.enumerated.item[0] =
800 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
804 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
806 struct oxygen *chip = ctl->private_data;
807 struct xonar_wm87x6 *data = chip->model_data;
811 mutex_lock(&chip->mutex);
812 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
813 if (!value->value.enumerated.item[0])
814 reg |= WM8776_ADCHPD;
815 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
817 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
818 mutex_unlock(&chip->mutex);
822 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
825 .info = snd_ctl_boolean_mono_info, \
826 .get = wm8776_bit_switch_get, \
827 .put = wm8776_bit_switch_put, \
828 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
830 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
833 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
834 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
835 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
836 _WM8776_FIELD_CTL(xname " Capture Enum", \
837 reg, shift, init, min, max, mask, flags), \
838 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
839 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
840 .info = wm8776_field_enum_info, \
841 .get = wm8776_field_enum_get, \
842 .put = wm8776_field_enum_put, \
844 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
845 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
846 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
847 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
848 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
849 .info = wm8776_field_volume_info, \
850 .get = wm8776_field_volume_get, \
851 .put = wm8776_field_volume_put, \
852 .tlv = { .p = tlv_p }, \
855 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
856 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
857 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
858 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
859 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
860 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
861 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
862 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
864 static const struct snd_kcontrol_new ds_controls[] = {
866 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
867 .name = "Headphone Playback Volume",
868 .info = wm8776_hp_vol_info,
869 .get = wm8776_hp_vol_get,
870 .put = wm8776_hp_vol_put,
871 .tlv = { .p = wm8776_hp_db_scale },
873 WM8776_BIT_SWITCH("Headphone Playback Switch",
874 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877 .name = "Input Capture Volume",
878 .info = wm8776_input_vol_info,
879 .get = wm8776_input_vol_get,
880 .put = wm8776_input_vol_put,
881 .tlv = { .p = wm8776_adc_db_scale },
884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
885 .name = "Line Capture Switch",
886 .info = snd_ctl_boolean_mono_info,
887 .get = wm8776_input_mux_get,
888 .put = wm8776_input_mux_put,
889 .private_value = 1 << 0,
892 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
893 .name = "Mic Capture Switch",
894 .info = snd_ctl_boolean_mono_info,
895 .get = wm8776_input_mux_get,
896 .put = wm8776_input_mux_put,
897 .private_value = 1 << 1,
899 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .name = "ADC Filter Capture Enum",
908 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
909 .name = "Level Control Capture Enum",
910 .info = wm8776_level_control_info,
911 .get = wm8776_level_control_get,
912 .put = wm8776_level_control_put,
916 static const struct snd_kcontrol_new lc_controls[] = {
917 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
918 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
919 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
920 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
921 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
923 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
924 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
926 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
927 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
929 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
930 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
932 wm8776_maxatten_lim_db_scale),
933 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
934 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
935 LC_CONTROL_ALC, wm8776_lct_db_scale),
936 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
937 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
939 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
940 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
942 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
943 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
944 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
945 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
946 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
947 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
948 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
949 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
951 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
952 WM8776_NOISEGATE, WM8776_NGAT, 0,
954 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
955 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
956 LC_CONTROL_ALC, wm8776_ngth_db_scale),
959 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
961 if (!strncmp(template->name, "CD Capture ", 11))
962 return 1; /* no CD input */
966 static int xonar_ds_mixer_init(struct oxygen *chip)
968 struct xonar_wm87x6 *data = chip->model_data;
970 struct snd_kcontrol *ctl;
973 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
974 ctl = snd_ctl_new1(&ds_controls[i], chip);
977 err = snd_ctl_add(chip->card, ctl);
980 if (!strcmp(ctl->id.name, "Line Capture Switch"))
981 data->line_adcmux_control = ctl;
982 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
983 data->mic_adcmux_control = ctl;
985 if (!data->line_adcmux_control || !data->mic_adcmux_control)
987 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
988 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
989 ctl = snd_ctl_new1(&lc_controls[i], chip);
992 err = snd_ctl_add(chip->card, ctl);
995 data->lc_controls[i] = ctl;
1000 static const struct oxygen_model model_xonar_ds = {
1001 .shortname = "Xonar DS",
1002 .longname = "Asus Virtuoso 200",
1004 .init = xonar_ds_init,
1005 .control_filter = xonar_ds_control_filter,
1006 .mixer_init = xonar_ds_mixer_init,
1007 .cleanup = xonar_ds_cleanup,
1008 .suspend = xonar_ds_suspend,
1009 .resume = xonar_ds_resume,
1010 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1011 .get_i2s_mclk = oxygen_default_i2s_mclk,
1012 .set_dac_params = set_wm87x6_dac_params,
1013 .set_adc_params = set_wm8776_adc_params,
1014 .update_dac_volume = update_wm87x6_volume,
1015 .update_dac_mute = update_wm87x6_mute,
1016 .gpio_changed = xonar_ds_gpio_changed,
1017 .dac_tlv = wm87x6_dac_db_scale,
1018 .model_data_size = sizeof(struct xonar_wm87x6),
1019 .device_config = PLAYBACK_0_TO_I2S |
1020 PLAYBACK_1_TO_SPDIF |
1021 CAPTURE_0_FROM_I2S_1,
1023 .dac_volume_min = 255 - 2*60,
1024 .dac_volume_max = 255,
1025 .function_flags = OXYGEN_FUNCTION_SPI,
1026 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1027 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1030 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1031 const struct pci_device_id *id)
1033 switch (id->subdevice) {
1035 chip->model = model_xonar_ds;