aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/xonar_wm87x6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/oxygen/xonar_wm87x6.c')
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c412
1 files changed, 353 insertions, 59 deletions
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index b82c1cfa96f5..42d1ab136217 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * card driver for models with WM8776/WM8766 DACs (Xonar DS) 2 * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim)
3 * 3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * 5 *
@@ -22,19 +22,49 @@
22 * 22 *
23 * CMI8788: 23 * CMI8788:
24 * 24 *
25 * SPI 0 -> WM8766 (surround, center/LFE, back) 25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input) 26 * SPI 1 -> WM8776 (front, input)
27 * 27 *
28 * GPIO 4 <- headphone detect 28 * GPIO 4 <- headphone detect, 0 = plugged
29 * GPIO 6 -> route input jack to input 1/2 (1/0) 29 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
30 * GPIO 7 -> enable output to speakers 30 * GPIO 7 -> enable output to front L/R speaker channels
31 * GPIO 8 -> enable output to speakers 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
32 */ 60 */
33 61
34#include <linux/pci.h> 62#include <linux/pci.h>
35#include <linux/delay.h> 63#include <linux/delay.h>
36#include <sound/control.h> 64#include <sound/control.h>
37#include <sound/core.h> 65#include <sound/core.h>
66#include <sound/info.h>
67#include <sound/jack.h>
38#include <sound/pcm.h> 68#include <sound/pcm.h>
39#include <sound/pcm_params.h> 69#include <sound/pcm_params.h>
40#include <sound/tlv.h> 70#include <sound/tlv.h>
@@ -44,7 +74,15 @@
44 74
45#define GPIO_DS_HP_DETECT 0x0010 75#define GPIO_DS_HP_DETECT 0x0010
46#define GPIO_DS_INPUT_ROUTE 0x0040 76#define GPIO_DS_INPUT_ROUTE 0x0040
47#define GPIO_DS_OUTPUT_ENABLE 0x0180 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 */
48 86
49#define LC_CONTROL_LIMITER 0x40000000 87#define LC_CONTROL_LIMITER 0x40000000
50#define LC_CONTROL_ALC 0x20000000 88#define LC_CONTROL_ALC 0x20000000
@@ -56,19 +94,38 @@ struct xonar_wm87x6 {
56 struct snd_kcontrol *line_adcmux_control; 94 struct snd_kcontrol *line_adcmux_control;
57 struct snd_kcontrol *mic_adcmux_control; 95 struct snd_kcontrol *mic_adcmux_control;
58 struct snd_kcontrol *lc_controls[13]; 96 struct snd_kcontrol *lc_controls[13];
97 struct snd_jack *hp_jack;
98 struct xonar_hdmi hdmi;
59}; 99};
60 100
61static void wm8776_write(struct oxygen *chip, 101static void wm8776_write_spi(struct oxygen *chip,
62 unsigned int reg, unsigned int value) 102 unsigned int reg, unsigned int value)
63{ 103{
64 struct xonar_wm87x6 *data = chip->model_data;
65
66 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 104 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
67 OXYGEN_SPI_DATA_LENGTH_2 | 105 OXYGEN_SPI_DATA_LENGTH_2 |
68 OXYGEN_SPI_CLOCK_160 | 106 OXYGEN_SPI_CLOCK_160 |
69 (1 << OXYGEN_SPI_CODEC_SHIFT) | 107 (1 << OXYGEN_SPI_CODEC_SHIFT) |
70 OXYGEN_SPI_CEN_LATCH_CLOCK_LO, 108 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
71 (reg << 9) | value); 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);
72 if (reg < ARRAY_SIZE(data->wm8776_regs)) { 129 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
73 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) 130 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
74 value &= ~WM8776_UPDATE; 131 value &= ~WM8776_UPDATE;
@@ -97,8 +154,12 @@ static void wm8766_write(struct oxygen *chip,
97 (0 << OXYGEN_SPI_CODEC_SHIFT) | 154 (0 << OXYGEN_SPI_CODEC_SHIFT) |
98 OXYGEN_SPI_CEN_LATCH_CLOCK_LO, 155 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
99 (reg << 9) | value); 156 (reg << 9) | value);
100 if (reg < ARRAY_SIZE(data->wm8766_regs)) 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;
101 data->wm8766_regs[reg] = value; 161 data->wm8766_regs[reg] = value;
162 }
102} 163}
103 164
104static void wm8766_write_cached(struct oxygen *chip, 165static void wm8766_write_cached(struct oxygen *chip,
@@ -107,12 +168,8 @@ static void wm8766_write_cached(struct oxygen *chip,
107 struct xonar_wm87x6 *data = chip->model_data; 168 struct xonar_wm87x6 *data = chip->model_data;
108 169
109 if (reg >= ARRAY_SIZE(data->wm8766_regs) || 170 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
110 value != data->wm8766_regs[reg]) { 171 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); 172 wm8766_write(chip, reg, value);
115 }
116} 173}
117 174
118static void wm8776_registers_init(struct oxygen *chip) 175static void wm8776_registers_init(struct oxygen *chip)
@@ -141,7 +198,10 @@ static void wm8776_registers_init(struct oxygen *chip)
141 198
142static void wm8766_registers_init(struct oxygen *chip) 199static void wm8766_registers_init(struct oxygen *chip)
143{ 200{
201 struct xonar_wm87x6 *data = chip->model_data;
202
144 wm8766_write(chip, WM8766_RESET, 0); 203 wm8766_write(chip, WM8766_RESET, 0);
204 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
145 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); 205 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
146 wm8766_write(chip, WM8766_DAC_CTRL2, 206 wm8766_write(chip, WM8766_DAC_CTRL2,
147 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); 207 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
@@ -170,6 +230,40 @@ static void wm8776_init(struct oxygen *chip)
170 wm8776_registers_init(chip); 230 wm8776_registers_init(chip);
171} 231}
172 232
233static void wm8766_init(struct oxygen *chip)
234{
235 struct xonar_wm87x6 *data = chip->model_data;
236
237 data->wm8766_regs[WM8766_DAC_CTRL] =
238 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
239 wm8766_registers_init(chip);
240}
241
242static void xonar_ds_handle_hp_jack(struct oxygen *chip)
243{
244 struct xonar_wm87x6 *data = chip->model_data;
245 bool hp_plugged;
246 unsigned int reg;
247
248 mutex_lock(&chip->mutex);
249
250 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
251 GPIO_DS_HP_DETECT);
252
253 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
254 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
255 GPIO_DS_OUTPUT_FRONTLR);
256
257 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
258 if (hp_plugged)
259 reg |= WM8766_MUTEALL;
260 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
261
262 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
263
264 mutex_unlock(&chip->mutex);
265}
266
173static void xonar_ds_init(struct oxygen *chip) 267static void xonar_ds_init(struct oxygen *chip)
174{ 268{
175 struct xonar_wm87x6 *data = chip->model_data; 269 struct xonar_wm87x6 *data = chip->model_data;
@@ -178,36 +272,85 @@ static void xonar_ds_init(struct oxygen *chip)
178 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; 272 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
179 273
180 wm8776_init(chip); 274 wm8776_init(chip);
181 wm8766_registers_init(chip); 275 wm8766_init(chip);
182 276
183 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, 277 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
184 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); 278 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
279 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
280 GPIO_DS_HP_DETECT);
185 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); 281 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
186 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); 282 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
187 chip->interrupt_mask |= OXYGEN_INT_GPIO; 283 chip->interrupt_mask |= OXYGEN_INT_GPIO;
188 284
189 xonar_enable_output(chip); 285 xonar_enable_output(chip);
190 286
287 snd_jack_new(chip->card, "Headphone",
288 SND_JACK_HEADPHONE, &data->hp_jack);
289 xonar_ds_handle_hp_jack(chip);
290
191 snd_component_add(chip->card, "WM8776"); 291 snd_component_add(chip->card, "WM8776");
192 snd_component_add(chip->card, "WM8766"); 292 snd_component_add(chip->card, "WM8766");
193} 293}
194 294
295static void xonar_hdav_slim_init(struct oxygen *chip)
296{
297 struct xonar_wm87x6 *data = chip->model_data;
298
299 data->generic.anti_pop_delay = 300;
300 data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE;
301
302 wm8776_init(chip);
303
304 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
305 GPIO_SLIM_HDMI_DISABLE |
306 GPIO_SLIM_FIRMWARE_CLK |
307 GPIO_SLIM_FIRMWARE_DATA);
308
309 xonar_hdmi_init(chip, &data->hdmi);
310 xonar_enable_output(chip);
311
312 snd_component_add(chip->card, "WM8776");
313}
314
195static void xonar_ds_cleanup(struct oxygen *chip) 315static void xonar_ds_cleanup(struct oxygen *chip)
196{ 316{
197 xonar_disable_output(chip); 317 xonar_disable_output(chip);
198 wm8776_write(chip, WM8776_RESET, 0); 318 wm8776_write(chip, WM8776_RESET, 0);
199} 319}
200 320
321static void xonar_hdav_slim_cleanup(struct oxygen *chip)
322{
323 xonar_hdmi_cleanup(chip);
324 xonar_disable_output(chip);
325 wm8776_write(chip, WM8776_RESET, 0);
326 msleep(2);
327}
328
201static void xonar_ds_suspend(struct oxygen *chip) 329static void xonar_ds_suspend(struct oxygen *chip)
202{ 330{
203 xonar_ds_cleanup(chip); 331 xonar_ds_cleanup(chip);
204} 332}
205 333
334static void xonar_hdav_slim_suspend(struct oxygen *chip)
335{
336 xonar_hdav_slim_cleanup(chip);
337}
338
206static void xonar_ds_resume(struct oxygen *chip) 339static void xonar_ds_resume(struct oxygen *chip)
207{ 340{
208 wm8776_registers_init(chip); 341 wm8776_registers_init(chip);
209 wm8766_registers_init(chip); 342 wm8766_registers_init(chip);
210 xonar_enable_output(chip); 343 xonar_enable_output(chip);
344 xonar_ds_handle_hp_jack(chip);
345}
346
347static void xonar_hdav_slim_resume(struct oxygen *chip)
348{
349 struct xonar_wm87x6 *data = chip->model_data;
350
351 wm8776_registers_init(chip);
352 xonar_hdmi_resume(chip, &data->hdmi);
353 xonar_enable_output(chip);
211} 354}
212 355
213static void wm8776_adc_hardware_filter(unsigned int channel, 356static void wm8776_adc_hardware_filter(unsigned int channel,
@@ -224,6 +367,13 @@ static void wm8776_adc_hardware_filter(unsigned int channel,
224 } 367 }
225} 368}
226 369
370static void xonar_hdav_slim_hardware_filter(unsigned int channel,
371 struct snd_pcm_hardware *hardware)
372{
373 wm8776_adc_hardware_filter(channel, hardware);
374 xonar_hdmi_pcm_hardware_filter(channel, hardware);
375}
376
227static void set_wm87x6_dac_params(struct oxygen *chip, 377static void set_wm87x6_dac_params(struct oxygen *chip,
228 struct snd_pcm_hw_params *params) 378 struct snd_pcm_hw_params *params)
229{ 379{
@@ -240,6 +390,14 @@ static void set_wm8776_adc_params(struct oxygen *chip,
240 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg); 390 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
241} 391}
242 392
393static void set_hdav_slim_dac_params(struct oxygen *chip,
394 struct snd_pcm_hw_params *params)
395{
396 struct xonar_wm87x6 *data = chip->model_data;
397
398 xonar_set_hdmi_params(chip, &data->hdmi, params);
399}
400
243static void update_wm8776_volume(struct oxygen *chip) 401static void update_wm8776_volume(struct oxygen *chip)
244{ 402{
245 struct xonar_wm87x6 *data = chip->model_data; 403 struct xonar_wm87x6 *data = chip->model_data;
@@ -323,12 +481,27 @@ static void update_wm87x6_mute(struct oxygen *chip)
323 (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); 481 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
324} 482}
325 483
326static void xonar_ds_gpio_changed(struct oxygen *chip) 484static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
327{ 485{
328 u16 bits; 486 struct xonar_wm87x6 *data = chip->model_data;
487 unsigned int reg;
488
489 /*
490 * The WM8766 can mix left and right channels, but this setting
491 * applies to all three stereo pairs.
492 */
493 reg = data->wm8766_regs[WM8766_DAC_CTRL] &
494 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
495 if (mixed)
496 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
497 else
498 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
499 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
500}
329 501
330 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); 502static void xonar_ds_gpio_changed(struct oxygen *chip)
331 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT)); 503{
504 xonar_ds_handle_hp_jack(chip);
332} 505}
333 506
334static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, 507static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
@@ -404,11 +577,6 @@ static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
404 const char *const *names; 577 const char *const *names;
405 578
406 max = (ctl->private_value >> 12) & 0xf; 579 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) { 580 switch ((ctl->private_value >> 24) & 0x1f) {
413 case WM8776_ALCCTRL2: 581 case WM8776_ALCCTRL2:
414 names = hld; 582 names = hld;
@@ -432,8 +600,7 @@ static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
432 default: 600 default:
433 return -ENXIO; 601 return -ENXIO;
434 } 602 }
435 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); 603 return snd_ctl_enum_info(info, 1, max + 1, names);
436 return 0;
437} 604}
438 605
439static int wm8776_field_volume_info(struct snd_kcontrol *ctl, 606static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
@@ -690,13 +857,8 @@ static int wm8776_level_control_info(struct snd_kcontrol *ctl,
690 static const char *const names[3] = { 857 static const char *const names[3] = {
691 "None", "Peak Limiter", "Automatic Level Control" 858 "None", "Peak Limiter", "Automatic Level Control"
692 }; 859 };
693 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 860
694 info->count = 1; 861 return snd_ctl_enum_info(info, 1, 3, names);
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} 862}
701 863
702static int wm8776_level_control_get(struct snd_kcontrol *ctl, 864static int wm8776_level_control_get(struct snd_kcontrol *ctl,
@@ -782,13 +944,7 @@ static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
782 "None", "High-pass Filter" 944 "None", "High-pass Filter"
783 }; 945 };
784 946
785 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 947 return snd_ctl_enum_info(info, 1, 2, names);
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} 948}
793 949
794static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) 950static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
@@ -896,7 +1052,57 @@ static const struct snd_kcontrol_new ds_controls[] = {
896 .put = wm8776_input_mux_put, 1052 .put = wm8776_input_mux_put,
897 .private_value = 1 << 1, 1053 .private_value = 1 << 1,
898 }, 1054 },
899 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0), 1055 WM8776_BIT_SWITCH("Front Mic Capture Switch",
1056 WM8776_ADCMUX, 1 << 2, 0, 0),
1057 WM8776_BIT_SWITCH("Aux Capture Switch",
1058 WM8776_ADCMUX, 1 << 3, 0, 0),
1059 {
1060 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1061 .name = "ADC Filter Capture Enum",
1062 .info = hpf_info,
1063 .get = hpf_get,
1064 .put = hpf_put,
1065 },
1066 {
1067 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1068 .name = "Level Control Capture Enum",
1069 .info = wm8776_level_control_info,
1070 .get = wm8776_level_control_get,
1071 .put = wm8776_level_control_put,
1072 .private_value = 0,
1073 },
1074};
1075static const struct snd_kcontrol_new hdav_slim_controls[] = {
1076 {
1077 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1078 .name = "HDMI Playback Switch",
1079 .info = snd_ctl_boolean_mono_info,
1080 .get = xonar_gpio_bit_switch_get,
1081 .put = xonar_gpio_bit_switch_put,
1082 .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT,
1083 },
1084 {
1085 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1086 .name = "Headphone Playback Volume",
1087 .info = wm8776_hp_vol_info,
1088 .get = wm8776_hp_vol_get,
1089 .put = wm8776_hp_vol_put,
1090 .tlv = { .p = wm8776_hp_db_scale },
1091 },
1092 WM8776_BIT_SWITCH("Headphone Playback Switch",
1093 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1094 {
1095 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1096 .name = "Input Capture Volume",
1097 .info = wm8776_input_vol_info,
1098 .get = wm8776_input_vol_get,
1099 .put = wm8776_input_vol_put,
1100 .tlv = { .p = wm8776_adc_db_scale },
1101 },
1102 WM8776_BIT_SWITCH("Mic Capture Switch",
1103 WM8776_ADCMUX, 1 << 0, 0, 0),
1104 WM8776_BIT_SWITCH("Aux Capture Switch",
1105 WM8776_ADCMUX, 1 << 1, 0, 0),
900 { 1106 {
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1107 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .name = "ADC Filter Capture Enum", 1108 .name = "ADC Filter Capture Enum",
@@ -956,10 +1162,23 @@ static const struct snd_kcontrol_new lc_controls[] = {
956 LC_CONTROL_ALC, wm8776_ngth_db_scale), 1162 LC_CONTROL_ALC, wm8776_ngth_db_scale),
957}; 1163};
958 1164
959static int xonar_ds_control_filter(struct snd_kcontrol_new *template) 1165static int add_lc_controls(struct oxygen *chip)
960{ 1166{
961 if (!strncmp(template->name, "CD Capture ", 11)) 1167 struct xonar_wm87x6 *data = chip->model_data;
962 return 1; /* no CD input */ 1168 unsigned int i;
1169 struct snd_kcontrol *ctl;
1170 int err;
1171
1172 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1173 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1174 ctl = snd_ctl_new1(&lc_controls[i], chip);
1175 if (!ctl)
1176 return -ENOMEM;
1177 err = snd_ctl_add(chip->card, ctl);
1178 if (err < 0)
1179 return err;
1180 data->lc_controls[i] = ctl;
1181 }
963 return 0; 1182 return 0;
964} 1183}
965 1184
@@ -984,45 +1203,117 @@ static int xonar_ds_mixer_init(struct oxygen *chip)
984 } 1203 }
985 if (!data->line_adcmux_control || !data->mic_adcmux_control) 1204 if (!data->line_adcmux_control || !data->mic_adcmux_control)
986 return -ENXIO; 1205 return -ENXIO;
987 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); 1206
988 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { 1207 return add_lc_controls(chip);
989 ctl = snd_ctl_new1(&lc_controls[i], chip); 1208}
1209
1210static int xonar_hdav_slim_mixer_init(struct oxygen *chip)
1211{
1212 unsigned int i;
1213 struct snd_kcontrol *ctl;
1214 int err;
1215
1216 for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) {
1217 ctl = snd_ctl_new1(&hdav_slim_controls[i], chip);
990 if (!ctl) 1218 if (!ctl)
991 return -ENOMEM; 1219 return -ENOMEM;
992 err = snd_ctl_add(chip->card, ctl); 1220 err = snd_ctl_add(chip->card, ctl);
993 if (err < 0) 1221 if (err < 0)
994 return err; 1222 return err;
995 data->lc_controls[i] = ctl;
996 } 1223 }
997 return 0; 1224
1225 return add_lc_controls(chip);
1226}
1227
1228static void dump_wm8776_registers(struct oxygen *chip,
1229 struct snd_info_buffer *buffer)
1230{
1231 struct xonar_wm87x6 *data = chip->model_data;
1232 unsigned int i;
1233
1234 snd_iprintf(buffer, "\nWM8776:\n00:");
1235 for (i = 0; i < 0x10; ++i)
1236 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1237 snd_iprintf(buffer, "\n10:");
1238 for (i = 0x10; i < 0x17; ++i)
1239 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1240 snd_iprintf(buffer, "\n");
1241}
1242
1243static void dump_wm87x6_registers(struct oxygen *chip,
1244 struct snd_info_buffer *buffer)
1245{
1246 struct xonar_wm87x6 *data = chip->model_data;
1247 unsigned int i;
1248
1249 dump_wm8776_registers(chip, buffer);
1250 snd_iprintf(buffer, "\nWM8766:\n00:");
1251 for (i = 0; i < 0x10; ++i)
1252 snd_iprintf(buffer, " %03x", data->wm8766_regs[i]);
1253 snd_iprintf(buffer, "\n");
998} 1254}
999 1255
1000static const struct oxygen_model model_xonar_ds = { 1256static const struct oxygen_model model_xonar_ds = {
1001 .shortname = "Xonar DS", 1257 .shortname = "Xonar DS",
1002 .longname = "Asus Virtuoso 200", 1258 .longname = "Asus Virtuoso 66",
1003 .chip = "AV200", 1259 .chip = "AV200",
1004 .init = xonar_ds_init, 1260 .init = xonar_ds_init,
1005 .control_filter = xonar_ds_control_filter,
1006 .mixer_init = xonar_ds_mixer_init, 1261 .mixer_init = xonar_ds_mixer_init,
1007 .cleanup = xonar_ds_cleanup, 1262 .cleanup = xonar_ds_cleanup,
1008 .suspend = xonar_ds_suspend, 1263 .suspend = xonar_ds_suspend,
1009 .resume = xonar_ds_resume, 1264 .resume = xonar_ds_resume,
1010 .pcm_hardware_filter = wm8776_adc_hardware_filter, 1265 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1011 .get_i2s_mclk = oxygen_default_i2s_mclk,
1012 .set_dac_params = set_wm87x6_dac_params, 1266 .set_dac_params = set_wm87x6_dac_params,
1013 .set_adc_params = set_wm8776_adc_params, 1267 .set_adc_params = set_wm8776_adc_params,
1014 .update_dac_volume = update_wm87x6_volume, 1268 .update_dac_volume = update_wm87x6_volume,
1015 .update_dac_mute = update_wm87x6_mute, 1269 .update_dac_mute = update_wm87x6_mute,
1270 .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1016 .gpio_changed = xonar_ds_gpio_changed, 1271 .gpio_changed = xonar_ds_gpio_changed,
1272 .dump_registers = dump_wm87x6_registers,
1017 .dac_tlv = wm87x6_dac_db_scale, 1273 .dac_tlv = wm87x6_dac_db_scale,
1018 .model_data_size = sizeof(struct xonar_wm87x6), 1274 .model_data_size = sizeof(struct xonar_wm87x6),
1019 .device_config = PLAYBACK_0_TO_I2S | 1275 .device_config = PLAYBACK_0_TO_I2S |
1020 PLAYBACK_1_TO_SPDIF | 1276 PLAYBACK_1_TO_SPDIF |
1021 CAPTURE_0_FROM_I2S_1, 1277 CAPTURE_0_FROM_I2S_1,
1022 .dac_channels = 8, 1278 .dac_channels_pcm = 8,
1279 .dac_channels_mixer = 8,
1023 .dac_volume_min = 255 - 2*60, 1280 .dac_volume_min = 255 - 2*60,
1024 .dac_volume_max = 255, 1281 .dac_volume_max = 255,
1025 .function_flags = OXYGEN_FUNCTION_SPI, 1282 .function_flags = OXYGEN_FUNCTION_SPI,
1283 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1284 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1285 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1286 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1287};
1288
1289static const struct oxygen_model model_xonar_hdav_slim = {
1290 .shortname = "Xonar HDAV1.3 Slim",
1291 .longname = "Asus Virtuoso 200",
1292 .chip = "AV200",
1293 .init = xonar_hdav_slim_init,
1294 .mixer_init = xonar_hdav_slim_mixer_init,
1295 .cleanup = xonar_hdav_slim_cleanup,
1296 .suspend = xonar_hdav_slim_suspend,
1297 .resume = xonar_hdav_slim_resume,
1298 .pcm_hardware_filter = xonar_hdav_slim_hardware_filter,
1299 .set_dac_params = set_hdav_slim_dac_params,
1300 .set_adc_params = set_wm8776_adc_params,
1301 .update_dac_volume = update_wm8776_volume,
1302 .update_dac_mute = update_wm8776_mute,
1303 .uart_input = xonar_hdmi_uart_input,
1304 .dump_registers = dump_wm8776_registers,
1305 .dac_tlv = wm87x6_dac_db_scale,
1306 .model_data_size = sizeof(struct xonar_wm87x6),
1307 .device_config = PLAYBACK_0_TO_I2S |
1308 PLAYBACK_1_TO_SPDIF |
1309 CAPTURE_0_FROM_I2S_1,
1310 .dac_channels_pcm = 8,
1311 .dac_channels_mixer = 2,
1312 .dac_volume_min = 255 - 2*60,
1313 .dac_volume_max = 255,
1314 .function_flags = OXYGEN_FUNCTION_2WIRE,
1315 .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1316 .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1026 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 1317 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1027 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 1318 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1028}; 1319};
@@ -1034,6 +1325,9 @@ int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1034 case 0x838e: 1325 case 0x838e:
1035 chip->model = model_xonar_ds; 1326 chip->model = model_xonar_ds;
1036 break; 1327 break;
1328 case 0x835e:
1329 chip->model = model_xonar_hdav_slim;
1330 break;
1037 default: 1331 default:
1038 return -EINVAL; 1332 return -EINVAL;
1039 } 1333 }