ALSA: virtuoso: add Xonar HDAV1.3 Slim support
[deliverable/linux.git] / sound / pci / oxygen / xonar_wm87x6.c
1 /*
2 * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim)
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * Xonar DS
21 * --------
22 *
23 * CMI8788:
24 *
25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input)
27 *
28 * GPIO 4 <- headphone detect, 0 = plugged
29 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
30 * GPIO 7 -> enable output to front L/R speaker channels
31 * GPIO 8 -> enable output to other speaker channels and front panel headphone
32 *
33 * WM8776:
34 *
35 * input 1 <- line
36 * input 2 <- mic
37 * input 3 <- front mic
38 * input 4 <- aux
39 */
40
41 /*
42 * Xonar HDAV1.3 Slim
43 * ------------------
44 *
45 * CMI8788:
46 *
47 * I²C <-> WM8776 (addr 0011010)
48 *
49 * GPIO 0 -> disable HDMI output
50 * GPIO 1 -> enable HP output
51 * GPIO 6 -> firmware EEPROM I²C clock
52 * GPIO 7 <-> firmware EEPROM I²C data
53 *
54 * UART <-> HDMI controller
55 *
56 * WM8776:
57 *
58 * input 1 <- mic
59 * input 2 <- aux
60 */
61
62 #include <linux/pci.h>
63 #include <linux/delay.h>
64 #include <sound/control.h>
65 #include <sound/core.h>
66 #include <sound/info.h>
67 #include <sound/jack.h>
68 #include <sound/pcm.h>
69 #include <sound/pcm_params.h>
70 #include <sound/tlv.h>
71 #include "xonar.h"
72 #include "wm8776.h"
73 #include "wm8766.h"
74
75 #define GPIO_DS_HP_DETECT 0x0010
76 #define GPIO_DS_INPUT_ROUTE 0x0040
77 #define GPIO_DS_OUTPUT_FRONTLR 0x0080
78 #define GPIO_DS_OUTPUT_ENABLE 0x0100
79
80 #define GPIO_SLIM_HDMI_DISABLE 0x0001
81 #define GPIO_SLIM_OUTPUT_ENABLE 0x0002
82 #define GPIO_SLIM_FIRMWARE_CLK 0x0040
83 #define GPIO_SLIM_FIRMWARE_DATA 0x0080
84
85 #define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */
86
87 #define LC_CONTROL_LIMITER 0x40000000
88 #define LC_CONTROL_ALC 0x20000000
89
90 struct xonar_wm87x6 {
91 struct xonar_generic generic;
92 u16 wm8776_regs[0x17];
93 u16 wm8766_regs[0x10];
94 struct snd_kcontrol *line_adcmux_control;
95 struct snd_kcontrol *mic_adcmux_control;
96 struct snd_kcontrol *lc_controls[13];
97 struct snd_jack *hp_jack;
98 struct xonar_hdmi hdmi;
99 };
100
101 static void wm8776_write_spi(struct oxygen *chip,
102 unsigned int reg, unsigned int value)
103 {
104 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
105 OXYGEN_SPI_DATA_LENGTH_2 |
106 OXYGEN_SPI_CLOCK_160 |
107 (1 << OXYGEN_SPI_CODEC_SHIFT) |
108 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
109 (reg << 9) | value);
110 }
111
112 static void wm8776_write_i2c(struct oxygen *chip,
113 unsigned int reg, unsigned int value)
114 {
115 oxygen_write_i2c(chip, I2C_DEVICE_WM8776,
116 (reg << 1) | (value >> 8), value);
117 }
118
119 static void wm8776_write(struct oxygen *chip,
120 unsigned int reg, unsigned int value)
121 {
122 struct xonar_wm87x6 *data = chip->model_data;
123
124 if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) ==
125 OXYGEN_FUNCTION_SPI)
126 wm8776_write_spi(chip, reg, value);
127 else
128 wm8776_write_i2c(chip, reg, value);
129 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
130 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
131 value &= ~WM8776_UPDATE;
132 data->wm8776_regs[reg] = value;
133 }
134 }
135
136 static void wm8776_write_cached(struct oxygen *chip,
137 unsigned int reg, unsigned int value)
138 {
139 struct xonar_wm87x6 *data = chip->model_data;
140
141 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
142 value != data->wm8776_regs[reg])
143 wm8776_write(chip, reg, value);
144 }
145
146 static void wm8766_write(struct oxygen *chip,
147 unsigned int reg, unsigned int value)
148 {
149 struct xonar_wm87x6 *data = chip->model_data;
150
151 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
152 OXYGEN_SPI_DATA_LENGTH_2 |
153 OXYGEN_SPI_CLOCK_160 |
154 (0 << OXYGEN_SPI_CODEC_SHIFT) |
155 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
156 (reg << 9) | value);
157 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
158 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
159 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
160 value &= ~WM8766_UPDATE;
161 data->wm8766_regs[reg] = value;
162 }
163 }
164
165 static void wm8766_write_cached(struct oxygen *chip,
166 unsigned int reg, unsigned int value)
167 {
168 struct xonar_wm87x6 *data = chip->model_data;
169
170 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
171 value != data->wm8766_regs[reg])
172 wm8766_write(chip, reg, value);
173 }
174
175 static void wm8776_registers_init(struct oxygen *chip)
176 {
177 struct xonar_wm87x6 *data = chip->model_data;
178
179 wm8776_write(chip, WM8776_RESET, 0);
180 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
181 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
182 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
183 wm8776_write(chip, WM8776_DACIFCTRL,
184 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
185 wm8776_write(chip, WM8776_ADCIFCTRL,
186 data->wm8776_regs[WM8776_ADCIFCTRL]);
187 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
188 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
189 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
190 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
191 WM8776_UPDATE);
192 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
193 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
194 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
195 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
196 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
197 }
198
199 static void wm8766_registers_init(struct oxygen *chip)
200 {
201 struct xonar_wm87x6 *data = chip->model_data;
202
203 wm8766_write(chip, WM8766_RESET, 0);
204 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
205 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
206 wm8766_write(chip, WM8766_DAC_CTRL2,
207 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
208 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
209 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
210 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
211 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
212 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
213 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
214 }
215
216 static void wm8776_init(struct oxygen *chip)
217 {
218 struct xonar_wm87x6 *data = chip->model_data;
219
220 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
221 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
222 data->wm8776_regs[WM8776_ADCIFCTRL] =
223 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
224 data->wm8776_regs[WM8776_MSTRCTRL] =
225 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
226 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
227 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
228 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
229 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
230 wm8776_registers_init(chip);
231 }
232
233 static void wm8766_init(struct oxygen *chip)
234 {
235 struct xonar_wm87x6 *data = chip->model_data;
236
237 data->wm8766_regs[WM8766_DAC_CTRL] =
238 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
239 wm8766_registers_init(chip);
240 }
241
242 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
243 {
244 struct xonar_wm87x6 *data = chip->model_data;
245 bool hp_plugged;
246 unsigned int reg;
247
248 mutex_lock(&chip->mutex);
249
250 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
251 GPIO_DS_HP_DETECT);
252
253 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
254 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
255 GPIO_DS_OUTPUT_FRONTLR);
256
257 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
258 if (hp_plugged)
259 reg |= WM8766_MUTEALL;
260 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
261
262 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
263
264 mutex_unlock(&chip->mutex);
265 }
266
267 static void xonar_ds_init(struct oxygen *chip)
268 {
269 struct xonar_wm87x6 *data = chip->model_data;
270
271 data->generic.anti_pop_delay = 300;
272 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
273
274 wm8776_init(chip);
275 wm8766_init(chip);
276
277 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
278 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
279 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
280 GPIO_DS_HP_DETECT);
281 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
282 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
283 chip->interrupt_mask |= OXYGEN_INT_GPIO;
284
285 xonar_enable_output(chip);
286
287 snd_jack_new(chip->card, "Headphone",
288 SND_JACK_HEADPHONE, &data->hp_jack);
289 xonar_ds_handle_hp_jack(chip);
290
291 snd_component_add(chip->card, "WM8776");
292 snd_component_add(chip->card, "WM8766");
293 }
294
295 static void xonar_hdav_slim_init(struct oxygen *chip)
296 {
297 struct xonar_wm87x6 *data = chip->model_data;
298
299 data->generic.anti_pop_delay = 300;
300 data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE;
301
302 wm8776_init(chip);
303
304 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
305 GPIO_SLIM_HDMI_DISABLE |
306 GPIO_SLIM_FIRMWARE_CLK |
307 GPIO_SLIM_FIRMWARE_DATA);
308
309 xonar_hdmi_init(chip, &data->hdmi);
310 xonar_enable_output(chip);
311
312 snd_component_add(chip->card, "WM8776");
313 }
314
315 static void xonar_ds_cleanup(struct oxygen *chip)
316 {
317 xonar_disable_output(chip);
318 wm8776_write(chip, WM8776_RESET, 0);
319 }
320
321 static void xonar_hdav_slim_cleanup(struct oxygen *chip)
322 {
323 xonar_hdmi_cleanup(chip);
324 xonar_disable_output(chip);
325 wm8776_write(chip, WM8776_RESET, 0);
326 msleep(2);
327 }
328
329 static void xonar_ds_suspend(struct oxygen *chip)
330 {
331 xonar_ds_cleanup(chip);
332 }
333
334 static void xonar_hdav_slim_suspend(struct oxygen *chip)
335 {
336 xonar_hdav_slim_cleanup(chip);
337 }
338
339 static void xonar_ds_resume(struct oxygen *chip)
340 {
341 wm8776_registers_init(chip);
342 wm8766_registers_init(chip);
343 xonar_enable_output(chip);
344 xonar_ds_handle_hp_jack(chip);
345 }
346
347 static void xonar_hdav_slim_resume(struct oxygen *chip)
348 {
349 struct xonar_wm87x6 *data = chip->model_data;
350
351 wm8776_registers_init(chip);
352 xonar_hdmi_resume(chip, &data->hdmi);
353 xonar_enable_output(chip);
354 }
355
356 static void wm8776_adc_hardware_filter(unsigned int channel,
357 struct snd_pcm_hardware *hardware)
358 {
359 if (channel == PCM_A) {
360 hardware->rates = SNDRV_PCM_RATE_32000 |
361 SNDRV_PCM_RATE_44100 |
362 SNDRV_PCM_RATE_48000 |
363 SNDRV_PCM_RATE_64000 |
364 SNDRV_PCM_RATE_88200 |
365 SNDRV_PCM_RATE_96000;
366 hardware->rate_max = 96000;
367 }
368 }
369
370 static void xonar_hdav_slim_hardware_filter(unsigned int channel,
371 struct snd_pcm_hardware *hardware)
372 {
373 wm8776_adc_hardware_filter(channel, hardware);
374 xonar_hdmi_pcm_hardware_filter(channel, hardware);
375 }
376
377 static void set_wm87x6_dac_params(struct oxygen *chip,
378 struct snd_pcm_hw_params *params)
379 {
380 }
381
382 static void set_wm8776_adc_params(struct oxygen *chip,
383 struct snd_pcm_hw_params *params)
384 {
385 u16 reg;
386
387 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
388 if (params_rate(params) > 48000)
389 reg |= WM8776_ADCOSR;
390 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
391 }
392
393 static void set_hdav_slim_dac_params(struct oxygen *chip,
394 struct snd_pcm_hw_params *params)
395 {
396 struct xonar_wm87x6 *data = chip->model_data;
397
398 xonar_set_hdmi_params(chip, &data->hdmi, params);
399 }
400
401 static void update_wm8776_volume(struct oxygen *chip)
402 {
403 struct xonar_wm87x6 *data = chip->model_data;
404 u8 to_change;
405
406 if (chip->dac_volume[0] == chip->dac_volume[1]) {
407 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
408 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
409 wm8776_write(chip, WM8776_DACMASTER,
410 chip->dac_volume[0] | WM8776_UPDATE);
411 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
412 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
413 }
414 } else {
415 to_change = (chip->dac_volume[0] !=
416 data->wm8776_regs[WM8776_DACLVOL]) << 0;
417 to_change |= (chip->dac_volume[1] !=
418 data->wm8776_regs[WM8776_DACLVOL]) << 1;
419 if (to_change & 1)
420 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
421 ((to_change & 2) ? 0 : WM8776_UPDATE));
422 if (to_change & 2)
423 wm8776_write(chip, WM8776_DACRVOL,
424 chip->dac_volume[1] | WM8776_UPDATE);
425 }
426 }
427
428 static void update_wm87x6_volume(struct oxygen *chip)
429 {
430 static const u8 wm8766_regs[6] = {
431 WM8766_LDA1, WM8766_RDA1,
432 WM8766_LDA2, WM8766_RDA2,
433 WM8766_LDA3, WM8766_RDA3,
434 };
435 struct xonar_wm87x6 *data = chip->model_data;
436 unsigned int i;
437 u8 to_change;
438
439 update_wm8776_volume(chip);
440 if (chip->dac_volume[2] == chip->dac_volume[3] &&
441 chip->dac_volume[2] == chip->dac_volume[4] &&
442 chip->dac_volume[2] == chip->dac_volume[5] &&
443 chip->dac_volume[2] == chip->dac_volume[6] &&
444 chip->dac_volume[2] == chip->dac_volume[7]) {
445 to_change = 0;
446 for (i = 0; i < 6; ++i)
447 if (chip->dac_volume[2] !=
448 data->wm8766_regs[wm8766_regs[i]])
449 to_change = 1;
450 if (to_change) {
451 wm8766_write(chip, WM8766_MASTDA,
452 chip->dac_volume[2] | WM8766_UPDATE);
453 for (i = 0; i < 6; ++i)
454 data->wm8766_regs[wm8766_regs[i]] =
455 chip->dac_volume[2];
456 }
457 } else {
458 to_change = 0;
459 for (i = 0; i < 6; ++i)
460 to_change |= (chip->dac_volume[2 + i] !=
461 data->wm8766_regs[wm8766_regs[i]]) << i;
462 for (i = 0; i < 6; ++i)
463 if (to_change & (1 << i))
464 wm8766_write(chip, wm8766_regs[i],
465 chip->dac_volume[2 + i] |
466 ((to_change & (0x3e << i))
467 ? 0 : WM8766_UPDATE));
468 }
469 }
470
471 static void update_wm8776_mute(struct oxygen *chip)
472 {
473 wm8776_write_cached(chip, WM8776_DACMUTE,
474 chip->dac_mute ? WM8776_DMUTE : 0);
475 }
476
477 static void update_wm87x6_mute(struct oxygen *chip)
478 {
479 update_wm8776_mute(chip);
480 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
481 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
482 }
483
484 static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
485 {
486 struct xonar_wm87x6 *data = chip->model_data;
487 unsigned int reg;
488
489 /*
490 * The WM8766 can mix left and right channels, but this setting
491 * applies to all three stereo pairs.
492 */
493 reg = data->wm8766_regs[WM8766_DAC_CTRL] &
494 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
495 if (mixed)
496 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
497 else
498 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
499 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
500 }
501
502 static void xonar_ds_gpio_changed(struct oxygen *chip)
503 {
504 xonar_ds_handle_hp_jack(chip);
505 }
506
507 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
508 struct snd_ctl_elem_value *value)
509 {
510 struct oxygen *chip = ctl->private_data;
511 struct xonar_wm87x6 *data = chip->model_data;
512 u16 bit = ctl->private_value & 0xffff;
513 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
514 bool invert = (ctl->private_value >> 24) & 1;
515
516 value->value.integer.value[0] =
517 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
518 return 0;
519 }
520
521 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
522 struct snd_ctl_elem_value *value)
523 {
524 struct oxygen *chip = ctl->private_data;
525 struct xonar_wm87x6 *data = chip->model_data;
526 u16 bit = ctl->private_value & 0xffff;
527 u16 reg_value;
528 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
529 bool invert = (ctl->private_value >> 24) & 1;
530 int changed;
531
532 mutex_lock(&chip->mutex);
533 reg_value = data->wm8776_regs[reg_index] & ~bit;
534 if (value->value.integer.value[0] ^ invert)
535 reg_value |= bit;
536 changed = reg_value != data->wm8776_regs[reg_index];
537 if (changed)
538 wm8776_write(chip, reg_index, reg_value);
539 mutex_unlock(&chip->mutex);
540 return changed;
541 }
542
543 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
544 struct snd_ctl_elem_info *info)
545 {
546 static const char *const hld[16] = {
547 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
548 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
549 "341 ms", "683 ms", "1.37 s", "2.73 s",
550 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
551 };
552 static const char *const atk_lim[11] = {
553 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
554 "4 ms", "8 ms", "16 ms", "32 ms",
555 "64 ms", "128 ms", "256 ms",
556 };
557 static const char *const atk_alc[11] = {
558 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
559 "134 ms", "269 ms", "538 ms", "1.08 s",
560 "2.15 s", "4.3 s", "8.6 s",
561 };
562 static const char *const dcy_lim[11] = {
563 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
564 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
565 "307 ms", "614 ms", "1.23 s",
566 };
567 static const char *const dcy_alc[11] = {
568 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
569 "536 ms", "1.07 s", "2.14 s", "4.29 s",
570 "8.58 s", "17.2 s", "34.3 s",
571 };
572 static const char *const tranwin[8] = {
573 "0 us", "62.5 us", "125 us", "250 us",
574 "500 us", "1 ms", "2 ms", "4 ms",
575 };
576 u8 max;
577 const char *const *names;
578
579 max = (ctl->private_value >> 12) & 0xf;
580 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
581 info->count = 1;
582 info->value.enumerated.items = max + 1;
583 if (info->value.enumerated.item > max)
584 info->value.enumerated.item = max;
585 switch ((ctl->private_value >> 24) & 0x1f) {
586 case WM8776_ALCCTRL2:
587 names = hld;
588 break;
589 case WM8776_ALCCTRL3:
590 if (((ctl->private_value >> 20) & 0xf) == 0) {
591 if (ctl->private_value & LC_CONTROL_LIMITER)
592 names = atk_lim;
593 else
594 names = atk_alc;
595 } else {
596 if (ctl->private_value & LC_CONTROL_LIMITER)
597 names = dcy_lim;
598 else
599 names = dcy_alc;
600 }
601 break;
602 case WM8776_LIMITER:
603 names = tranwin;
604 break;
605 default:
606 return -ENXIO;
607 }
608 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
609 return 0;
610 }
611
612 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
613 struct snd_ctl_elem_info *info)
614 {
615 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
616 info->count = 1;
617 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
618 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
619 return 0;
620 }
621
622 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
623 {
624 struct oxygen *chip = ctl->private_data;
625 struct xonar_wm87x6 *data = chip->model_data;
626 unsigned int value, reg_index, mode;
627 u8 min, max, shift;
628 u16 mask, reg_value;
629 bool invert;
630
631 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
632 WM8776_LCSEL_LIMITER)
633 mode = LC_CONTROL_LIMITER;
634 else
635 mode = LC_CONTROL_ALC;
636 if (!(ctl->private_value & mode))
637 return;
638
639 value = ctl->private_value & 0xf;
640 min = (ctl->private_value >> 8) & 0xf;
641 max = (ctl->private_value >> 12) & 0xf;
642 mask = (ctl->private_value >> 16) & 0xf;
643 shift = (ctl->private_value >> 20) & 0xf;
644 reg_index = (ctl->private_value >> 24) & 0x1f;
645 invert = (ctl->private_value >> 29) & 0x1;
646
647 if (invert)
648 value = max - (value - min);
649 reg_value = data->wm8776_regs[reg_index];
650 reg_value &= ~(mask << shift);
651 reg_value |= value << shift;
652 wm8776_write_cached(chip, reg_index, reg_value);
653 }
654
655 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
656 {
657 struct oxygen *chip = ctl->private_data;
658 u8 min, max;
659 int changed;
660
661 min = (ctl->private_value >> 8) & 0xf;
662 max = (ctl->private_value >> 12) & 0xf;
663 if (value < min || value > max)
664 return -EINVAL;
665 mutex_lock(&chip->mutex);
666 changed = value != (ctl->private_value & 0xf);
667 if (changed) {
668 ctl->private_value = (ctl->private_value & ~0xf) | value;
669 wm8776_field_set_from_ctl(ctl);
670 }
671 mutex_unlock(&chip->mutex);
672 return changed;
673 }
674
675 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
676 struct snd_ctl_elem_value *value)
677 {
678 value->value.enumerated.item[0] = ctl->private_value & 0xf;
679 return 0;
680 }
681
682 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
683 struct snd_ctl_elem_value *value)
684 {
685 value->value.integer.value[0] = ctl->private_value & 0xf;
686 return 0;
687 }
688
689 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
690 struct snd_ctl_elem_value *value)
691 {
692 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
693 }
694
695 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
696 struct snd_ctl_elem_value *value)
697 {
698 return wm8776_field_set(ctl, value->value.integer.value[0]);
699 }
700
701 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
702 struct snd_ctl_elem_info *info)
703 {
704 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
705 info->count = 2;
706 info->value.integer.min = 0x79 - 60;
707 info->value.integer.max = 0x7f;
708 return 0;
709 }
710
711 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
712 struct snd_ctl_elem_value *value)
713 {
714 struct oxygen *chip = ctl->private_data;
715 struct xonar_wm87x6 *data = chip->model_data;
716
717 mutex_lock(&chip->mutex);
718 value->value.integer.value[0] =
719 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
720 value->value.integer.value[1] =
721 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
722 mutex_unlock(&chip->mutex);
723 return 0;
724 }
725
726 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
727 struct snd_ctl_elem_value *value)
728 {
729 struct oxygen *chip = ctl->private_data;
730 struct xonar_wm87x6 *data = chip->model_data;
731 u8 to_update;
732
733 mutex_lock(&chip->mutex);
734 to_update = (value->value.integer.value[0] !=
735 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
736 << 0;
737 to_update |= (value->value.integer.value[1] !=
738 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
739 << 1;
740 if (value->value.integer.value[0] == value->value.integer.value[1]) {
741 if (to_update) {
742 wm8776_write(chip, WM8776_HPMASTER,
743 value->value.integer.value[0] |
744 WM8776_HPZCEN | WM8776_UPDATE);
745 data->wm8776_regs[WM8776_HPLVOL] =
746 value->value.integer.value[0] | WM8776_HPZCEN;
747 data->wm8776_regs[WM8776_HPRVOL] =
748 value->value.integer.value[0] | WM8776_HPZCEN;
749 }
750 } else {
751 if (to_update & 1)
752 wm8776_write(chip, WM8776_HPLVOL,
753 value->value.integer.value[0] |
754 WM8776_HPZCEN |
755 ((to_update & 2) ? 0 : WM8776_UPDATE));
756 if (to_update & 2)
757 wm8776_write(chip, WM8776_HPRVOL,
758 value->value.integer.value[1] |
759 WM8776_HPZCEN | WM8776_UPDATE);
760 }
761 mutex_unlock(&chip->mutex);
762 return to_update != 0;
763 }
764
765 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
766 struct snd_ctl_elem_value *value)
767 {
768 struct oxygen *chip = ctl->private_data;
769 struct xonar_wm87x6 *data = chip->model_data;
770 unsigned int mux_bit = ctl->private_value;
771
772 value->value.integer.value[0] =
773 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
774 return 0;
775 }
776
777 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
778 struct snd_ctl_elem_value *value)
779 {
780 struct oxygen *chip = ctl->private_data;
781 struct xonar_wm87x6 *data = chip->model_data;
782 struct snd_kcontrol *other_ctl;
783 unsigned int mux_bit = ctl->private_value;
784 u16 reg;
785 int changed;
786
787 mutex_lock(&chip->mutex);
788 reg = data->wm8776_regs[WM8776_ADCMUX];
789 if (value->value.integer.value[0]) {
790 reg |= mux_bit;
791 /* line-in and mic-in are exclusive */
792 mux_bit ^= 3;
793 if (reg & mux_bit) {
794 reg &= ~mux_bit;
795 if (mux_bit == 1)
796 other_ctl = data->line_adcmux_control;
797 else
798 other_ctl = data->mic_adcmux_control;
799 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
800 &other_ctl->id);
801 }
802 } else
803 reg &= ~mux_bit;
804 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
805 if (changed) {
806 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
807 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
808 GPIO_DS_INPUT_ROUTE);
809 wm8776_write(chip, WM8776_ADCMUX, reg);
810 }
811 mutex_unlock(&chip->mutex);
812 return changed;
813 }
814
815 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
816 struct snd_ctl_elem_info *info)
817 {
818 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
819 info->count = 2;
820 info->value.integer.min = 0xa5;
821 info->value.integer.max = 0xff;
822 return 0;
823 }
824
825 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
826 struct snd_ctl_elem_value *value)
827 {
828 struct oxygen *chip = ctl->private_data;
829 struct xonar_wm87x6 *data = chip->model_data;
830
831 mutex_lock(&chip->mutex);
832 value->value.integer.value[0] =
833 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
834 value->value.integer.value[1] =
835 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
836 mutex_unlock(&chip->mutex);
837 return 0;
838 }
839
840 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
841 struct snd_ctl_elem_value *value)
842 {
843 struct oxygen *chip = ctl->private_data;
844 struct xonar_wm87x6 *data = chip->model_data;
845 int changed = 0;
846
847 mutex_lock(&chip->mutex);
848 changed = (value->value.integer.value[0] !=
849 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
850 (value->value.integer.value[1] !=
851 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
852 wm8776_write_cached(chip, WM8776_ADCLVOL,
853 value->value.integer.value[0] | WM8776_ZCA);
854 wm8776_write_cached(chip, WM8776_ADCRVOL,
855 value->value.integer.value[1] | WM8776_ZCA);
856 mutex_unlock(&chip->mutex);
857 return changed;
858 }
859
860 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
861 struct snd_ctl_elem_info *info)
862 {
863 static const char *const names[3] = {
864 "None", "Peak Limiter", "Automatic Level Control"
865 };
866 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
867 info->count = 1;
868 info->value.enumerated.items = 3;
869 if (info->value.enumerated.item >= 3)
870 info->value.enumerated.item = 2;
871 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
872 return 0;
873 }
874
875 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
876 struct snd_ctl_elem_value *value)
877 {
878 struct oxygen *chip = ctl->private_data;
879 struct xonar_wm87x6 *data = chip->model_data;
880
881 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
882 value->value.enumerated.item[0] = 0;
883 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
884 WM8776_LCSEL_LIMITER)
885 value->value.enumerated.item[0] = 1;
886 else
887 value->value.enumerated.item[0] = 2;
888 return 0;
889 }
890
891 static void activate_control(struct oxygen *chip,
892 struct snd_kcontrol *ctl, unsigned int mode)
893 {
894 unsigned int access;
895
896 if (ctl->private_value & mode)
897 access = 0;
898 else
899 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
900 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
901 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
902 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
903 }
904 }
905
906 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
907 struct snd_ctl_elem_value *value)
908 {
909 struct oxygen *chip = ctl->private_data;
910 struct xonar_wm87x6 *data = chip->model_data;
911 unsigned int mode = 0, i;
912 u16 ctrl1, ctrl2;
913 int changed;
914
915 if (value->value.enumerated.item[0] >= 3)
916 return -EINVAL;
917 mutex_lock(&chip->mutex);
918 changed = value->value.enumerated.item[0] != ctl->private_value;
919 if (changed) {
920 ctl->private_value = value->value.enumerated.item[0];
921 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
922 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
923 switch (value->value.enumerated.item[0]) {
924 default:
925 wm8776_write_cached(chip, WM8776_ALCCTRL2,
926 ctrl2 & ~WM8776_LCEN);
927 break;
928 case 1:
929 wm8776_write_cached(chip, WM8776_ALCCTRL1,
930 (ctrl1 & ~WM8776_LCSEL_MASK) |
931 WM8776_LCSEL_LIMITER);
932 wm8776_write_cached(chip, WM8776_ALCCTRL2,
933 ctrl2 | WM8776_LCEN);
934 mode = LC_CONTROL_LIMITER;
935 break;
936 case 2:
937 wm8776_write_cached(chip, WM8776_ALCCTRL1,
938 (ctrl1 & ~WM8776_LCSEL_MASK) |
939 WM8776_LCSEL_ALC_STEREO);
940 wm8776_write_cached(chip, WM8776_ALCCTRL2,
941 ctrl2 | WM8776_LCEN);
942 mode = LC_CONTROL_ALC;
943 break;
944 }
945 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
946 activate_control(chip, data->lc_controls[i], mode);
947 }
948 mutex_unlock(&chip->mutex);
949 return changed;
950 }
951
952 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
953 {
954 static const char *const names[2] = {
955 "None", "High-pass Filter"
956 };
957
958 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
959 info->count = 1;
960 info->value.enumerated.items = 2;
961 if (info->value.enumerated.item >= 2)
962 info->value.enumerated.item = 1;
963 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
964 return 0;
965 }
966
967 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
968 {
969 struct oxygen *chip = ctl->private_data;
970 struct xonar_wm87x6 *data = chip->model_data;
971
972 value->value.enumerated.item[0] =
973 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
974 return 0;
975 }
976
977 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
978 {
979 struct oxygen *chip = ctl->private_data;
980 struct xonar_wm87x6 *data = chip->model_data;
981 unsigned int reg;
982 int changed;
983
984 mutex_lock(&chip->mutex);
985 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
986 if (!value->value.enumerated.item[0])
987 reg |= WM8776_ADCHPD;
988 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
989 if (changed)
990 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
991 mutex_unlock(&chip->mutex);
992 return changed;
993 }
994
995 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
996 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
997 .name = xname, \
998 .info = snd_ctl_boolean_mono_info, \
999 .get = wm8776_bit_switch_get, \
1000 .put = wm8776_bit_switch_put, \
1001 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
1002 }
1003 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
1004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1005 .name = xname, \
1006 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
1007 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
1008 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
1009 _WM8776_FIELD_CTL(xname " Capture Enum", \
1010 reg, shift, init, min, max, mask, flags), \
1011 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1012 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
1013 .info = wm8776_field_enum_info, \
1014 .get = wm8776_field_enum_get, \
1015 .put = wm8776_field_enum_put, \
1016 }
1017 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
1018 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
1019 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1020 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
1021 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
1022 .info = wm8776_field_volume_info, \
1023 .get = wm8776_field_volume_get, \
1024 .put = wm8776_field_volume_put, \
1025 .tlv = { .p = tlv_p }, \
1026 }
1027
1028 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
1029 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
1030 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
1031 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
1032 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
1033 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
1034 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
1035 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
1036
1037 static const struct snd_kcontrol_new ds_controls[] = {
1038 {
1039 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1040 .name = "Headphone Playback Volume",
1041 .info = wm8776_hp_vol_info,
1042 .get = wm8776_hp_vol_get,
1043 .put = wm8776_hp_vol_put,
1044 .tlv = { .p = wm8776_hp_db_scale },
1045 },
1046 WM8776_BIT_SWITCH("Headphone Playback Switch",
1047 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1048 {
1049 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1050 .name = "Input Capture Volume",
1051 .info = wm8776_input_vol_info,
1052 .get = wm8776_input_vol_get,
1053 .put = wm8776_input_vol_put,
1054 .tlv = { .p = wm8776_adc_db_scale },
1055 },
1056 {
1057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1058 .name = "Line Capture Switch",
1059 .info = snd_ctl_boolean_mono_info,
1060 .get = wm8776_input_mux_get,
1061 .put = wm8776_input_mux_put,
1062 .private_value = 1 << 0,
1063 },
1064 {
1065 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1066 .name = "Mic Capture Switch",
1067 .info = snd_ctl_boolean_mono_info,
1068 .get = wm8776_input_mux_get,
1069 .put = wm8776_input_mux_put,
1070 .private_value = 1 << 1,
1071 },
1072 WM8776_BIT_SWITCH("Front Mic Capture Switch",
1073 WM8776_ADCMUX, 1 << 2, 0, 0),
1074 WM8776_BIT_SWITCH("Aux Capture Switch",
1075 WM8776_ADCMUX, 1 << 3, 0, 0),
1076 {
1077 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1078 .name = "ADC Filter Capture Enum",
1079 .info = hpf_info,
1080 .get = hpf_get,
1081 .put = hpf_put,
1082 },
1083 {
1084 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1085 .name = "Level Control Capture Enum",
1086 .info = wm8776_level_control_info,
1087 .get = wm8776_level_control_get,
1088 .put = wm8776_level_control_put,
1089 .private_value = 0,
1090 },
1091 };
1092 static const struct snd_kcontrol_new hdav_slim_controls[] = {
1093 {
1094 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1095 .name = "HDMI Playback Switch",
1096 .info = snd_ctl_boolean_mono_info,
1097 .get = xonar_gpio_bit_switch_get,
1098 .put = xonar_gpio_bit_switch_put,
1099 .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT,
1100 },
1101 {
1102 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1103 .name = "Headphone Playback Volume",
1104 .info = wm8776_hp_vol_info,
1105 .get = wm8776_hp_vol_get,
1106 .put = wm8776_hp_vol_put,
1107 .tlv = { .p = wm8776_hp_db_scale },
1108 },
1109 WM8776_BIT_SWITCH("Headphone Playback Switch",
1110 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1111 {
1112 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1113 .name = "Input Capture Volume",
1114 .info = wm8776_input_vol_info,
1115 .get = wm8776_input_vol_get,
1116 .put = wm8776_input_vol_put,
1117 .tlv = { .p = wm8776_adc_db_scale },
1118 },
1119 WM8776_BIT_SWITCH("Mic Capture Switch",
1120 WM8776_ADCMUX, 1 << 0, 0, 0),
1121 WM8776_BIT_SWITCH("Aux Capture Switch",
1122 WM8776_ADCMUX, 1 << 1, 0, 0),
1123 {
1124 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1125 .name = "ADC Filter Capture Enum",
1126 .info = hpf_info,
1127 .get = hpf_get,
1128 .put = hpf_put,
1129 },
1130 {
1131 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1132 .name = "Level Control Capture Enum",
1133 .info = wm8776_level_control_info,
1134 .get = wm8776_level_control_get,
1135 .put = wm8776_level_control_put,
1136 .private_value = 0,
1137 },
1138 };
1139 static const struct snd_kcontrol_new lc_controls[] = {
1140 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
1141 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1142 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
1143 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
1144 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1145 LC_CONTROL_LIMITER),
1146 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
1147 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1148 LC_CONTROL_LIMITER),
1149 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
1150 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
1151 LC_CONTROL_LIMITER),
1152 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
1153 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
1154 LC_CONTROL_LIMITER,
1155 wm8776_maxatten_lim_db_scale),
1156 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
1157 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1158 LC_CONTROL_ALC, wm8776_lct_db_scale),
1159 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
1160 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1161 LC_CONTROL_ALC),
1162 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1163 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1164 LC_CONTROL_ALC),
1165 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
1166 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
1167 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
1168 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1169 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1170 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1171 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1172 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1173 LC_CONTROL_ALC),
1174 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1175 WM8776_NOISEGATE, WM8776_NGAT, 0,
1176 LC_CONTROL_ALC),
1177 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1178 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1179 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1180 };
1181
1182 static int add_lc_controls(struct oxygen *chip)
1183 {
1184 struct xonar_wm87x6 *data = chip->model_data;
1185 unsigned int i;
1186 struct snd_kcontrol *ctl;
1187 int err;
1188
1189 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1190 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1191 ctl = snd_ctl_new1(&lc_controls[i], chip);
1192 if (!ctl)
1193 return -ENOMEM;
1194 err = snd_ctl_add(chip->card, ctl);
1195 if (err < 0)
1196 return err;
1197 data->lc_controls[i] = ctl;
1198 }
1199 return 0;
1200 }
1201
1202 static int xonar_ds_mixer_init(struct oxygen *chip)
1203 {
1204 struct xonar_wm87x6 *data = chip->model_data;
1205 unsigned int i;
1206 struct snd_kcontrol *ctl;
1207 int err;
1208
1209 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1210 ctl = snd_ctl_new1(&ds_controls[i], chip);
1211 if (!ctl)
1212 return -ENOMEM;
1213 err = snd_ctl_add(chip->card, ctl);
1214 if (err < 0)
1215 return err;
1216 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1217 data->line_adcmux_control = ctl;
1218 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1219 data->mic_adcmux_control = ctl;
1220 }
1221 if (!data->line_adcmux_control || !data->mic_adcmux_control)
1222 return -ENXIO;
1223
1224 return add_lc_controls(chip);
1225 }
1226
1227 static int xonar_hdav_slim_mixer_init(struct oxygen *chip)
1228 {
1229 unsigned int i;
1230 struct snd_kcontrol *ctl;
1231 int err;
1232
1233 for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) {
1234 ctl = snd_ctl_new1(&hdav_slim_controls[i], chip);
1235 if (!ctl)
1236 return -ENOMEM;
1237 err = snd_ctl_add(chip->card, ctl);
1238 if (err < 0)
1239 return err;
1240 }
1241
1242 return add_lc_controls(chip);
1243 }
1244
1245 static void dump_wm8776_registers(struct oxygen *chip,
1246 struct snd_info_buffer *buffer)
1247 {
1248 struct xonar_wm87x6 *data = chip->model_data;
1249 unsigned int i;
1250
1251 snd_iprintf(buffer, "\nWM8776:\n00:");
1252 for (i = 0; i < 0x10; ++i)
1253 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1254 snd_iprintf(buffer, "\n10:");
1255 for (i = 0x10; i < 0x17; ++i)
1256 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1257 snd_iprintf(buffer, "\n");
1258 }
1259
1260 static void dump_wm87x6_registers(struct oxygen *chip,
1261 struct snd_info_buffer *buffer)
1262 {
1263 struct xonar_wm87x6 *data = chip->model_data;
1264 unsigned int i;
1265
1266 dump_wm8776_registers(chip, buffer);
1267 snd_iprintf(buffer, "\nWM8766:\n00:");
1268 for (i = 0; i < 0x10; ++i)
1269 snd_iprintf(buffer, " %03x", data->wm8766_regs[i]);
1270 snd_iprintf(buffer, "\n");
1271 }
1272
1273 static const struct oxygen_model model_xonar_ds = {
1274 .shortname = "Xonar DS",
1275 .longname = "Asus Virtuoso 66",
1276 .chip = "AV200",
1277 .init = xonar_ds_init,
1278 .mixer_init = xonar_ds_mixer_init,
1279 .cleanup = xonar_ds_cleanup,
1280 .suspend = xonar_ds_suspend,
1281 .resume = xonar_ds_resume,
1282 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1283 .set_dac_params = set_wm87x6_dac_params,
1284 .set_adc_params = set_wm8776_adc_params,
1285 .update_dac_volume = update_wm87x6_volume,
1286 .update_dac_mute = update_wm87x6_mute,
1287 .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1288 .gpio_changed = xonar_ds_gpio_changed,
1289 .dump_registers = dump_wm87x6_registers,
1290 .dac_tlv = wm87x6_dac_db_scale,
1291 .model_data_size = sizeof(struct xonar_wm87x6),
1292 .device_config = PLAYBACK_0_TO_I2S |
1293 PLAYBACK_1_TO_SPDIF |
1294 CAPTURE_0_FROM_I2S_1,
1295 .dac_channels_pcm = 8,
1296 .dac_channels_mixer = 8,
1297 .dac_volume_min = 255 - 2*60,
1298 .dac_volume_max = 255,
1299 .function_flags = OXYGEN_FUNCTION_SPI,
1300 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1301 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1302 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1303 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1304 };
1305
1306 static const struct oxygen_model model_xonar_hdav_slim = {
1307 .shortname = "Xonar HDAV1.3 Slim",
1308 .longname = "Asus Virtuoso 200",
1309 .chip = "AV200",
1310 .init = xonar_hdav_slim_init,
1311 .mixer_init = xonar_hdav_slim_mixer_init,
1312 .cleanup = xonar_hdav_slim_cleanup,
1313 .suspend = xonar_hdav_slim_suspend,
1314 .resume = xonar_hdav_slim_resume,
1315 .pcm_hardware_filter = xonar_hdav_slim_hardware_filter,
1316 .set_dac_params = set_hdav_slim_dac_params,
1317 .set_adc_params = set_wm8776_adc_params,
1318 .update_dac_volume = update_wm8776_volume,
1319 .update_dac_mute = update_wm8776_mute,
1320 .uart_input = xonar_hdmi_uart_input,
1321 .dump_registers = dump_wm8776_registers,
1322 .dac_tlv = wm87x6_dac_db_scale,
1323 .model_data_size = sizeof(struct xonar_wm87x6),
1324 .device_config = PLAYBACK_0_TO_I2S |
1325 PLAYBACK_1_TO_SPDIF |
1326 CAPTURE_0_FROM_I2S_1,
1327 .dac_channels_pcm = 8,
1328 .dac_channels_mixer = 2,
1329 .dac_volume_min = 255 - 2*60,
1330 .dac_volume_max = 255,
1331 .function_flags = OXYGEN_FUNCTION_2WIRE,
1332 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1333 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1334 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1335 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1336 };
1337
1338 int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1339 const struct pci_device_id *id)
1340 {
1341 switch (id->subdevice) {
1342 case 0x838e:
1343 chip->model = model_xonar_ds;
1344 break;
1345 case 0x835e:
1346 chip->model = model_xonar_hdav_slim;
1347 break;
1348 default:
1349 return -EINVAL;
1350 }
1351 return 0;
1352 }
This page took 0.092212 seconds and 5 git commands to generate.