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