blob: 0b89932fb8c40807e7dbbefe9cde41e08db9757a [file] [log] [blame]
Clemens Ladischd1db38c2010-01-18 15:44:04 +01001/*
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
52struct 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
59static 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)) {
Clemens Ladischfaf4eb22010-03-03 09:16:18 +010071 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
Clemens Ladischd1db38c2010-01-18 15:44:04 +010072 value &= ~WM8776_UPDATE;
73 data->wm8776_regs[reg] = value;
74 }
75}
76
77static 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
87static 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
102static 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
116static 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
140static 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
154static 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
171static 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
193static void xonar_ds_cleanup(struct oxygen *chip)
194{
195 xonar_disable_output(chip);
Clemens Ladisch4c25b932010-09-07 13:37:10 +0200196 wm8776_write(chip, WM8776_RESET, 0);
Clemens Ladischd1db38c2010-01-18 15:44:04 +0100197}
198
199static void xonar_ds_suspend(struct oxygen *chip)
200{
201 xonar_ds_cleanup(chip);
202}
203
204static 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
211static 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
225static void set_wm87x6_dac_params(struct oxygen *chip,
226 struct snd_pcm_hw_params *params)
227{
228}
229
230static 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
241static 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
268static 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
311static void update_wm8776_mute(struct oxygen *chip)
312{
313 wm8776_write_cached(chip, WM8776_DACMUTE,
314 chip->dac_mute ? WM8776_DMUTE : 0);
315}
316
317static 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
324static 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
332static 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
346static 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
368static 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
437static 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
447static 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
480static 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
500static 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
507static 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
514static 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
520static 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
526static 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
536static 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
551static 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
590static 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
602static 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
629static 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
639static 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
654static 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
674static 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
689static 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
705static 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
720static 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
766static 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
781static 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
791static 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
842static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
843static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
844static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
845static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
846static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
847static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
848static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
849static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
850
851static 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};
903static 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
946static 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
953static 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
981static 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
1011int __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}