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