ALSA: oxygen: simplify model-specific MCLK handling
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / sound / pci / oxygen / xonar_wm87x6.c
blob4f9657084603897c868802b268a32c57dcb6c7b1
1 /*
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/>.
20 * Xonar DS
21 * --------
23 * CMI8788:
25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input)
28 * GPIO 4 <- headphone detect, 0 = plugged
29 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
30 * GPIO 7 -> enable output to front L/R speaker channels
31 * GPIO 8 -> enable output to other speaker channels and front panel headphone
33 * WM8776:
35 * input 1 <- line
36 * input 2 <- mic
37 * input 3 <- front mic
38 * input 4 <- aux
42 * Xonar HDAV1.3 Slim
43 * ------------------
45 * CMI8788:
47 * I²C <-> WM8776 (addr 0011010)
49 * GPIO 0 -> disable HDMI output
50 * GPIO 1 -> enable HP output
51 * GPIO 6 -> firmware EEPROM I²C clock
52 * GPIO 7 <-> firmware EEPROM I²C data
54 * UART <-> HDMI controller
56 * WM8776:
58 * input 1 <- mic
59 * input 2 <- aux
62 #include <linux/pci.h>
63 #include <linux/delay.h>
64 #include <sound/control.h>
65 #include <sound/core.h>
66 #include <sound/info.h>
67 #include <sound/jack.h>
68 #include <sound/pcm.h>
69 #include <sound/pcm_params.h>
70 #include <sound/tlv.h>
71 #include "xonar.h"
72 #include "wm8776.h"
73 #include "wm8766.h"
75 #define GPIO_DS_HP_DETECT 0x0010
76 #define GPIO_DS_INPUT_ROUTE 0x0040
77 #define GPIO_DS_OUTPUT_FRONTLR 0x0080
78 #define GPIO_DS_OUTPUT_ENABLE 0x0100
80 #define LC_CONTROL_LIMITER 0x40000000
81 #define LC_CONTROL_ALC 0x20000000
83 struct xonar_wm87x6 {
84 struct xonar_generic generic;
85 u16 wm8776_regs[0x17];
86 u16 wm8766_regs[0x10];
87 struct snd_kcontrol *line_adcmux_control;
88 struct snd_kcontrol *mic_adcmux_control;
89 struct snd_kcontrol *lc_controls[13];
90 struct snd_jack *hp_jack;
93 static void wm8776_write(struct oxygen *chip,
94 unsigned int reg, unsigned int value)
96 struct xonar_wm87x6 *data = chip->model_data;
98 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
99 OXYGEN_SPI_DATA_LENGTH_2 |
100 OXYGEN_SPI_CLOCK_160 |
101 (1 << OXYGEN_SPI_CODEC_SHIFT) |
102 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
103 (reg << 9) | value);
104 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
105 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
106 value &= ~WM8776_UPDATE;
107 data->wm8776_regs[reg] = value;
111 static void wm8776_write_cached(struct oxygen *chip,
112 unsigned int reg, unsigned int value)
114 struct xonar_wm87x6 *data = chip->model_data;
116 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
117 value != data->wm8776_regs[reg])
118 wm8776_write(chip, reg, value);
121 static void wm8766_write(struct oxygen *chip,
122 unsigned int reg, unsigned int value)
124 struct xonar_wm87x6 *data = chip->model_data;
126 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
127 OXYGEN_SPI_DATA_LENGTH_2 |
128 OXYGEN_SPI_CLOCK_160 |
129 (0 << OXYGEN_SPI_CODEC_SHIFT) |
130 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
131 (reg << 9) | value);
132 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
133 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
134 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
135 value &= ~WM8766_UPDATE;
136 data->wm8766_regs[reg] = value;
140 static void wm8766_write_cached(struct oxygen *chip,
141 unsigned int reg, unsigned int value)
143 struct xonar_wm87x6 *data = chip->model_data;
145 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
146 value != data->wm8766_regs[reg])
147 wm8766_write(chip, reg, value);
150 static void wm8776_registers_init(struct oxygen *chip)
152 struct xonar_wm87x6 *data = chip->model_data;
154 wm8776_write(chip, WM8776_RESET, 0);
155 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
156 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
157 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
158 wm8776_write(chip, WM8776_DACIFCTRL,
159 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
160 wm8776_write(chip, WM8776_ADCIFCTRL,
161 data->wm8776_regs[WM8776_ADCIFCTRL]);
162 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
163 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
164 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
165 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
166 WM8776_UPDATE);
167 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
168 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
169 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
170 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
171 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
174 static void wm8766_registers_init(struct oxygen *chip)
176 struct xonar_wm87x6 *data = chip->model_data;
178 wm8766_write(chip, WM8766_RESET, 0);
179 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
180 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
181 wm8766_write(chip, WM8766_DAC_CTRL2,
182 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
183 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
184 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
185 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
186 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
187 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
188 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
191 static void wm8776_init(struct oxygen *chip)
193 struct xonar_wm87x6 *data = chip->model_data;
195 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
196 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
197 data->wm8776_regs[WM8776_ADCIFCTRL] =
198 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
199 data->wm8776_regs[WM8776_MSTRCTRL] =
200 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
201 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
202 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
203 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
204 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
205 wm8776_registers_init(chip);
208 static void wm8766_init(struct oxygen *chip)
210 struct xonar_wm87x6 *data = chip->model_data;
212 data->wm8766_regs[WM8766_DAC_CTRL] =
213 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
214 wm8766_registers_init(chip);
217 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
219 struct xonar_wm87x6 *data = chip->model_data;
220 bool hp_plugged;
221 unsigned int reg;
223 mutex_lock(&chip->mutex);
225 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
226 GPIO_DS_HP_DETECT);
228 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
229 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
230 GPIO_DS_OUTPUT_FRONTLR);
232 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
233 if (hp_plugged)
234 reg |= WM8766_MUTEALL;
235 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
237 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
239 mutex_unlock(&chip->mutex);
242 static void xonar_ds_init(struct oxygen *chip)
244 struct xonar_wm87x6 *data = chip->model_data;
246 data->generic.anti_pop_delay = 300;
247 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
249 wm8776_init(chip);
250 wm8766_init(chip);
252 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
253 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
254 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
255 GPIO_DS_HP_DETECT);
256 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
257 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
258 chip->interrupt_mask |= OXYGEN_INT_GPIO;
260 xonar_enable_output(chip);
262 snd_jack_new(chip->card, "Headphone",
263 SND_JACK_HEADPHONE, &data->hp_jack);
264 xonar_ds_handle_hp_jack(chip);
266 snd_component_add(chip->card, "WM8776");
267 snd_component_add(chip->card, "WM8766");
270 static void xonar_ds_cleanup(struct oxygen *chip)
272 xonar_disable_output(chip);
273 wm8776_write(chip, WM8776_RESET, 0);
276 static void xonar_ds_suspend(struct oxygen *chip)
278 xonar_ds_cleanup(chip);
281 static void xonar_ds_resume(struct oxygen *chip)
283 wm8776_registers_init(chip);
284 wm8766_registers_init(chip);
285 xonar_enable_output(chip);
286 xonar_ds_handle_hp_jack(chip);
289 static void wm8776_adc_hardware_filter(unsigned int channel,
290 struct snd_pcm_hardware *hardware)
292 if (channel == PCM_A) {
293 hardware->rates = SNDRV_PCM_RATE_32000 |
294 SNDRV_PCM_RATE_44100 |
295 SNDRV_PCM_RATE_48000 |
296 SNDRV_PCM_RATE_64000 |
297 SNDRV_PCM_RATE_88200 |
298 SNDRV_PCM_RATE_96000;
299 hardware->rate_max = 96000;
303 static void set_wm87x6_dac_params(struct oxygen *chip,
304 struct snd_pcm_hw_params *params)
308 static void set_wm8776_adc_params(struct oxygen *chip,
309 struct snd_pcm_hw_params *params)
311 u16 reg;
313 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
314 if (params_rate(params) > 48000)
315 reg |= WM8776_ADCOSR;
316 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
319 static void update_wm8776_volume(struct oxygen *chip)
321 struct xonar_wm87x6 *data = chip->model_data;
322 u8 to_change;
324 if (chip->dac_volume[0] == chip->dac_volume[1]) {
325 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
326 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
327 wm8776_write(chip, WM8776_DACMASTER,
328 chip->dac_volume[0] | WM8776_UPDATE);
329 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
330 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
332 } else {
333 to_change = (chip->dac_volume[0] !=
334 data->wm8776_regs[WM8776_DACLVOL]) << 0;
335 to_change |= (chip->dac_volume[1] !=
336 data->wm8776_regs[WM8776_DACLVOL]) << 1;
337 if (to_change & 1)
338 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
339 ((to_change & 2) ? 0 : WM8776_UPDATE));
340 if (to_change & 2)
341 wm8776_write(chip, WM8776_DACRVOL,
342 chip->dac_volume[1] | WM8776_UPDATE);
346 static void update_wm87x6_volume(struct oxygen *chip)
348 static const u8 wm8766_regs[6] = {
349 WM8766_LDA1, WM8766_RDA1,
350 WM8766_LDA2, WM8766_RDA2,
351 WM8766_LDA3, WM8766_RDA3,
353 struct xonar_wm87x6 *data = chip->model_data;
354 unsigned int i;
355 u8 to_change;
357 update_wm8776_volume(chip);
358 if (chip->dac_volume[2] == chip->dac_volume[3] &&
359 chip->dac_volume[2] == chip->dac_volume[4] &&
360 chip->dac_volume[2] == chip->dac_volume[5] &&
361 chip->dac_volume[2] == chip->dac_volume[6] &&
362 chip->dac_volume[2] == chip->dac_volume[7]) {
363 to_change = 0;
364 for (i = 0; i < 6; ++i)
365 if (chip->dac_volume[2] !=
366 data->wm8766_regs[wm8766_regs[i]])
367 to_change = 1;
368 if (to_change) {
369 wm8766_write(chip, WM8766_MASTDA,
370 chip->dac_volume[2] | WM8766_UPDATE);
371 for (i = 0; i < 6; ++i)
372 data->wm8766_regs[wm8766_regs[i]] =
373 chip->dac_volume[2];
375 } else {
376 to_change = 0;
377 for (i = 0; i < 6; ++i)
378 to_change |= (chip->dac_volume[2 + i] !=
379 data->wm8766_regs[wm8766_regs[i]]) << i;
380 for (i = 0; i < 6; ++i)
381 if (to_change & (1 << i))
382 wm8766_write(chip, wm8766_regs[i],
383 chip->dac_volume[2 + i] |
384 ((to_change & (0x3e << i))
385 ? 0 : WM8766_UPDATE));
389 static void update_wm8776_mute(struct oxygen *chip)
391 wm8776_write_cached(chip, WM8776_DACMUTE,
392 chip->dac_mute ? WM8776_DMUTE : 0);
395 static void update_wm87x6_mute(struct oxygen *chip)
397 update_wm8776_mute(chip);
398 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
399 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
402 static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
404 struct xonar_wm87x6 *data = chip->model_data;
405 unsigned int reg;
408 * The WM8766 can mix left and right channels, but this setting
409 * applies to all three stereo pairs.
411 reg = data->wm8766_regs[WM8766_DAC_CTRL] &
412 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
413 if (mixed)
414 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
415 else
416 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
417 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
420 static void xonar_ds_gpio_changed(struct oxygen *chip)
422 xonar_ds_handle_hp_jack(chip);
425 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
426 struct snd_ctl_elem_value *value)
428 struct oxygen *chip = ctl->private_data;
429 struct xonar_wm87x6 *data = chip->model_data;
430 u16 bit = ctl->private_value & 0xffff;
431 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
432 bool invert = (ctl->private_value >> 24) & 1;
434 value->value.integer.value[0] =
435 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
436 return 0;
439 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
440 struct snd_ctl_elem_value *value)
442 struct oxygen *chip = ctl->private_data;
443 struct xonar_wm87x6 *data = chip->model_data;
444 u16 bit = ctl->private_value & 0xffff;
445 u16 reg_value;
446 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
447 bool invert = (ctl->private_value >> 24) & 1;
448 int changed;
450 mutex_lock(&chip->mutex);
451 reg_value = data->wm8776_regs[reg_index] & ~bit;
452 if (value->value.integer.value[0] ^ invert)
453 reg_value |= bit;
454 changed = reg_value != data->wm8776_regs[reg_index];
455 if (changed)
456 wm8776_write(chip, reg_index, reg_value);
457 mutex_unlock(&chip->mutex);
458 return changed;
461 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
462 struct snd_ctl_elem_info *info)
464 static const char *const hld[16] = {
465 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
466 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
467 "341 ms", "683 ms", "1.37 s", "2.73 s",
468 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
470 static const char *const atk_lim[11] = {
471 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
472 "4 ms", "8 ms", "16 ms", "32 ms",
473 "64 ms", "128 ms", "256 ms",
475 static const char *const atk_alc[11] = {
476 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
477 "134 ms", "269 ms", "538 ms", "1.08 s",
478 "2.15 s", "4.3 s", "8.6 s",
480 static const char *const dcy_lim[11] = {
481 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
482 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
483 "307 ms", "614 ms", "1.23 s",
485 static const char *const dcy_alc[11] = {
486 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
487 "536 ms", "1.07 s", "2.14 s", "4.29 s",
488 "8.58 s", "17.2 s", "34.3 s",
490 static const char *const tranwin[8] = {
491 "0 us", "62.5 us", "125 us", "250 us",
492 "500 us", "1 ms", "2 ms", "4 ms",
494 u8 max;
495 const char *const *names;
497 max = (ctl->private_value >> 12) & 0xf;
498 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
499 info->count = 1;
500 info->value.enumerated.items = max + 1;
501 if (info->value.enumerated.item > max)
502 info->value.enumerated.item = max;
503 switch ((ctl->private_value >> 24) & 0x1f) {
504 case WM8776_ALCCTRL2:
505 names = hld;
506 break;
507 case WM8776_ALCCTRL3:
508 if (((ctl->private_value >> 20) & 0xf) == 0) {
509 if (ctl->private_value & LC_CONTROL_LIMITER)
510 names = atk_lim;
511 else
512 names = atk_alc;
513 } else {
514 if (ctl->private_value & LC_CONTROL_LIMITER)
515 names = dcy_lim;
516 else
517 names = dcy_alc;
519 break;
520 case WM8776_LIMITER:
521 names = tranwin;
522 break;
523 default:
524 return -ENXIO;
526 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
527 return 0;
530 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
531 struct snd_ctl_elem_info *info)
533 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
534 info->count = 1;
535 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
536 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
537 return 0;
540 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
542 struct oxygen *chip = ctl->private_data;
543 struct xonar_wm87x6 *data = chip->model_data;
544 unsigned int value, reg_index, mode;
545 u8 min, max, shift;
546 u16 mask, reg_value;
547 bool invert;
549 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
550 WM8776_LCSEL_LIMITER)
551 mode = LC_CONTROL_LIMITER;
552 else
553 mode = LC_CONTROL_ALC;
554 if (!(ctl->private_value & mode))
555 return;
557 value = ctl->private_value & 0xf;
558 min = (ctl->private_value >> 8) & 0xf;
559 max = (ctl->private_value >> 12) & 0xf;
560 mask = (ctl->private_value >> 16) & 0xf;
561 shift = (ctl->private_value >> 20) & 0xf;
562 reg_index = (ctl->private_value >> 24) & 0x1f;
563 invert = (ctl->private_value >> 29) & 0x1;
565 if (invert)
566 value = max - (value - min);
567 reg_value = data->wm8776_regs[reg_index];
568 reg_value &= ~(mask << shift);
569 reg_value |= value << shift;
570 wm8776_write_cached(chip, reg_index, reg_value);
573 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
575 struct oxygen *chip = ctl->private_data;
576 u8 min, max;
577 int changed;
579 min = (ctl->private_value >> 8) & 0xf;
580 max = (ctl->private_value >> 12) & 0xf;
581 if (value < min || value > max)
582 return -EINVAL;
583 mutex_lock(&chip->mutex);
584 changed = value != (ctl->private_value & 0xf);
585 if (changed) {
586 ctl->private_value = (ctl->private_value & ~0xf) | value;
587 wm8776_field_set_from_ctl(ctl);
589 mutex_unlock(&chip->mutex);
590 return changed;
593 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
594 struct snd_ctl_elem_value *value)
596 value->value.enumerated.item[0] = ctl->private_value & 0xf;
597 return 0;
600 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
601 struct snd_ctl_elem_value *value)
603 value->value.integer.value[0] = ctl->private_value & 0xf;
604 return 0;
607 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
608 struct snd_ctl_elem_value *value)
610 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
613 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
614 struct snd_ctl_elem_value *value)
616 return wm8776_field_set(ctl, value->value.integer.value[0]);
619 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
620 struct snd_ctl_elem_info *info)
622 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
623 info->count = 2;
624 info->value.integer.min = 0x79 - 60;
625 info->value.integer.max = 0x7f;
626 return 0;
629 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
630 struct snd_ctl_elem_value *value)
632 struct oxygen *chip = ctl->private_data;
633 struct xonar_wm87x6 *data = chip->model_data;
635 mutex_lock(&chip->mutex);
636 value->value.integer.value[0] =
637 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
638 value->value.integer.value[1] =
639 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
640 mutex_unlock(&chip->mutex);
641 return 0;
644 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
645 struct snd_ctl_elem_value *value)
647 struct oxygen *chip = ctl->private_data;
648 struct xonar_wm87x6 *data = chip->model_data;
649 u8 to_update;
651 mutex_lock(&chip->mutex);
652 to_update = (value->value.integer.value[0] !=
653 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
654 << 0;
655 to_update |= (value->value.integer.value[1] !=
656 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
657 << 1;
658 if (value->value.integer.value[0] == value->value.integer.value[1]) {
659 if (to_update) {
660 wm8776_write(chip, WM8776_HPMASTER,
661 value->value.integer.value[0] |
662 WM8776_HPZCEN | WM8776_UPDATE);
663 data->wm8776_regs[WM8776_HPLVOL] =
664 value->value.integer.value[0] | WM8776_HPZCEN;
665 data->wm8776_regs[WM8776_HPRVOL] =
666 value->value.integer.value[0] | WM8776_HPZCEN;
668 } else {
669 if (to_update & 1)
670 wm8776_write(chip, WM8776_HPLVOL,
671 value->value.integer.value[0] |
672 WM8776_HPZCEN |
673 ((to_update & 2) ? 0 : WM8776_UPDATE));
674 if (to_update & 2)
675 wm8776_write(chip, WM8776_HPRVOL,
676 value->value.integer.value[1] |
677 WM8776_HPZCEN | WM8776_UPDATE);
679 mutex_unlock(&chip->mutex);
680 return to_update != 0;
683 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
684 struct snd_ctl_elem_value *value)
686 struct oxygen *chip = ctl->private_data;
687 struct xonar_wm87x6 *data = chip->model_data;
688 unsigned int mux_bit = ctl->private_value;
690 value->value.integer.value[0] =
691 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
692 return 0;
695 static int wm8776_input_mux_put(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;
700 struct snd_kcontrol *other_ctl;
701 unsigned int mux_bit = ctl->private_value;
702 u16 reg;
703 int changed;
705 mutex_lock(&chip->mutex);
706 reg = data->wm8776_regs[WM8776_ADCMUX];
707 if (value->value.integer.value[0]) {
708 reg |= mux_bit;
709 /* line-in and mic-in are exclusive */
710 mux_bit ^= 3;
711 if (reg & mux_bit) {
712 reg &= ~mux_bit;
713 if (mux_bit == 1)
714 other_ctl = data->line_adcmux_control;
715 else
716 other_ctl = data->mic_adcmux_control;
717 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
718 &other_ctl->id);
720 } else
721 reg &= ~mux_bit;
722 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
723 if (changed) {
724 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
725 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
726 GPIO_DS_INPUT_ROUTE);
727 wm8776_write(chip, WM8776_ADCMUX, reg);
729 mutex_unlock(&chip->mutex);
730 return changed;
733 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
734 struct snd_ctl_elem_info *info)
736 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
737 info->count = 2;
738 info->value.integer.min = 0xa5;
739 info->value.integer.max = 0xff;
740 return 0;
743 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
744 struct snd_ctl_elem_value *value)
746 struct oxygen *chip = ctl->private_data;
747 struct xonar_wm87x6 *data = chip->model_data;
749 mutex_lock(&chip->mutex);
750 value->value.integer.value[0] =
751 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
752 value->value.integer.value[1] =
753 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
754 mutex_unlock(&chip->mutex);
755 return 0;
758 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
759 struct snd_ctl_elem_value *value)
761 struct oxygen *chip = ctl->private_data;
762 struct xonar_wm87x6 *data = chip->model_data;
763 int changed = 0;
765 mutex_lock(&chip->mutex);
766 changed = (value->value.integer.value[0] !=
767 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
768 (value->value.integer.value[1] !=
769 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
770 wm8776_write_cached(chip, WM8776_ADCLVOL,
771 value->value.integer.value[0] | WM8776_ZCA);
772 wm8776_write_cached(chip, WM8776_ADCRVOL,
773 value->value.integer.value[1] | WM8776_ZCA);
774 mutex_unlock(&chip->mutex);
775 return changed;
778 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
779 struct snd_ctl_elem_info *info)
781 static const char *const names[3] = {
782 "None", "Peak Limiter", "Automatic Level Control"
784 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
785 info->count = 1;
786 info->value.enumerated.items = 3;
787 if (info->value.enumerated.item >= 3)
788 info->value.enumerated.item = 2;
789 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
790 return 0;
793 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
794 struct snd_ctl_elem_value *value)
796 struct oxygen *chip = ctl->private_data;
797 struct xonar_wm87x6 *data = chip->model_data;
799 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
800 value->value.enumerated.item[0] = 0;
801 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
802 WM8776_LCSEL_LIMITER)
803 value->value.enumerated.item[0] = 1;
804 else
805 value->value.enumerated.item[0] = 2;
806 return 0;
809 static void activate_control(struct oxygen *chip,
810 struct snd_kcontrol *ctl, unsigned int mode)
812 unsigned int access;
814 if (ctl->private_value & mode)
815 access = 0;
816 else
817 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
818 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
819 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
820 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
824 static int wm8776_level_control_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;
829 unsigned int mode = 0, i;
830 u16 ctrl1, ctrl2;
831 int changed;
833 if (value->value.enumerated.item[0] >= 3)
834 return -EINVAL;
835 mutex_lock(&chip->mutex);
836 changed = value->value.enumerated.item[0] != ctl->private_value;
837 if (changed) {
838 ctl->private_value = value->value.enumerated.item[0];
839 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
840 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
841 switch (value->value.enumerated.item[0]) {
842 default:
843 wm8776_write_cached(chip, WM8776_ALCCTRL2,
844 ctrl2 & ~WM8776_LCEN);
845 break;
846 case 1:
847 wm8776_write_cached(chip, WM8776_ALCCTRL1,
848 (ctrl1 & ~WM8776_LCSEL_MASK) |
849 WM8776_LCSEL_LIMITER);
850 wm8776_write_cached(chip, WM8776_ALCCTRL2,
851 ctrl2 | WM8776_LCEN);
852 mode = LC_CONTROL_LIMITER;
853 break;
854 case 2:
855 wm8776_write_cached(chip, WM8776_ALCCTRL1,
856 (ctrl1 & ~WM8776_LCSEL_MASK) |
857 WM8776_LCSEL_ALC_STEREO);
858 wm8776_write_cached(chip, WM8776_ALCCTRL2,
859 ctrl2 | WM8776_LCEN);
860 mode = LC_CONTROL_ALC;
861 break;
863 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
864 activate_control(chip, data->lc_controls[i], mode);
866 mutex_unlock(&chip->mutex);
867 return changed;
870 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
872 static const char *const names[2] = {
873 "None", "High-pass Filter"
876 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
877 info->count = 1;
878 info->value.enumerated.items = 2;
879 if (info->value.enumerated.item >= 2)
880 info->value.enumerated.item = 1;
881 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
882 return 0;
885 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
887 struct oxygen *chip = ctl->private_data;
888 struct xonar_wm87x6 *data = chip->model_data;
890 value->value.enumerated.item[0] =
891 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
892 return 0;
895 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
897 struct oxygen *chip = ctl->private_data;
898 struct xonar_wm87x6 *data = chip->model_data;
899 unsigned int reg;
900 int changed;
902 mutex_lock(&chip->mutex);
903 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
904 if (!value->value.enumerated.item[0])
905 reg |= WM8776_ADCHPD;
906 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
907 if (changed)
908 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
909 mutex_unlock(&chip->mutex);
910 return changed;
913 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
914 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
915 .name = xname, \
916 .info = snd_ctl_boolean_mono_info, \
917 .get = wm8776_bit_switch_get, \
918 .put = wm8776_bit_switch_put, \
919 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
921 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
922 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
923 .name = xname, \
924 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
925 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
926 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
927 _WM8776_FIELD_CTL(xname " Capture Enum", \
928 reg, shift, init, min, max, mask, flags), \
929 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
930 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
931 .info = wm8776_field_enum_info, \
932 .get = wm8776_field_enum_get, \
933 .put = wm8776_field_enum_put, \
935 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
936 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
937 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
938 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
939 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
940 .info = wm8776_field_volume_info, \
941 .get = wm8776_field_volume_get, \
942 .put = wm8776_field_volume_put, \
943 .tlv = { .p = tlv_p }, \
946 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
947 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
948 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
949 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
950 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
951 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
952 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
953 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
955 static const struct snd_kcontrol_new ds_controls[] = {
957 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
958 .name = "Headphone Playback Volume",
959 .info = wm8776_hp_vol_info,
960 .get = wm8776_hp_vol_get,
961 .put = wm8776_hp_vol_put,
962 .tlv = { .p = wm8776_hp_db_scale },
964 WM8776_BIT_SWITCH("Headphone Playback Switch",
965 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
967 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
968 .name = "Input Capture Volume",
969 .info = wm8776_input_vol_info,
970 .get = wm8776_input_vol_get,
971 .put = wm8776_input_vol_put,
972 .tlv = { .p = wm8776_adc_db_scale },
975 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
976 .name = "Line Capture Switch",
977 .info = snd_ctl_boolean_mono_info,
978 .get = wm8776_input_mux_get,
979 .put = wm8776_input_mux_put,
980 .private_value = 1 << 0,
983 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
984 .name = "Mic Capture Switch",
985 .info = snd_ctl_boolean_mono_info,
986 .get = wm8776_input_mux_get,
987 .put = wm8776_input_mux_put,
988 .private_value = 1 << 1,
990 WM8776_BIT_SWITCH("Front Mic Capture Switch",
991 WM8776_ADCMUX, 1 << 2, 0, 0),
992 WM8776_BIT_SWITCH("Aux Capture Switch",
993 WM8776_ADCMUX, 1 << 3, 0, 0),
995 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
996 .name = "ADC Filter Capture Enum",
997 .info = hpf_info,
998 .get = hpf_get,
999 .put = hpf_put,
1002 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1003 .name = "Level Control Capture Enum",
1004 .info = wm8776_level_control_info,
1005 .get = wm8776_level_control_get,
1006 .put = wm8776_level_control_put,
1007 .private_value = 0,
1010 static const struct snd_kcontrol_new lc_controls[] = {
1011 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
1012 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1013 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
1014 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
1015 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1016 LC_CONTROL_LIMITER),
1017 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
1018 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1019 LC_CONTROL_LIMITER),
1020 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
1021 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
1022 LC_CONTROL_LIMITER),
1023 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
1024 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
1025 LC_CONTROL_LIMITER,
1026 wm8776_maxatten_lim_db_scale),
1027 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
1028 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1029 LC_CONTROL_ALC, wm8776_lct_db_scale),
1030 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
1031 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1032 LC_CONTROL_ALC),
1033 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1034 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1035 LC_CONTROL_ALC),
1036 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
1037 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
1038 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
1039 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1040 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1041 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1042 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1043 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1044 LC_CONTROL_ALC),
1045 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1046 WM8776_NOISEGATE, WM8776_NGAT, 0,
1047 LC_CONTROL_ALC),
1048 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1049 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1050 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1053 static int xonar_ds_mixer_init(struct oxygen *chip)
1055 struct xonar_wm87x6 *data = chip->model_data;
1056 unsigned int i;
1057 struct snd_kcontrol *ctl;
1058 int err;
1060 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1061 ctl = snd_ctl_new1(&ds_controls[i], chip);
1062 if (!ctl)
1063 return -ENOMEM;
1064 err = snd_ctl_add(chip->card, ctl);
1065 if (err < 0)
1066 return err;
1067 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1068 data->line_adcmux_control = ctl;
1069 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1070 data->mic_adcmux_control = ctl;
1072 if (!data->line_adcmux_control || !data->mic_adcmux_control)
1073 return -ENXIO;
1074 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1075 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1076 ctl = snd_ctl_new1(&lc_controls[i], chip);
1077 if (!ctl)
1078 return -ENOMEM;
1079 err = snd_ctl_add(chip->card, ctl);
1080 if (err < 0)
1081 return err;
1082 data->lc_controls[i] = ctl;
1084 return 0;
1087 static void dump_wm8776_registers(struct oxygen *chip,
1088 struct snd_info_buffer *buffer)
1090 struct xonar_wm87x6 *data = chip->model_data;
1091 unsigned int i;
1093 snd_iprintf(buffer, "\nWM8776:\n00:");
1094 for (i = 0; i < 0x10; ++i)
1095 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1096 snd_iprintf(buffer, "\n10:");
1097 for (i = 0x10; i < 0x17; ++i)
1098 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1099 snd_iprintf(buffer, "\n");
1102 static void dump_wm87x6_registers(struct oxygen *chip,
1103 struct snd_info_buffer *buffer)
1105 struct xonar_wm87x6 *data = chip->model_data;
1106 unsigned int i;
1108 dump_wm8776_registers(chip, buffer);
1109 snd_iprintf(buffer, "\nWM8766:\n00:");
1110 for (i = 0; i < 0x10; ++i)
1111 snd_iprintf(buffer, " %03x", data->wm8766_regs[i]);
1112 snd_iprintf(buffer, "\n");
1115 static const struct oxygen_model model_xonar_ds = {
1116 .shortname = "Xonar DS",
1117 .longname = "Asus Virtuoso 66",
1118 .chip = "AV200",
1119 .init = xonar_ds_init,
1120 .mixer_init = xonar_ds_mixer_init,
1121 .cleanup = xonar_ds_cleanup,
1122 .suspend = xonar_ds_suspend,
1123 .resume = xonar_ds_resume,
1124 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1125 .set_dac_params = set_wm87x6_dac_params,
1126 .set_adc_params = set_wm8776_adc_params,
1127 .update_dac_volume = update_wm87x6_volume,
1128 .update_dac_mute = update_wm87x6_mute,
1129 .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1130 .gpio_changed = xonar_ds_gpio_changed,
1131 .dump_registers = dump_wm87x6_registers,
1132 .dac_tlv = wm87x6_dac_db_scale,
1133 .model_data_size = sizeof(struct xonar_wm87x6),
1134 .device_config = PLAYBACK_0_TO_I2S |
1135 PLAYBACK_1_TO_SPDIF |
1136 CAPTURE_0_FROM_I2S_1,
1137 .dac_channels_pcm = 8,
1138 .dac_channels_mixer = 8,
1139 .dac_volume_min = 255 - 2*60,
1140 .dac_volume_max = 255,
1141 .function_flags = OXYGEN_FUNCTION_SPI,
1142 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1143 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1144 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1145 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1148 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1149 const struct pci_device_id *id)
1151 switch (id->subdevice) {
1152 case 0x838e:
1153 chip->model = model_xonar_ds;
1154 break;
1155 default:
1156 return -EINVAL;
1158 return 0;