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