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