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