]> git.karo-electronics.de Git - mv-sheeva.git/blob - sound/pci/oxygen/xonar_wm87x6.c
ALSA: virtuoso: automatically handle Xonar DS headphone routing
[mv-sheeva.git] / sound / pci / oxygen / xonar_wm87x6.c
1 /*
2  * card driver for models with WM8776/WM8766 DACs (Xonar DS)
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  *
6  *
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.
9  *
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.
14  *
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/>.
17  */
18
19 /*
20  * Xonar DS
21  * --------
22  *
23  * CMI8788:
24  *
25  * SPI 0 -> WM8766 (surround, center/LFE, back)
26  * SPI 1 -> WM8776 (front, input)
27  *
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
32  *
33  * WM8766:
34  *
35  * input 1 <- line
36  * input 2 <- mic
37  * input 3 <- front mic
38  * input 4 <- aux
39  */
40
41 #include <linux/pci.h>
42 #include <linux/delay.h>
43 #include <sound/control.h>
44 #include <sound/core.h>
45 #include <sound/jack.h>
46 #include <sound/pcm.h>
47 #include <sound/pcm_params.h>
48 #include <sound/tlv.h>
49 #include "xonar.h"
50 #include "wm8776.h"
51 #include "wm8766.h"
52
53 #define GPIO_DS_HP_DETECT       0x0010
54 #define GPIO_DS_INPUT_ROUTE     0x0040
55 #define GPIO_DS_OUTPUT_FRONTLR  0x0080
56 #define GPIO_DS_OUTPUT_ENABLE   0x0100
57
58 #define LC_CONTROL_LIMITER      0x40000000
59 #define LC_CONTROL_ALC          0x20000000
60
61 struct xonar_wm87x6 {
62         struct xonar_generic generic;
63         u16 wm8776_regs[0x17];
64         u16 wm8766_regs[0x10];
65         struct snd_kcontrol *line_adcmux_control;
66         struct snd_kcontrol *mic_adcmux_control;
67         struct snd_kcontrol *lc_controls[13];
68         struct snd_jack *hp_jack;
69 };
70
71 static void wm8776_write(struct oxygen *chip,
72                          unsigned int reg, unsigned int value)
73 {
74         struct xonar_wm87x6 *data = chip->model_data;
75
76         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
77                          OXYGEN_SPI_DATA_LENGTH_2 |
78                          OXYGEN_SPI_CLOCK_160 |
79                          (1 << OXYGEN_SPI_CODEC_SHIFT) |
80                          OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
81                          (reg << 9) | value);
82         if (reg < ARRAY_SIZE(data->wm8776_regs)) {
83                 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
84                         value &= ~WM8776_UPDATE;
85                 data->wm8776_regs[reg] = value;
86         }
87 }
88
89 static void wm8776_write_cached(struct oxygen *chip,
90                                 unsigned int reg, unsigned int value)
91 {
92         struct xonar_wm87x6 *data = chip->model_data;
93
94         if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
95             value != data->wm8776_regs[reg])
96                 wm8776_write(chip, reg, value);
97 }
98
99 static void wm8766_write(struct oxygen *chip,
100                          unsigned int reg, unsigned int value)
101 {
102         struct xonar_wm87x6 *data = chip->model_data;
103
104         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
105                          OXYGEN_SPI_DATA_LENGTH_2 |
106                          OXYGEN_SPI_CLOCK_160 |
107                          (0 << OXYGEN_SPI_CODEC_SHIFT) |
108                          OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
109                          (reg << 9) | value);
110         if (reg < ARRAY_SIZE(data->wm8766_regs)) {
111                 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112                     (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113                         value &= ~WM8766_UPDATE;
114                 data->wm8766_regs[reg] = value;
115         }
116 }
117
118 static void wm8766_write_cached(struct oxygen *chip,
119                                 unsigned int reg, unsigned int value)
120 {
121         struct xonar_wm87x6 *data = chip->model_data;
122
123         if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
124             value != data->wm8766_regs[reg])
125                 wm8766_write(chip, reg, value);
126 }
127
128 static void wm8776_registers_init(struct oxygen *chip)
129 {
130         struct xonar_wm87x6 *data = chip->model_data;
131
132         wm8776_write(chip, WM8776_RESET, 0);
133         wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
134                      WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
135         wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
136         wm8776_write(chip, WM8776_DACIFCTRL,
137                      WM8776_DACFMT_LJUST | WM8776_DACWL_24);
138         wm8776_write(chip, WM8776_ADCIFCTRL,
139                      data->wm8776_regs[WM8776_ADCIFCTRL]);
140         wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
141         wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
142         wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
143         wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
144                      WM8776_UPDATE);
145         wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
146         wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
147         wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
148         wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
149         wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
150 }
151
152 static void wm8766_registers_init(struct oxygen *chip)
153 {
154         struct xonar_wm87x6 *data = chip->model_data;
155
156         wm8766_write(chip, WM8766_RESET, 0);
157         wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
158         wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
159         wm8766_write(chip, WM8766_DAC_CTRL2,
160                      WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
161         wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
162         wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
163         wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
164         wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
165         wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
166         wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
167 }
168
169 static void wm8776_init(struct oxygen *chip)
170 {
171         struct xonar_wm87x6 *data = chip->model_data;
172
173         data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
174         data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
175         data->wm8776_regs[WM8776_ADCIFCTRL] =
176                 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
177         data->wm8776_regs[WM8776_MSTRCTRL] =
178                 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
179         data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
180         data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
181         data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
182         data->wm8776_regs[WM8776_ADCMUX] = 0x001;
183         wm8776_registers_init(chip);
184 }
185
186 static void wm8766_init(struct oxygen *chip)
187 {
188         struct xonar_wm87x6 *data = chip->model_data;
189
190         data->wm8766_regs[WM8766_DAC_CTRL] =
191                 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
192         wm8766_registers_init(chip);
193 }
194
195 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
196 {
197         struct xonar_wm87x6 *data = chip->model_data;
198         bool hp_plugged;
199         unsigned int reg;
200
201         mutex_lock(&chip->mutex);
202
203         hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
204                        GPIO_DS_HP_DETECT);
205
206         oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
207                               hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
208                               GPIO_DS_OUTPUT_FRONTLR);
209
210         reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
211         if (hp_plugged)
212                 reg |= WM8766_MUTEALL;
213         wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
214
215         snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
216
217         mutex_unlock(&chip->mutex);
218 }
219
220 static void xonar_ds_init(struct oxygen *chip)
221 {
222         struct xonar_wm87x6 *data = chip->model_data;
223
224         data->generic.anti_pop_delay = 300;
225         data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
226
227         wm8776_init(chip);
228         wm8766_init(chip);
229
230         oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
231                           GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
232         oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
233                             GPIO_DS_HP_DETECT);
234         oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
235         oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
236         chip->interrupt_mask |= OXYGEN_INT_GPIO;
237
238         xonar_enable_output(chip);
239
240         snd_jack_new(chip->card, "Headphone",
241                      SND_JACK_HEADPHONE, &data->hp_jack);
242         xonar_ds_handle_hp_jack(chip);
243
244         snd_component_add(chip->card, "WM8776");
245         snd_component_add(chip->card, "WM8766");
246 }
247
248 static void xonar_ds_cleanup(struct oxygen *chip)
249 {
250         xonar_disable_output(chip);
251         wm8776_write(chip, WM8776_RESET, 0);
252 }
253
254 static void xonar_ds_suspend(struct oxygen *chip)
255 {
256         xonar_ds_cleanup(chip);
257 }
258
259 static void xonar_ds_resume(struct oxygen *chip)
260 {
261         wm8776_registers_init(chip);
262         wm8766_registers_init(chip);
263         xonar_enable_output(chip);
264         xonar_ds_handle_hp_jack(chip);
265 }
266
267 static void wm8776_adc_hardware_filter(unsigned int channel,
268                                        struct snd_pcm_hardware *hardware)
269 {
270         if (channel == PCM_A) {
271                 hardware->rates = SNDRV_PCM_RATE_32000 |
272                                   SNDRV_PCM_RATE_44100 |
273                                   SNDRV_PCM_RATE_48000 |
274                                   SNDRV_PCM_RATE_64000 |
275                                   SNDRV_PCM_RATE_88200 |
276                                   SNDRV_PCM_RATE_96000;
277                 hardware->rate_max = 96000;
278         }
279 }
280
281 static void set_wm87x6_dac_params(struct oxygen *chip,
282                                   struct snd_pcm_hw_params *params)
283 {
284 }
285
286 static void set_wm8776_adc_params(struct oxygen *chip,
287                                   struct snd_pcm_hw_params *params)
288 {
289         u16 reg;
290
291         reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
292         if (params_rate(params) > 48000)
293                 reg |= WM8776_ADCOSR;
294         wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
295 }
296
297 static void update_wm8776_volume(struct oxygen *chip)
298 {
299         struct xonar_wm87x6 *data = chip->model_data;
300         u8 to_change;
301
302         if (chip->dac_volume[0] == chip->dac_volume[1]) {
303                 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
304                     chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
305                         wm8776_write(chip, WM8776_DACMASTER,
306                                      chip->dac_volume[0] | WM8776_UPDATE);
307                         data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
308                         data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
309                 }
310         } else {
311                 to_change = (chip->dac_volume[0] !=
312                              data->wm8776_regs[WM8776_DACLVOL]) << 0;
313                 to_change |= (chip->dac_volume[1] !=
314                               data->wm8776_regs[WM8776_DACLVOL]) << 1;
315                 if (to_change & 1)
316                         wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
317                                      ((to_change & 2) ? 0 : WM8776_UPDATE));
318                 if (to_change & 2)
319                         wm8776_write(chip, WM8776_DACRVOL,
320                                      chip->dac_volume[1] | WM8776_UPDATE);
321         }
322 }
323
324 static void update_wm87x6_volume(struct oxygen *chip)
325 {
326         static const u8 wm8766_regs[6] = {
327                 WM8766_LDA1, WM8766_RDA1,
328                 WM8766_LDA2, WM8766_RDA2,
329                 WM8766_LDA3, WM8766_RDA3,
330         };
331         struct xonar_wm87x6 *data = chip->model_data;
332         unsigned int i;
333         u8 to_change;
334
335         update_wm8776_volume(chip);
336         if (chip->dac_volume[2] == chip->dac_volume[3] &&
337             chip->dac_volume[2] == chip->dac_volume[4] &&
338             chip->dac_volume[2] == chip->dac_volume[5] &&
339             chip->dac_volume[2] == chip->dac_volume[6] &&
340             chip->dac_volume[2] == chip->dac_volume[7]) {
341                 to_change = 0;
342                 for (i = 0; i < 6; ++i)
343                         if (chip->dac_volume[2] !=
344                             data->wm8766_regs[wm8766_regs[i]])
345                                 to_change = 1;
346                 if (to_change) {
347                         wm8766_write(chip, WM8766_MASTDA,
348                                      chip->dac_volume[2] | WM8766_UPDATE);
349                         for (i = 0; i < 6; ++i)
350                                 data->wm8766_regs[wm8766_regs[i]] =
351                                         chip->dac_volume[2];
352                 }
353         } else {
354                 to_change = 0;
355                 for (i = 0; i < 6; ++i)
356                         to_change |= (chip->dac_volume[2 + i] !=
357                                       data->wm8766_regs[wm8766_regs[i]]) << i;
358                 for (i = 0; i < 6; ++i)
359                         if (to_change & (1 << i))
360                                 wm8766_write(chip, wm8766_regs[i],
361                                              chip->dac_volume[2 + i] |
362                                              ((to_change & (0x3e << i))
363                                               ? 0 : WM8766_UPDATE));
364         }
365 }
366
367 static void update_wm8776_mute(struct oxygen *chip)
368 {
369         wm8776_write_cached(chip, WM8776_DACMUTE,
370                             chip->dac_mute ? WM8776_DMUTE : 0);
371 }
372
373 static void update_wm87x6_mute(struct oxygen *chip)
374 {
375         update_wm8776_mute(chip);
376         wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
377                             (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
378 }
379
380 static void xonar_ds_gpio_changed(struct oxygen *chip)
381 {
382         xonar_ds_handle_hp_jack(chip);
383 }
384
385 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
386                                  struct snd_ctl_elem_value *value)
387 {
388         struct oxygen *chip = ctl->private_data;
389         struct xonar_wm87x6 *data = chip->model_data;
390         u16 bit = ctl->private_value & 0xffff;
391         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
392         bool invert = (ctl->private_value >> 24) & 1;
393
394         value->value.integer.value[0] =
395                 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
396         return 0;
397 }
398
399 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
400                                  struct snd_ctl_elem_value *value)
401 {
402         struct oxygen *chip = ctl->private_data;
403         struct xonar_wm87x6 *data = chip->model_data;
404         u16 bit = ctl->private_value & 0xffff;
405         u16 reg_value;
406         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
407         bool invert = (ctl->private_value >> 24) & 1;
408         int changed;
409
410         mutex_lock(&chip->mutex);
411         reg_value = data->wm8776_regs[reg_index] & ~bit;
412         if (value->value.integer.value[0] ^ invert)
413                 reg_value |= bit;
414         changed = reg_value != data->wm8776_regs[reg_index];
415         if (changed)
416                 wm8776_write(chip, reg_index, reg_value);
417         mutex_unlock(&chip->mutex);
418         return changed;
419 }
420
421 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
422                                   struct snd_ctl_elem_info *info)
423 {
424         static const char *const hld[16] = {
425                 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
426                 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
427                 "341 ms", "683 ms", "1.37 s", "2.73 s",
428                 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
429         };
430         static const char *const atk_lim[11] = {
431                 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
432                 "4 ms", "8 ms", "16 ms", "32 ms",
433                 "64 ms", "128 ms", "256 ms",
434         };
435         static const char *const atk_alc[11] = {
436                 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
437                 "134 ms", "269 ms", "538 ms", "1.08 s",
438                 "2.15 s", "4.3 s", "8.6 s",
439         };
440         static const char *const dcy_lim[11] = {
441                 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
442                 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
443                 "307 ms", "614 ms", "1.23 s",
444         };
445         static const char *const dcy_alc[11] = {
446                 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
447                 "536 ms", "1.07 s", "2.14 s", "4.29 s",
448                 "8.58 s", "17.2 s", "34.3 s",
449         };
450         static const char *const tranwin[8] = {
451                 "0 us", "62.5 us", "125 us", "250 us",
452                 "500 us", "1 ms", "2 ms", "4 ms",
453         };
454         u8 max;
455         const char *const *names;
456
457         max = (ctl->private_value >> 12) & 0xf;
458         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
459         info->count = 1;
460         info->value.enumerated.items = max + 1;
461         if (info->value.enumerated.item > max)
462                 info->value.enumerated.item = max;
463         switch ((ctl->private_value >> 24) & 0x1f) {
464         case WM8776_ALCCTRL2:
465                 names = hld;
466                 break;
467         case WM8776_ALCCTRL3:
468                 if (((ctl->private_value >> 20) & 0xf) == 0) {
469                         if (ctl->private_value & LC_CONTROL_LIMITER)
470                                 names = atk_lim;
471                         else
472                                 names = atk_alc;
473                 } else {
474                         if (ctl->private_value & LC_CONTROL_LIMITER)
475                                 names = dcy_lim;
476                         else
477                                 names = dcy_alc;
478                 }
479                 break;
480         case WM8776_LIMITER:
481                 names = tranwin;
482                 break;
483         default:
484                 return -ENXIO;
485         }
486         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
487         return 0;
488 }
489
490 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
491                                     struct snd_ctl_elem_info *info)
492 {
493         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
494         info->count = 1;
495         info->value.integer.min = (ctl->private_value >> 8) & 0xf;
496         info->value.integer.max = (ctl->private_value >> 12) & 0xf;
497         return 0;
498 }
499
500 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
501 {
502         struct oxygen *chip = ctl->private_data;
503         struct xonar_wm87x6 *data = chip->model_data;
504         unsigned int value, reg_index, mode;
505         u8 min, max, shift;
506         u16 mask, reg_value;
507         bool invert;
508
509         if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
510             WM8776_LCSEL_LIMITER)
511                 mode = LC_CONTROL_LIMITER;
512         else
513                 mode = LC_CONTROL_ALC;
514         if (!(ctl->private_value & mode))
515                 return;
516
517         value = ctl->private_value & 0xf;
518         min = (ctl->private_value >> 8) & 0xf;
519         max = (ctl->private_value >> 12) & 0xf;
520         mask = (ctl->private_value >> 16) & 0xf;
521         shift = (ctl->private_value >> 20) & 0xf;
522         reg_index = (ctl->private_value >> 24) & 0x1f;
523         invert = (ctl->private_value >> 29) & 0x1;
524
525         if (invert)
526                 value = max - (value - min);
527         reg_value = data->wm8776_regs[reg_index];
528         reg_value &= ~(mask << shift);
529         reg_value |= value << shift;
530         wm8776_write_cached(chip, reg_index, reg_value);
531 }
532
533 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
534 {
535         struct oxygen *chip = ctl->private_data;
536         u8 min, max;
537         int changed;
538
539         min = (ctl->private_value >> 8) & 0xf;
540         max = (ctl->private_value >> 12) & 0xf;
541         if (value < min || value > max)
542                 return -EINVAL;
543         mutex_lock(&chip->mutex);
544         changed = value != (ctl->private_value & 0xf);
545         if (changed) {
546                 ctl->private_value = (ctl->private_value & ~0xf) | value;
547                 wm8776_field_set_from_ctl(ctl);
548         }
549         mutex_unlock(&chip->mutex);
550         return changed;
551 }
552
553 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
554                                  struct snd_ctl_elem_value *value)
555 {
556         value->value.enumerated.item[0] = ctl->private_value & 0xf;
557         return 0;
558 }
559
560 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
561                                    struct snd_ctl_elem_value *value)
562 {
563         value->value.integer.value[0] = ctl->private_value & 0xf;
564         return 0;
565 }
566
567 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
568                                  struct snd_ctl_elem_value *value)
569 {
570         return wm8776_field_set(ctl, value->value.enumerated.item[0]);
571 }
572
573 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
574                                    struct snd_ctl_elem_value *value)
575 {
576         return wm8776_field_set(ctl, value->value.integer.value[0]);
577 }
578
579 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
580                               struct snd_ctl_elem_info *info)
581 {
582         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
583         info->count = 2;
584         info->value.integer.min = 0x79 - 60;
585         info->value.integer.max = 0x7f;
586         return 0;
587 }
588
589 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
590                              struct snd_ctl_elem_value *value)
591 {
592         struct oxygen *chip = ctl->private_data;
593         struct xonar_wm87x6 *data = chip->model_data;
594
595         mutex_lock(&chip->mutex);
596         value->value.integer.value[0] =
597                 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
598         value->value.integer.value[1] =
599                 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
600         mutex_unlock(&chip->mutex);
601         return 0;
602 }
603
604 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
605                              struct snd_ctl_elem_value *value)
606 {
607         struct oxygen *chip = ctl->private_data;
608         struct xonar_wm87x6 *data = chip->model_data;
609         u8 to_update;
610
611         mutex_lock(&chip->mutex);
612         to_update = (value->value.integer.value[0] !=
613                      (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
614                 << 0;
615         to_update |= (value->value.integer.value[1] !=
616                       (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
617                 << 1;
618         if (value->value.integer.value[0] == value->value.integer.value[1]) {
619                 if (to_update) {
620                         wm8776_write(chip, WM8776_HPMASTER,
621                                      value->value.integer.value[0] |
622                                      WM8776_HPZCEN | WM8776_UPDATE);
623                         data->wm8776_regs[WM8776_HPLVOL] =
624                                 value->value.integer.value[0] | WM8776_HPZCEN;
625                         data->wm8776_regs[WM8776_HPRVOL] =
626                                 value->value.integer.value[0] | WM8776_HPZCEN;
627                 }
628         } else {
629                 if (to_update & 1)
630                         wm8776_write(chip, WM8776_HPLVOL,
631                                      value->value.integer.value[0] |
632                                      WM8776_HPZCEN |
633                                      ((to_update & 2) ? 0 : WM8776_UPDATE));
634                 if (to_update & 2)
635                         wm8776_write(chip, WM8776_HPRVOL,
636                                      value->value.integer.value[1] |
637                                      WM8776_HPZCEN | WM8776_UPDATE);
638         }
639         mutex_unlock(&chip->mutex);
640         return to_update != 0;
641 }
642
643 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
644                                 struct snd_ctl_elem_value *value)
645 {
646         struct oxygen *chip = ctl->private_data;
647         struct xonar_wm87x6 *data = chip->model_data;
648         unsigned int mux_bit = ctl->private_value;
649
650         value->value.integer.value[0] =
651                 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
652         return 0;
653 }
654
655 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
656                                 struct snd_ctl_elem_value *value)
657 {
658         struct oxygen *chip = ctl->private_data;
659         struct xonar_wm87x6 *data = chip->model_data;
660         struct snd_kcontrol *other_ctl;
661         unsigned int mux_bit = ctl->private_value;
662         u16 reg;
663         int changed;
664
665         mutex_lock(&chip->mutex);
666         reg = data->wm8776_regs[WM8776_ADCMUX];
667         if (value->value.integer.value[0]) {
668                 reg |= mux_bit;
669                 /* line-in and mic-in are exclusive */
670                 mux_bit ^= 3;
671                 if (reg & mux_bit) {
672                         reg &= ~mux_bit;
673                         if (mux_bit == 1)
674                                 other_ctl = data->line_adcmux_control;
675                         else
676                                 other_ctl = data->mic_adcmux_control;
677                         snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
678                                        &other_ctl->id);
679                 }
680         } else
681                 reg &= ~mux_bit;
682         changed = reg != data->wm8776_regs[WM8776_ADCMUX];
683         if (changed) {
684                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
685                                       reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
686                                       GPIO_DS_INPUT_ROUTE);
687                 wm8776_write(chip, WM8776_ADCMUX, reg);
688         }
689         mutex_unlock(&chip->mutex);
690         return changed;
691 }
692
693 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
694                                  struct snd_ctl_elem_info *info)
695 {
696         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
697         info->count = 2;
698         info->value.integer.min = 0xa5;
699         info->value.integer.max = 0xff;
700         return 0;
701 }
702
703 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
704                                 struct snd_ctl_elem_value *value)
705 {
706         struct oxygen *chip = ctl->private_data;
707         struct xonar_wm87x6 *data = chip->model_data;
708
709         mutex_lock(&chip->mutex);
710         value->value.integer.value[0] =
711                 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
712         value->value.integer.value[1] =
713                 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
714         mutex_unlock(&chip->mutex);
715         return 0;
716 }
717
718 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
719                                 struct snd_ctl_elem_value *value)
720 {
721         struct oxygen *chip = ctl->private_data;
722         struct xonar_wm87x6 *data = chip->model_data;
723         int changed = 0;
724
725         mutex_lock(&chip->mutex);
726         changed = (value->value.integer.value[0] !=
727                    (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
728                   (value->value.integer.value[1] !=
729                    (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
730         wm8776_write_cached(chip, WM8776_ADCLVOL,
731                             value->value.integer.value[0] | WM8776_ZCA);
732         wm8776_write_cached(chip, WM8776_ADCRVOL,
733                             value->value.integer.value[1] | WM8776_ZCA);
734         mutex_unlock(&chip->mutex);
735         return changed;
736 }
737
738 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
739                                      struct snd_ctl_elem_info *info)
740 {
741         static const char *const names[3] = {
742                 "None", "Peak Limiter", "Automatic Level Control"
743         };
744         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
745         info->count = 1;
746         info->value.enumerated.items = 3;
747         if (info->value.enumerated.item >= 3)
748                 info->value.enumerated.item = 2;
749         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
750         return 0;
751 }
752
753 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
754                                     struct snd_ctl_elem_value *value)
755 {
756         struct oxygen *chip = ctl->private_data;
757         struct xonar_wm87x6 *data = chip->model_data;
758
759         if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
760                 value->value.enumerated.item[0] = 0;
761         else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
762                  WM8776_LCSEL_LIMITER)
763                 value->value.enumerated.item[0] = 1;
764         else
765                 value->value.enumerated.item[0] = 2;
766         return 0;
767 }
768
769 static void activate_control(struct oxygen *chip,
770                              struct snd_kcontrol *ctl, unsigned int mode)
771 {
772         unsigned int access;
773
774         if (ctl->private_value & mode)
775                 access = 0;
776         else
777                 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
778         if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
779                 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
780                 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
781         }
782 }
783
784 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
785                                     struct snd_ctl_elem_value *value)
786 {
787         struct oxygen *chip = ctl->private_data;
788         struct xonar_wm87x6 *data = chip->model_data;
789         unsigned int mode = 0, i;
790         u16 ctrl1, ctrl2;
791         int changed;
792
793         if (value->value.enumerated.item[0] >= 3)
794                 return -EINVAL;
795         mutex_lock(&chip->mutex);
796         changed = value->value.enumerated.item[0] != ctl->private_value;
797         if (changed) {
798                 ctl->private_value = value->value.enumerated.item[0];
799                 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
800                 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
801                 switch (value->value.enumerated.item[0]) {
802                 default:
803                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
804                                             ctrl2 & ~WM8776_LCEN);
805                         break;
806                 case 1:
807                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
808                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
809                                             WM8776_LCSEL_LIMITER);
810                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
811                                             ctrl2 | WM8776_LCEN);
812                         mode = LC_CONTROL_LIMITER;
813                         break;
814                 case 2:
815                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
816                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
817                                             WM8776_LCSEL_ALC_STEREO);
818                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
819                                             ctrl2 | WM8776_LCEN);
820                         mode = LC_CONTROL_ALC;
821                         break;
822                 }
823                 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
824                         activate_control(chip, data->lc_controls[i], mode);
825         }
826         mutex_unlock(&chip->mutex);
827         return changed;
828 }
829
830 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
831 {
832         static const char *const names[2] = {
833                 "None", "High-pass Filter"
834         };
835
836         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
837         info->count = 1;
838         info->value.enumerated.items = 2;
839         if (info->value.enumerated.item >= 2)
840                 info->value.enumerated.item = 1;
841         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
842         return 0;
843 }
844
845 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
846 {
847         struct oxygen *chip = ctl->private_data;
848         struct xonar_wm87x6 *data = chip->model_data;
849
850         value->value.enumerated.item[0] =
851                 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
852         return 0;
853 }
854
855 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
856 {
857         struct oxygen *chip = ctl->private_data;
858         struct xonar_wm87x6 *data = chip->model_data;
859         unsigned int reg;
860         int changed;
861
862         mutex_lock(&chip->mutex);
863         reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
864         if (!value->value.enumerated.item[0])
865                 reg |= WM8776_ADCHPD;
866         changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
867         if (changed)
868                 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
869         mutex_unlock(&chip->mutex);
870         return changed;
871 }
872
873 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
874         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
875         .name = xname, \
876         .info = snd_ctl_boolean_mono_info, \
877         .get = wm8776_bit_switch_get, \
878         .put = wm8776_bit_switch_put, \
879         .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
880 }
881 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
882         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
883         .name = xname, \
884         .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
885         ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
886 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
887         _WM8776_FIELD_CTL(xname " Capture Enum", \
888                           reg, shift, init, min, max, mask, flags), \
889         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
890                   SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
891         .info = wm8776_field_enum_info, \
892         .get = wm8776_field_enum_get, \
893         .put = wm8776_field_enum_put, \
894 }
895 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
896         _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
897         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
898                   SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
899                   SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
900         .info = wm8776_field_volume_info, \
901         .get = wm8776_field_volume_get, \
902         .put = wm8776_field_volume_put, \
903         .tlv = { .p = tlv_p }, \
904 }
905
906 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
907 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
908 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
909 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
910 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
911 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
912 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
913 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
914
915 static const struct snd_kcontrol_new ds_controls[] = {
916         {
917                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
918                 .name = "Headphone Playback Volume",
919                 .info = wm8776_hp_vol_info,
920                 .get = wm8776_hp_vol_get,
921                 .put = wm8776_hp_vol_put,
922                 .tlv = { .p = wm8776_hp_db_scale },
923         },
924         WM8776_BIT_SWITCH("Headphone Playback Switch",
925                           WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
926         {
927                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
928                 .name = "Input Capture Volume",
929                 .info = wm8776_input_vol_info,
930                 .get = wm8776_input_vol_get,
931                 .put = wm8776_input_vol_put,
932                 .tlv = { .p = wm8776_adc_db_scale },
933         },
934         {
935                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
936                 .name = "Line Capture Switch",
937                 .info = snd_ctl_boolean_mono_info,
938                 .get = wm8776_input_mux_get,
939                 .put = wm8776_input_mux_put,
940                 .private_value = 1 << 0,
941         },
942         {
943                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
944                 .name = "Mic Capture Switch",
945                 .info = snd_ctl_boolean_mono_info,
946                 .get = wm8776_input_mux_get,
947                 .put = wm8776_input_mux_put,
948                 .private_value = 1 << 1,
949         },
950         WM8776_BIT_SWITCH("Front Mic Capture Switch",
951                           WM8776_ADCMUX, 1 << 2, 0, 0),
952         WM8776_BIT_SWITCH("Aux Capture Switch",
953                           WM8776_ADCMUX, 1 << 3, 0, 0),
954         {
955                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
956                 .name = "ADC Filter Capture Enum",
957                 .info = hpf_info,
958                 .get = hpf_get,
959                 .put = hpf_put,
960         },
961         {
962                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
963                 .name = "Level Control Capture Enum",
964                 .info = wm8776_level_control_info,
965                 .get = wm8776_level_control_get,
966                 .put = wm8776_level_control_put,
967                 .private_value = 0,
968         },
969 };
970 static const struct snd_kcontrol_new lc_controls[] = {
971         WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
972                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
973                                 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
974         WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
975                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
976                               LC_CONTROL_LIMITER),
977         WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
978                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
979                               LC_CONTROL_LIMITER),
980         WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
981                               WM8776_LIMITER, 4, 2, 0, 7, 0x7,
982                               LC_CONTROL_LIMITER),
983         WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
984                                 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
985                                 LC_CONTROL_LIMITER,
986                                 wm8776_maxatten_lim_db_scale),
987         WM8776_FIELD_CTL_VOLUME("ALC Target Level",
988                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
989                                 LC_CONTROL_ALC, wm8776_lct_db_scale),
990         WM8776_FIELD_CTL_ENUM("ALC Attack Time",
991                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
992                               LC_CONTROL_ALC),
993         WM8776_FIELD_CTL_ENUM("ALC Decay Time",
994                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
995                               LC_CONTROL_ALC),
996         WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
997                                 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
998                                 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
999         WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1000                                 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1001                                 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1002         WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1003                               WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1004                               LC_CONTROL_ALC),
1005         WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1006                           WM8776_NOISEGATE, WM8776_NGAT, 0,
1007                           LC_CONTROL_ALC),
1008         WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1009                                 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1010                                 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1011 };
1012
1013 static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
1014 {
1015         if (!strncmp(template->name, "CD Capture ", 11))
1016                 return 1; /* no CD input */
1017         return 0;
1018 }
1019
1020 static int xonar_ds_mixer_init(struct oxygen *chip)
1021 {
1022         struct xonar_wm87x6 *data = chip->model_data;
1023         unsigned int i;
1024         struct snd_kcontrol *ctl;
1025         int err;
1026
1027         for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1028                 ctl = snd_ctl_new1(&ds_controls[i], chip);
1029                 if (!ctl)
1030                         return -ENOMEM;
1031                 err = snd_ctl_add(chip->card, ctl);
1032                 if (err < 0)
1033                         return err;
1034                 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1035                         data->line_adcmux_control = ctl;
1036                 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1037                         data->mic_adcmux_control = ctl;
1038         }
1039         if (!data->line_adcmux_control || !data->mic_adcmux_control)
1040                 return -ENXIO;
1041         BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1042         for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1043                 ctl = snd_ctl_new1(&lc_controls[i], chip);
1044                 if (!ctl)
1045                         return -ENOMEM;
1046                 err = snd_ctl_add(chip->card, ctl);
1047                 if (err < 0)
1048                         return err;
1049                 data->lc_controls[i] = ctl;
1050         }
1051         return 0;
1052 }
1053
1054 static const struct oxygen_model model_xonar_ds = {
1055         .shortname = "Xonar DS",
1056         .longname = "Asus Virtuoso 200",
1057         .chip = "AV200",
1058         .init = xonar_ds_init,
1059         .control_filter = xonar_ds_control_filter,
1060         .mixer_init = xonar_ds_mixer_init,
1061         .cleanup = xonar_ds_cleanup,
1062         .suspend = xonar_ds_suspend,
1063         .resume = xonar_ds_resume,
1064         .pcm_hardware_filter = wm8776_adc_hardware_filter,
1065         .get_i2s_mclk = oxygen_default_i2s_mclk,
1066         .set_dac_params = set_wm87x6_dac_params,
1067         .set_adc_params = set_wm8776_adc_params,
1068         .update_dac_volume = update_wm87x6_volume,
1069         .update_dac_mute = update_wm87x6_mute,
1070         .gpio_changed = xonar_ds_gpio_changed,
1071         .dac_tlv = wm87x6_dac_db_scale,
1072         .model_data_size = sizeof(struct xonar_wm87x6),
1073         .device_config = PLAYBACK_0_TO_I2S |
1074                          PLAYBACK_1_TO_SPDIF |
1075                          CAPTURE_0_FROM_I2S_1,
1076         .dac_channels = 8,
1077         .dac_volume_min = 255 - 2*60,
1078         .dac_volume_max = 255,
1079         .function_flags = OXYGEN_FUNCTION_SPI,
1080         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1081         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1082 };
1083
1084 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1085                                      const struct pci_device_id *id)
1086 {
1087         switch (id->subdevice) {
1088         case 0x838e:
1089                 chip->model = model_xonar_ds;
1090                 break;
1091         default:
1092                 return -EINVAL;
1093         }
1094         return 0;
1095 }