]> git.karo-electronics.de Git - mv-sheeva.git/blob - sound/pci/oxygen/xonar_wm87x6.c
Merge branch 'for-2.6.37' into for-2.6.38
[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 update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
381 {
382         struct xonar_wm87x6 *data = chip->model_data;
383         unsigned int reg;
384
385         /*
386          * The WM8766 can mix left and right channels, but this setting
387          * applies to all three stereo pairs.
388          */
389         reg = data->wm8766_regs[WM8766_DAC_CTRL] &
390                 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
391         if (mixed)
392                 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
393         else
394                 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
395         wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
396 }
397
398 static void xonar_ds_gpio_changed(struct oxygen *chip)
399 {
400         xonar_ds_handle_hp_jack(chip);
401 }
402
403 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
404                                  struct snd_ctl_elem_value *value)
405 {
406         struct oxygen *chip = ctl->private_data;
407         struct xonar_wm87x6 *data = chip->model_data;
408         u16 bit = ctl->private_value & 0xffff;
409         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
410         bool invert = (ctl->private_value >> 24) & 1;
411
412         value->value.integer.value[0] =
413                 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
414         return 0;
415 }
416
417 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
418                                  struct snd_ctl_elem_value *value)
419 {
420         struct oxygen *chip = ctl->private_data;
421         struct xonar_wm87x6 *data = chip->model_data;
422         u16 bit = ctl->private_value & 0xffff;
423         u16 reg_value;
424         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
425         bool invert = (ctl->private_value >> 24) & 1;
426         int changed;
427
428         mutex_lock(&chip->mutex);
429         reg_value = data->wm8776_regs[reg_index] & ~bit;
430         if (value->value.integer.value[0] ^ invert)
431                 reg_value |= bit;
432         changed = reg_value != data->wm8776_regs[reg_index];
433         if (changed)
434                 wm8776_write(chip, reg_index, reg_value);
435         mutex_unlock(&chip->mutex);
436         return changed;
437 }
438
439 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
440                                   struct snd_ctl_elem_info *info)
441 {
442         static const char *const hld[16] = {
443                 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
444                 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
445                 "341 ms", "683 ms", "1.37 s", "2.73 s",
446                 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
447         };
448         static const char *const atk_lim[11] = {
449                 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
450                 "4 ms", "8 ms", "16 ms", "32 ms",
451                 "64 ms", "128 ms", "256 ms",
452         };
453         static const char *const atk_alc[11] = {
454                 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
455                 "134 ms", "269 ms", "538 ms", "1.08 s",
456                 "2.15 s", "4.3 s", "8.6 s",
457         };
458         static const char *const dcy_lim[11] = {
459                 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
460                 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
461                 "307 ms", "614 ms", "1.23 s",
462         };
463         static const char *const dcy_alc[11] = {
464                 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
465                 "536 ms", "1.07 s", "2.14 s", "4.29 s",
466                 "8.58 s", "17.2 s", "34.3 s",
467         };
468         static const char *const tranwin[8] = {
469                 "0 us", "62.5 us", "125 us", "250 us",
470                 "500 us", "1 ms", "2 ms", "4 ms",
471         };
472         u8 max;
473         const char *const *names;
474
475         max = (ctl->private_value >> 12) & 0xf;
476         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
477         info->count = 1;
478         info->value.enumerated.items = max + 1;
479         if (info->value.enumerated.item > max)
480                 info->value.enumerated.item = max;
481         switch ((ctl->private_value >> 24) & 0x1f) {
482         case WM8776_ALCCTRL2:
483                 names = hld;
484                 break;
485         case WM8776_ALCCTRL3:
486                 if (((ctl->private_value >> 20) & 0xf) == 0) {
487                         if (ctl->private_value & LC_CONTROL_LIMITER)
488                                 names = atk_lim;
489                         else
490                                 names = atk_alc;
491                 } else {
492                         if (ctl->private_value & LC_CONTROL_LIMITER)
493                                 names = dcy_lim;
494                         else
495                                 names = dcy_alc;
496                 }
497                 break;
498         case WM8776_LIMITER:
499                 names = tranwin;
500                 break;
501         default:
502                 return -ENXIO;
503         }
504         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
505         return 0;
506 }
507
508 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
509                                     struct snd_ctl_elem_info *info)
510 {
511         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
512         info->count = 1;
513         info->value.integer.min = (ctl->private_value >> 8) & 0xf;
514         info->value.integer.max = (ctl->private_value >> 12) & 0xf;
515         return 0;
516 }
517
518 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
519 {
520         struct oxygen *chip = ctl->private_data;
521         struct xonar_wm87x6 *data = chip->model_data;
522         unsigned int value, reg_index, mode;
523         u8 min, max, shift;
524         u16 mask, reg_value;
525         bool invert;
526
527         if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
528             WM8776_LCSEL_LIMITER)
529                 mode = LC_CONTROL_LIMITER;
530         else
531                 mode = LC_CONTROL_ALC;
532         if (!(ctl->private_value & mode))
533                 return;
534
535         value = ctl->private_value & 0xf;
536         min = (ctl->private_value >> 8) & 0xf;
537         max = (ctl->private_value >> 12) & 0xf;
538         mask = (ctl->private_value >> 16) & 0xf;
539         shift = (ctl->private_value >> 20) & 0xf;
540         reg_index = (ctl->private_value >> 24) & 0x1f;
541         invert = (ctl->private_value >> 29) & 0x1;
542
543         if (invert)
544                 value = max - (value - min);
545         reg_value = data->wm8776_regs[reg_index];
546         reg_value &= ~(mask << shift);
547         reg_value |= value << shift;
548         wm8776_write_cached(chip, reg_index, reg_value);
549 }
550
551 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
552 {
553         struct oxygen *chip = ctl->private_data;
554         u8 min, max;
555         int changed;
556
557         min = (ctl->private_value >> 8) & 0xf;
558         max = (ctl->private_value >> 12) & 0xf;
559         if (value < min || value > max)
560                 return -EINVAL;
561         mutex_lock(&chip->mutex);
562         changed = value != (ctl->private_value & 0xf);
563         if (changed) {
564                 ctl->private_value = (ctl->private_value & ~0xf) | value;
565                 wm8776_field_set_from_ctl(ctl);
566         }
567         mutex_unlock(&chip->mutex);
568         return changed;
569 }
570
571 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
572                                  struct snd_ctl_elem_value *value)
573 {
574         value->value.enumerated.item[0] = ctl->private_value & 0xf;
575         return 0;
576 }
577
578 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
579                                    struct snd_ctl_elem_value *value)
580 {
581         value->value.integer.value[0] = ctl->private_value & 0xf;
582         return 0;
583 }
584
585 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
586                                  struct snd_ctl_elem_value *value)
587 {
588         return wm8776_field_set(ctl, value->value.enumerated.item[0]);
589 }
590
591 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
592                                    struct snd_ctl_elem_value *value)
593 {
594         return wm8776_field_set(ctl, value->value.integer.value[0]);
595 }
596
597 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
598                               struct snd_ctl_elem_info *info)
599 {
600         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
601         info->count = 2;
602         info->value.integer.min = 0x79 - 60;
603         info->value.integer.max = 0x7f;
604         return 0;
605 }
606
607 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
608                              struct snd_ctl_elem_value *value)
609 {
610         struct oxygen *chip = ctl->private_data;
611         struct xonar_wm87x6 *data = chip->model_data;
612
613         mutex_lock(&chip->mutex);
614         value->value.integer.value[0] =
615                 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
616         value->value.integer.value[1] =
617                 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
618         mutex_unlock(&chip->mutex);
619         return 0;
620 }
621
622 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
623                              struct snd_ctl_elem_value *value)
624 {
625         struct oxygen *chip = ctl->private_data;
626         struct xonar_wm87x6 *data = chip->model_data;
627         u8 to_update;
628
629         mutex_lock(&chip->mutex);
630         to_update = (value->value.integer.value[0] !=
631                      (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
632                 << 0;
633         to_update |= (value->value.integer.value[1] !=
634                       (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
635                 << 1;
636         if (value->value.integer.value[0] == value->value.integer.value[1]) {
637                 if (to_update) {
638                         wm8776_write(chip, WM8776_HPMASTER,
639                                      value->value.integer.value[0] |
640                                      WM8776_HPZCEN | WM8776_UPDATE);
641                         data->wm8776_regs[WM8776_HPLVOL] =
642                                 value->value.integer.value[0] | WM8776_HPZCEN;
643                         data->wm8776_regs[WM8776_HPRVOL] =
644                                 value->value.integer.value[0] | WM8776_HPZCEN;
645                 }
646         } else {
647                 if (to_update & 1)
648                         wm8776_write(chip, WM8776_HPLVOL,
649                                      value->value.integer.value[0] |
650                                      WM8776_HPZCEN |
651                                      ((to_update & 2) ? 0 : WM8776_UPDATE));
652                 if (to_update & 2)
653                         wm8776_write(chip, WM8776_HPRVOL,
654                                      value->value.integer.value[1] |
655                                      WM8776_HPZCEN | WM8776_UPDATE);
656         }
657         mutex_unlock(&chip->mutex);
658         return to_update != 0;
659 }
660
661 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
662                                 struct snd_ctl_elem_value *value)
663 {
664         struct oxygen *chip = ctl->private_data;
665         struct xonar_wm87x6 *data = chip->model_data;
666         unsigned int mux_bit = ctl->private_value;
667
668         value->value.integer.value[0] =
669                 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
670         return 0;
671 }
672
673 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
674                                 struct snd_ctl_elem_value *value)
675 {
676         struct oxygen *chip = ctl->private_data;
677         struct xonar_wm87x6 *data = chip->model_data;
678         struct snd_kcontrol *other_ctl;
679         unsigned int mux_bit = ctl->private_value;
680         u16 reg;
681         int changed;
682
683         mutex_lock(&chip->mutex);
684         reg = data->wm8776_regs[WM8776_ADCMUX];
685         if (value->value.integer.value[0]) {
686                 reg |= mux_bit;
687                 /* line-in and mic-in are exclusive */
688                 mux_bit ^= 3;
689                 if (reg & mux_bit) {
690                         reg &= ~mux_bit;
691                         if (mux_bit == 1)
692                                 other_ctl = data->line_adcmux_control;
693                         else
694                                 other_ctl = data->mic_adcmux_control;
695                         snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
696                                        &other_ctl->id);
697                 }
698         } else
699                 reg &= ~mux_bit;
700         changed = reg != data->wm8776_regs[WM8776_ADCMUX];
701         if (changed) {
702                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
703                                       reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
704                                       GPIO_DS_INPUT_ROUTE);
705                 wm8776_write(chip, WM8776_ADCMUX, reg);
706         }
707         mutex_unlock(&chip->mutex);
708         return changed;
709 }
710
711 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
712                                  struct snd_ctl_elem_info *info)
713 {
714         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
715         info->count = 2;
716         info->value.integer.min = 0xa5;
717         info->value.integer.max = 0xff;
718         return 0;
719 }
720
721 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
722                                 struct snd_ctl_elem_value *value)
723 {
724         struct oxygen *chip = ctl->private_data;
725         struct xonar_wm87x6 *data = chip->model_data;
726
727         mutex_lock(&chip->mutex);
728         value->value.integer.value[0] =
729                 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
730         value->value.integer.value[1] =
731                 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
732         mutex_unlock(&chip->mutex);
733         return 0;
734 }
735
736 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
737                                 struct snd_ctl_elem_value *value)
738 {
739         struct oxygen *chip = ctl->private_data;
740         struct xonar_wm87x6 *data = chip->model_data;
741         int changed = 0;
742
743         mutex_lock(&chip->mutex);
744         changed = (value->value.integer.value[0] !=
745                    (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
746                   (value->value.integer.value[1] !=
747                    (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
748         wm8776_write_cached(chip, WM8776_ADCLVOL,
749                             value->value.integer.value[0] | WM8776_ZCA);
750         wm8776_write_cached(chip, WM8776_ADCRVOL,
751                             value->value.integer.value[1] | WM8776_ZCA);
752         mutex_unlock(&chip->mutex);
753         return changed;
754 }
755
756 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
757                                      struct snd_ctl_elem_info *info)
758 {
759         static const char *const names[3] = {
760                 "None", "Peak Limiter", "Automatic Level Control"
761         };
762         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
763         info->count = 1;
764         info->value.enumerated.items = 3;
765         if (info->value.enumerated.item >= 3)
766                 info->value.enumerated.item = 2;
767         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
768         return 0;
769 }
770
771 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
772                                     struct snd_ctl_elem_value *value)
773 {
774         struct oxygen *chip = ctl->private_data;
775         struct xonar_wm87x6 *data = chip->model_data;
776
777         if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
778                 value->value.enumerated.item[0] = 0;
779         else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
780                  WM8776_LCSEL_LIMITER)
781                 value->value.enumerated.item[0] = 1;
782         else
783                 value->value.enumerated.item[0] = 2;
784         return 0;
785 }
786
787 static void activate_control(struct oxygen *chip,
788                              struct snd_kcontrol *ctl, unsigned int mode)
789 {
790         unsigned int access;
791
792         if (ctl->private_value & mode)
793                 access = 0;
794         else
795                 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
796         if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
797                 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
798                 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
799         }
800 }
801
802 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
803                                     struct snd_ctl_elem_value *value)
804 {
805         struct oxygen *chip = ctl->private_data;
806         struct xonar_wm87x6 *data = chip->model_data;
807         unsigned int mode = 0, i;
808         u16 ctrl1, ctrl2;
809         int changed;
810
811         if (value->value.enumerated.item[0] >= 3)
812                 return -EINVAL;
813         mutex_lock(&chip->mutex);
814         changed = value->value.enumerated.item[0] != ctl->private_value;
815         if (changed) {
816                 ctl->private_value = value->value.enumerated.item[0];
817                 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
818                 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
819                 switch (value->value.enumerated.item[0]) {
820                 default:
821                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
822                                             ctrl2 & ~WM8776_LCEN);
823                         break;
824                 case 1:
825                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
826                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
827                                             WM8776_LCSEL_LIMITER);
828                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
829                                             ctrl2 | WM8776_LCEN);
830                         mode = LC_CONTROL_LIMITER;
831                         break;
832                 case 2:
833                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
834                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
835                                             WM8776_LCSEL_ALC_STEREO);
836                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
837                                             ctrl2 | WM8776_LCEN);
838                         mode = LC_CONTROL_ALC;
839                         break;
840                 }
841                 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
842                         activate_control(chip, data->lc_controls[i], mode);
843         }
844         mutex_unlock(&chip->mutex);
845         return changed;
846 }
847
848 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
849 {
850         static const char *const names[2] = {
851                 "None", "High-pass Filter"
852         };
853
854         info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
855         info->count = 1;
856         info->value.enumerated.items = 2;
857         if (info->value.enumerated.item >= 2)
858                 info->value.enumerated.item = 1;
859         strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
860         return 0;
861 }
862
863 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
864 {
865         struct oxygen *chip = ctl->private_data;
866         struct xonar_wm87x6 *data = chip->model_data;
867
868         value->value.enumerated.item[0] =
869                 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
870         return 0;
871 }
872
873 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
874 {
875         struct oxygen *chip = ctl->private_data;
876         struct xonar_wm87x6 *data = chip->model_data;
877         unsigned int reg;
878         int changed;
879
880         mutex_lock(&chip->mutex);
881         reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
882         if (!value->value.enumerated.item[0])
883                 reg |= WM8776_ADCHPD;
884         changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
885         if (changed)
886                 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
887         mutex_unlock(&chip->mutex);
888         return changed;
889 }
890
891 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
892         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
893         .name = xname, \
894         .info = snd_ctl_boolean_mono_info, \
895         .get = wm8776_bit_switch_get, \
896         .put = wm8776_bit_switch_put, \
897         .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
898 }
899 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
900         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
901         .name = xname, \
902         .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
903         ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
904 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
905         _WM8776_FIELD_CTL(xname " Capture Enum", \
906                           reg, shift, init, min, max, mask, flags), \
907         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
908                   SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
909         .info = wm8776_field_enum_info, \
910         .get = wm8776_field_enum_get, \
911         .put = wm8776_field_enum_put, \
912 }
913 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
914         _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
915         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
916                   SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
917                   SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
918         .info = wm8776_field_volume_info, \
919         .get = wm8776_field_volume_get, \
920         .put = wm8776_field_volume_put, \
921         .tlv = { .p = tlv_p }, \
922 }
923
924 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
925 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
926 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
927 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
928 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
929 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
930 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
931 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
932
933 static const struct snd_kcontrol_new ds_controls[] = {
934         {
935                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
936                 .name = "Headphone Playback Volume",
937                 .info = wm8776_hp_vol_info,
938                 .get = wm8776_hp_vol_get,
939                 .put = wm8776_hp_vol_put,
940                 .tlv = { .p = wm8776_hp_db_scale },
941         },
942         WM8776_BIT_SWITCH("Headphone Playback Switch",
943                           WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
944         {
945                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
946                 .name = "Input Capture Volume",
947                 .info = wm8776_input_vol_info,
948                 .get = wm8776_input_vol_get,
949                 .put = wm8776_input_vol_put,
950                 .tlv = { .p = wm8776_adc_db_scale },
951         },
952         {
953                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
954                 .name = "Line Capture Switch",
955                 .info = snd_ctl_boolean_mono_info,
956                 .get = wm8776_input_mux_get,
957                 .put = wm8776_input_mux_put,
958                 .private_value = 1 << 0,
959         },
960         {
961                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
962                 .name = "Mic Capture Switch",
963                 .info = snd_ctl_boolean_mono_info,
964                 .get = wm8776_input_mux_get,
965                 .put = wm8776_input_mux_put,
966                 .private_value = 1 << 1,
967         },
968         WM8776_BIT_SWITCH("Front Mic Capture Switch",
969                           WM8776_ADCMUX, 1 << 2, 0, 0),
970         WM8776_BIT_SWITCH("Aux Capture Switch",
971                           WM8776_ADCMUX, 1 << 3, 0, 0),
972         {
973                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
974                 .name = "ADC Filter Capture Enum",
975                 .info = hpf_info,
976                 .get = hpf_get,
977                 .put = hpf_put,
978         },
979         {
980                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
981                 .name = "Level Control Capture Enum",
982                 .info = wm8776_level_control_info,
983                 .get = wm8776_level_control_get,
984                 .put = wm8776_level_control_put,
985                 .private_value = 0,
986         },
987 };
988 static const struct snd_kcontrol_new lc_controls[] = {
989         WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
990                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
991                                 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
992         WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
993                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
994                               LC_CONTROL_LIMITER),
995         WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
996                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
997                               LC_CONTROL_LIMITER),
998         WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
999                               WM8776_LIMITER, 4, 2, 0, 7, 0x7,
1000                               LC_CONTROL_LIMITER),
1001         WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
1002                                 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
1003                                 LC_CONTROL_LIMITER,
1004                                 wm8776_maxatten_lim_db_scale),
1005         WM8776_FIELD_CTL_VOLUME("ALC Target Level",
1006                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1007                                 LC_CONTROL_ALC, wm8776_lct_db_scale),
1008         WM8776_FIELD_CTL_ENUM("ALC Attack Time",
1009                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1010                               LC_CONTROL_ALC),
1011         WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1012                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1013                               LC_CONTROL_ALC),
1014         WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
1015                                 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
1016                                 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
1017         WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1018                                 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1019                                 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1020         WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1021                               WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1022                               LC_CONTROL_ALC),
1023         WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1024                           WM8776_NOISEGATE, WM8776_NGAT, 0,
1025                           LC_CONTROL_ALC),
1026         WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1027                                 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1028                                 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1029 };
1030
1031 static int xonar_ds_mixer_init(struct oxygen *chip)
1032 {
1033         struct xonar_wm87x6 *data = chip->model_data;
1034         unsigned int i;
1035         struct snd_kcontrol *ctl;
1036         int err;
1037
1038         for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1039                 ctl = snd_ctl_new1(&ds_controls[i], chip);
1040                 if (!ctl)
1041                         return -ENOMEM;
1042                 err = snd_ctl_add(chip->card, ctl);
1043                 if (err < 0)
1044                         return err;
1045                 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1046                         data->line_adcmux_control = ctl;
1047                 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1048                         data->mic_adcmux_control = ctl;
1049         }
1050         if (!data->line_adcmux_control || !data->mic_adcmux_control)
1051                 return -ENXIO;
1052         BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1053         for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1054                 ctl = snd_ctl_new1(&lc_controls[i], chip);
1055                 if (!ctl)
1056                         return -ENOMEM;
1057                 err = snd_ctl_add(chip->card, ctl);
1058                 if (err < 0)
1059                         return err;
1060                 data->lc_controls[i] = ctl;
1061         }
1062         return 0;
1063 }
1064
1065 static const struct oxygen_model model_xonar_ds = {
1066         .shortname = "Xonar DS",
1067         .longname = "Asus Virtuoso 66",
1068         .chip = "AV200",
1069         .init = xonar_ds_init,
1070         .mixer_init = xonar_ds_mixer_init,
1071         .cleanup = xonar_ds_cleanup,
1072         .suspend = xonar_ds_suspend,
1073         .resume = xonar_ds_resume,
1074         .pcm_hardware_filter = wm8776_adc_hardware_filter,
1075         .get_i2s_mclk = oxygen_default_i2s_mclk,
1076         .set_dac_params = set_wm87x6_dac_params,
1077         .set_adc_params = set_wm8776_adc_params,
1078         .update_dac_volume = update_wm87x6_volume,
1079         .update_dac_mute = update_wm87x6_mute,
1080         .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1081         .gpio_changed = xonar_ds_gpio_changed,
1082         .dac_tlv = wm87x6_dac_db_scale,
1083         .model_data_size = sizeof(struct xonar_wm87x6),
1084         .device_config = PLAYBACK_0_TO_I2S |
1085                          PLAYBACK_1_TO_SPDIF |
1086                          CAPTURE_0_FROM_I2S_1,
1087         .dac_channels = 8,
1088         .dac_volume_min = 255 - 2*60,
1089         .dac_volume_max = 255,
1090         .function_flags = OXYGEN_FUNCTION_SPI,
1091         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1092         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1093 };
1094
1095 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1096                                      const struct pci_device_id *id)
1097 {
1098         switch (id->subdevice) {
1099         case 0x838e:
1100                 chip->model = model_xonar_ds;
1101                 break;
1102         default:
1103                 return -EINVAL;
1104         }
1105         return 0;
1106 }