2 * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim)
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
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.
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.
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/>.
25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input)
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
37 * input 3 <- front mic
47 * I²C <-> WM8776 (addr 0011010)
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
54 * UART <-> HDMI controller
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>
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
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
85 #define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */
87 #define LC_CONTROL_LIMITER 0x40000000
88 #define LC_CONTROL_ALC 0x20000000
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
;
101 static void wm8776_write_spi(struct oxygen
*chip
,
102 unsigned int reg
, unsigned int value
)
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
,
112 static void wm8776_write_i2c(struct oxygen
*chip
,
113 unsigned int reg
, unsigned int value
)
115 oxygen_write_i2c(chip
, I2C_DEVICE_WM8776
,
116 (reg
<< 1) | (value
>> 8), value
);
119 static void wm8776_write(struct oxygen
*chip
,
120 unsigned int reg
, unsigned int value
)
122 struct xonar_wm87x6
*data
= chip
->model_data
;
124 if ((chip
->model
.function_flags
& OXYGEN_FUNCTION_2WIRE_SPI_MASK
) ==
126 wm8776_write_spi(chip
, reg
, value
);
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
;
136 static void wm8776_write_cached(struct oxygen
*chip
,
137 unsigned int reg
, unsigned int value
)
139 struct xonar_wm87x6
*data
= chip
->model_data
;
141 if (reg
>= ARRAY_SIZE(data
->wm8776_regs
) ||
142 value
!= data
->wm8776_regs
[reg
])
143 wm8776_write(chip
, reg
, value
);
146 static void wm8766_write(struct oxygen
*chip
,
147 unsigned int reg
, unsigned int value
)
149 struct xonar_wm87x6
*data
= chip
->model_data
;
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
,
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
;
165 static void wm8766_write_cached(struct oxygen
*chip
,
166 unsigned int reg
, unsigned int value
)
168 struct xonar_wm87x6
*data
= chip
->model_data
;
170 if (reg
>= ARRAY_SIZE(data
->wm8766_regs
) ||
171 value
!= data
->wm8766_regs
[reg
])
172 wm8766_write(chip
, reg
, value
);
175 static void wm8776_registers_init(struct oxygen
*chip
)
177 struct xonar_wm87x6
*data
= chip
->model_data
;
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
] |
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
);
200 static void wm8766_registers_init(struct oxygen
*chip
)
202 struct xonar_wm87x6
*data
= chip
->model_data
;
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
);
217 static void wm8776_init(struct oxygen
*chip
)
219 struct xonar_wm87x6
*data
= chip
->model_data
;
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
);
234 static void wm8766_init(struct oxygen
*chip
)
236 struct xonar_wm87x6
*data
= chip
->model_data
;
238 data
->wm8766_regs
[WM8766_DAC_CTRL
] =
239 WM8766_PL_LEFT_LEFT
| WM8766_PL_RIGHT_RIGHT
;
240 wm8766_registers_init(chip
);
243 static void xonar_ds_handle_hp_jack(struct oxygen
*chip
)
245 struct xonar_wm87x6
*data
= chip
->model_data
;
249 mutex_lock(&chip
->mutex
);
251 hp_plugged
= !(oxygen_read16(chip
, OXYGEN_GPIO_DATA
) &
254 oxygen_write16_masked(chip
, OXYGEN_GPIO_DATA
,
255 hp_plugged
? 0 : GPIO_DS_OUTPUT_FRONTLR
,
256 GPIO_DS_OUTPUT_FRONTLR
);
258 reg
= data
->wm8766_regs
[WM8766_DAC_CTRL
] & ~WM8766_MUTEALL
;
260 reg
|= WM8766_MUTEALL
;
261 wm8766_write_cached(chip
, WM8766_DAC_CTRL
, reg
);
263 snd_jack_report(data
->hp_jack
, hp_plugged
? SND_JACK_HEADPHONE
: 0);
265 mutex_unlock(&chip
->mutex
);
268 static void xonar_ds_init(struct oxygen
*chip
)
270 struct xonar_wm87x6
*data
= chip
->model_data
;
272 data
->generic
.anti_pop_delay
= 300;
273 data
->generic
.output_enable_bit
= GPIO_DS_OUTPUT_ENABLE
;
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
,
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
;
286 xonar_enable_output(chip
);
288 snd_jack_new(chip
->card
, "Headphone",
289 SND_JACK_HEADPHONE
, &data
->hp_jack
);
290 xonar_ds_handle_hp_jack(chip
);
292 snd_component_add(chip
->card
, "WM8776");
293 snd_component_add(chip
->card
, "WM8766");
296 static void xonar_hdav_slim_init(struct oxygen
*chip
)
298 struct xonar_wm87x6
*data
= chip
->model_data
;
300 data
->generic
.anti_pop_delay
= 300;
301 data
->generic
.output_enable_bit
= GPIO_SLIM_OUTPUT_ENABLE
;
305 oxygen_set_bits16(chip
, OXYGEN_GPIO_CONTROL
,
306 GPIO_SLIM_HDMI_DISABLE
|
307 GPIO_SLIM_FIRMWARE_CLK
|
308 GPIO_SLIM_FIRMWARE_DATA
);
310 xonar_hdmi_init(chip
, &data
->hdmi
);
311 xonar_enable_output(chip
);
313 snd_component_add(chip
->card
, "WM8776");
316 static void xonar_ds_cleanup(struct oxygen
*chip
)
318 xonar_disable_output(chip
);
319 wm8776_write(chip
, WM8776_RESET
, 0);
322 static void xonar_hdav_slim_cleanup(struct oxygen
*chip
)
324 xonar_hdmi_cleanup(chip
);
325 xonar_disable_output(chip
);
326 wm8776_write(chip
, WM8776_RESET
, 0);
330 static void xonar_ds_suspend(struct oxygen
*chip
)
332 xonar_ds_cleanup(chip
);
335 static void xonar_hdav_slim_suspend(struct oxygen
*chip
)
337 xonar_hdav_slim_cleanup(chip
);
340 static void xonar_ds_resume(struct oxygen
*chip
)
342 wm8776_registers_init(chip
);
343 wm8766_registers_init(chip
);
344 xonar_enable_output(chip
);
345 xonar_ds_handle_hp_jack(chip
);
348 static void xonar_hdav_slim_resume(struct oxygen
*chip
)
350 struct xonar_wm87x6
*data
= chip
->model_data
;
352 wm8776_registers_init(chip
);
353 xonar_hdmi_resume(chip
, &data
->hdmi
);
354 xonar_enable_output(chip
);
357 static void wm8776_adc_hardware_filter(unsigned int channel
,
358 struct snd_pcm_hardware
*hardware
)
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;
371 static void xonar_hdav_slim_hardware_filter(unsigned int channel
,
372 struct snd_pcm_hardware
*hardware
)
374 wm8776_adc_hardware_filter(channel
, hardware
);
375 xonar_hdmi_pcm_hardware_filter(channel
, hardware
);
378 static void set_wm87x6_dac_params(struct oxygen
*chip
,
379 struct snd_pcm_hw_params
*params
)
383 static void set_wm8776_adc_params(struct oxygen
*chip
,
384 struct snd_pcm_hw_params
*params
)
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
);
394 static void set_hdav_slim_dac_params(struct oxygen
*chip
,
395 struct snd_pcm_hw_params
*params
)
397 struct xonar_wm87x6
*data
= chip
->model_data
;
399 xonar_set_hdmi_params(chip
, &data
->hdmi
, params
);
402 static void update_wm8776_volume(struct oxygen
*chip
)
404 struct xonar_wm87x6
*data
= chip
->model_data
;
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];
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;
421 wm8776_write(chip
, WM8776_DACLVOL
, chip
->dac_volume
[0] |
422 ((to_change
& 2) ? 0 : WM8776_UPDATE
));
424 wm8776_write(chip
, WM8776_DACRVOL
,
425 chip
->dac_volume
[1] | WM8776_UPDATE
);
429 static void update_wm87x6_volume(struct oxygen
*chip
)
431 static const u8 wm8766_regs
[6] = {
432 WM8766_LDA1
, WM8766_RDA1
,
433 WM8766_LDA2
, WM8766_RDA2
,
434 WM8766_LDA3
, WM8766_RDA3
,
436 struct xonar_wm87x6
*data
= chip
->model_data
;
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]) {
447 for (i
= 0; i
< 6; ++i
)
448 if (chip
->dac_volume
[2] !=
449 data
->wm8766_regs
[wm8766_regs
[i
]])
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
]] =
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
));
472 static void update_wm8776_mute(struct oxygen
*chip
)
474 wm8776_write_cached(chip
, WM8776_DACMUTE
,
475 chip
->dac_mute
? WM8776_DMUTE
: 0);
478 static void update_wm87x6_mute(struct oxygen
*chip
)
480 update_wm8776_mute(chip
);
481 wm8766_write_cached(chip
, WM8766_DAC_CTRL2
, WM8766_ZCD
|
482 (chip
->dac_mute
? WM8766_DMUTE_MASK
: 0));
485 static void update_wm8766_center_lfe_mix(struct oxygen
*chip
, bool mixed
)
487 struct xonar_wm87x6
*data
= chip
->model_data
;
491 * The WM8766 can mix left and right channels, but this setting
492 * applies to all three stereo pairs.
494 reg
= data
->wm8766_regs
[WM8766_DAC_CTRL
] &
495 ~(WM8766_PL_LEFT_MASK
| WM8766_PL_RIGHT_MASK
);
497 reg
|= WM8766_PL_LEFT_LRMIX
| WM8766_PL_RIGHT_LRMIX
;
499 reg
|= WM8766_PL_LEFT_LEFT
| WM8766_PL_RIGHT_RIGHT
;
500 wm8766_write_cached(chip
, WM8766_DAC_CTRL
, reg
);
503 static void xonar_ds_gpio_changed(struct oxygen
*chip
)
505 xonar_ds_handle_hp_jack(chip
);
508 static int wm8776_bit_switch_get(struct snd_kcontrol
*ctl
,
509 struct snd_ctl_elem_value
*value
)
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;
517 value
->value
.integer
.value
[0] =
518 ((data
->wm8776_regs
[reg_index
] & bit
) != 0) ^ invert
;
522 static int wm8776_bit_switch_put(struct snd_kcontrol
*ctl
,
523 struct snd_ctl_elem_value
*value
)
525 struct oxygen
*chip
= ctl
->private_data
;
526 struct xonar_wm87x6
*data
= chip
->model_data
;
527 u16 bit
= ctl
->private_value
& 0xffff;
529 unsigned int reg_index
= (ctl
->private_value
>> 16) & 0xff;
530 bool invert
= (ctl
->private_value
>> 24) & 1;
533 mutex_lock(&chip
->mutex
);
534 reg_value
= data
->wm8776_regs
[reg_index
] & ~bit
;
535 if (value
->value
.integer
.value
[0] ^ invert
)
537 changed
= reg_value
!= data
->wm8776_regs
[reg_index
];
539 wm8776_write(chip
, reg_index
, reg_value
);
540 mutex_unlock(&chip
->mutex
);
544 static int wm8776_field_enum_info(struct snd_kcontrol
*ctl
,
545 struct snd_ctl_elem_info
*info
)
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",
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",
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",
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",
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",
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",
578 const char *const *names
;
580 max
= (ctl
->private_value
>> 12) & 0xf;
581 switch ((ctl
->private_value
>> 24) & 0x1f) {
582 case WM8776_ALCCTRL2
:
585 case WM8776_ALCCTRL3
:
586 if (((ctl
->private_value
>> 20) & 0xf) == 0) {
587 if (ctl
->private_value
& LC_CONTROL_LIMITER
)
592 if (ctl
->private_value
& LC_CONTROL_LIMITER
)
604 return snd_ctl_enum_info(info
, 1, max
+ 1, names
);
607 static int wm8776_field_volume_info(struct snd_kcontrol
*ctl
,
608 struct snd_ctl_elem_info
*info
)
610 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
612 info
->value
.integer
.min
= (ctl
->private_value
>> 8) & 0xf;
613 info
->value
.integer
.max
= (ctl
->private_value
>> 12) & 0xf;
617 static void wm8776_field_set_from_ctl(struct snd_kcontrol
*ctl
)
619 struct oxygen
*chip
= ctl
->private_data
;
620 struct xonar_wm87x6
*data
= chip
->model_data
;
621 unsigned int value
, reg_index
, mode
;
626 if ((data
->wm8776_regs
[WM8776_ALCCTRL1
] & WM8776_LCSEL_MASK
) ==
627 WM8776_LCSEL_LIMITER
)
628 mode
= LC_CONTROL_LIMITER
;
630 mode
= LC_CONTROL_ALC
;
631 if (!(ctl
->private_value
& mode
))
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;
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
);
650 static int wm8776_field_set(struct snd_kcontrol
*ctl
, unsigned int value
)
652 struct oxygen
*chip
= ctl
->private_data
;
656 min
= (ctl
->private_value
>> 8) & 0xf;
657 max
= (ctl
->private_value
>> 12) & 0xf;
658 if (value
< min
|| value
> max
)
660 mutex_lock(&chip
->mutex
);
661 changed
= value
!= (ctl
->private_value
& 0xf);
663 ctl
->private_value
= (ctl
->private_value
& ~0xf) | value
;
664 wm8776_field_set_from_ctl(ctl
);
666 mutex_unlock(&chip
->mutex
);
670 static int wm8776_field_enum_get(struct snd_kcontrol
*ctl
,
671 struct snd_ctl_elem_value
*value
)
673 value
->value
.enumerated
.item
[0] = ctl
->private_value
& 0xf;
677 static int wm8776_field_volume_get(struct snd_kcontrol
*ctl
,
678 struct snd_ctl_elem_value
*value
)
680 value
->value
.integer
.value
[0] = ctl
->private_value
& 0xf;
684 static int wm8776_field_enum_put(struct snd_kcontrol
*ctl
,
685 struct snd_ctl_elem_value
*value
)
687 return wm8776_field_set(ctl
, value
->value
.enumerated
.item
[0]);
690 static int wm8776_field_volume_put(struct snd_kcontrol
*ctl
,
691 struct snd_ctl_elem_value
*value
)
693 return wm8776_field_set(ctl
, value
->value
.integer
.value
[0]);
696 static int wm8776_hp_vol_info(struct snd_kcontrol
*ctl
,
697 struct snd_ctl_elem_info
*info
)
699 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
701 info
->value
.integer
.min
= 0x79 - 60;
702 info
->value
.integer
.max
= 0x7f;
706 static int wm8776_hp_vol_get(struct snd_kcontrol
*ctl
,
707 struct snd_ctl_elem_value
*value
)
709 struct oxygen
*chip
= ctl
->private_data
;
710 struct xonar_wm87x6
*data
= chip
->model_data
;
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
);
721 static int wm8776_hp_vol_put(struct snd_kcontrol
*ctl
,
722 struct snd_ctl_elem_value
*value
)
724 struct oxygen
*chip
= ctl
->private_data
;
725 struct xonar_wm87x6
*data
= chip
->model_data
;
728 mutex_lock(&chip
->mutex
);
729 to_update
= (value
->value
.integer
.value
[0] !=
730 (data
->wm8776_regs
[WM8776_HPLVOL
] & WM8776_HPATT_MASK
))
732 to_update
|= (value
->value
.integer
.value
[1] !=
733 (data
->wm8776_regs
[WM8776_HPRVOL
] & WM8776_HPATT_MASK
))
735 if (value
->value
.integer
.value
[0] == value
->value
.integer
.value
[1]) {
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
;
747 wm8776_write(chip
, WM8776_HPLVOL
,
748 value
->value
.integer
.value
[0] |
750 ((to_update
& 2) ? 0 : WM8776_UPDATE
));
752 wm8776_write(chip
, WM8776_HPRVOL
,
753 value
->value
.integer
.value
[1] |
754 WM8776_HPZCEN
| WM8776_UPDATE
);
756 mutex_unlock(&chip
->mutex
);
757 return to_update
!= 0;
760 static int wm8776_input_mux_get(struct snd_kcontrol
*ctl
,
761 struct snd_ctl_elem_value
*value
)
763 struct oxygen
*chip
= ctl
->private_data
;
764 struct xonar_wm87x6
*data
= chip
->model_data
;
765 unsigned int mux_bit
= ctl
->private_value
;
767 value
->value
.integer
.value
[0] =
768 !!(data
->wm8776_regs
[WM8776_ADCMUX
] & mux_bit
);
772 static int wm8776_input_mux_put(struct snd_kcontrol
*ctl
,
773 struct snd_ctl_elem_value
*value
)
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
;
782 mutex_lock(&chip
->mutex
);
783 reg
= data
->wm8776_regs
[WM8776_ADCMUX
];
784 if (value
->value
.integer
.value
[0]) {
786 /* line-in and mic-in are exclusive */
791 other_ctl
= data
->line_adcmux_control
;
793 other_ctl
= data
->mic_adcmux_control
;
794 snd_ctl_notify(chip
->card
, SNDRV_CTL_EVENT_MASK_VALUE
,
799 changed
= reg
!= data
->wm8776_regs
[WM8776_ADCMUX
];
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
);
806 mutex_unlock(&chip
->mutex
);
810 static int wm8776_input_vol_info(struct snd_kcontrol
*ctl
,
811 struct snd_ctl_elem_info
*info
)
813 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
815 info
->value
.integer
.min
= 0xa5;
816 info
->value
.integer
.max
= 0xff;
820 static int wm8776_input_vol_get(struct snd_kcontrol
*ctl
,
821 struct snd_ctl_elem_value
*value
)
823 struct oxygen
*chip
= ctl
->private_data
;
824 struct xonar_wm87x6
*data
= chip
->model_data
;
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
);
835 static int wm8776_input_vol_put(struct snd_kcontrol
*ctl
,
836 struct snd_ctl_elem_value
*value
)
838 struct oxygen
*chip
= ctl
->private_data
;
839 struct xonar_wm87x6
*data
= chip
->model_data
;
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
);
855 static int wm8776_level_control_info(struct snd_kcontrol
*ctl
,
856 struct snd_ctl_elem_info
*info
)
858 static const char *const names
[3] = {
859 "None", "Peak Limiter", "Automatic Level Control"
862 return snd_ctl_enum_info(info
, 1, 3, names
);
865 static int wm8776_level_control_get(struct snd_kcontrol
*ctl
,
866 struct snd_ctl_elem_value
*value
)
868 struct oxygen
*chip
= ctl
->private_data
;
869 struct xonar_wm87x6
*data
= chip
->model_data
;
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;
877 value
->value
.enumerated
.item
[0] = 2;
881 static void activate_control(struct oxygen
*chip
,
882 struct snd_kcontrol
*ctl
, unsigned int mode
)
886 if (ctl
->private_value
& mode
)
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
);
896 static int wm8776_level_control_put(struct snd_kcontrol
*ctl
,
897 struct snd_ctl_elem_value
*value
)
899 struct oxygen
*chip
= ctl
->private_data
;
900 struct xonar_wm87x6
*data
= chip
->model_data
;
901 unsigned int mode
= 0, i
;
905 if (value
->value
.enumerated
.item
[0] >= 3)
907 mutex_lock(&chip
->mutex
);
908 changed
= value
->value
.enumerated
.item
[0] != ctl
->private_value
;
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]) {
915 wm8776_write_cached(chip
, WM8776_ALCCTRL2
,
916 ctrl2
& ~WM8776_LCEN
);
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
;
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
;
935 for (i
= 0; i
< ARRAY_SIZE(data
->lc_controls
); ++i
)
936 activate_control(chip
, data
->lc_controls
[i
], mode
);
938 mutex_unlock(&chip
->mutex
);
942 static int hpf_info(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_info
*info
)
944 static const char *const names
[2] = {
945 "None", "High-pass Filter"
948 return snd_ctl_enum_info(info
, 1, 2, names
);
951 static int hpf_get(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
953 struct oxygen
*chip
= ctl
->private_data
;
954 struct xonar_wm87x6
*data
= chip
->model_data
;
956 value
->value
.enumerated
.item
[0] =
957 !(data
->wm8776_regs
[WM8776_ADCIFCTRL
] & WM8776_ADCHPD
);
961 static int hpf_put(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
963 struct oxygen
*chip
= ctl
->private_data
;
964 struct xonar_wm87x6
*data
= chip
->model_data
;
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
];
974 wm8776_write(chip
, WM8776_ADCIFCTRL
, reg
);
975 mutex_unlock(&chip
->mutex
);
979 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
980 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
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), \
987 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
988 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
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, \
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 }, \
1012 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale
, -6000, 50, 0);
1013 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale
, -2100, 50, 0);
1014 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale
, -6000, 100, 0);
1015 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale
, -1600, 100, 0);
1016 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale
, 0, 400, 0);
1017 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale
, -7800, 600, 0);
1018 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale
, -1200, 100, 0);
1019 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale
, -2100, 400, 0);
1021 static const struct snd_kcontrol_new ds_controls
[] = {
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
},
1030 WM8776_BIT_SWITCH("Headphone Playback Switch",
1031 WM8776_PWRDOWN
, WM8776_HPPD
, 1, 0),
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
},
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,
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,
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),
1061 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1062 .name
= "ADC Filter Capture Enum",
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
,
1076 static const struct snd_kcontrol_new hdav_slim_controls
[] = {
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
,
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
},
1093 WM8776_BIT_SWITCH("Headphone Playback Switch",
1094 WM8776_PWRDOWN
, WM8776_HPPD
, 1, 0),
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
},
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),
1108 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1109 .name
= "ADC Filter Capture Enum",
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
,
1123 static 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,
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,
1146 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1147 WM8776_ALCCTRL3
, 4, 3, 0, 10, 0xf,
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,
1158 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1159 WM8776_NOISEGATE
, WM8776_NGAT
, 0,
1161 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1162 WM8776_NOISEGATE
, 2, 0, 0, 7, 0x7,
1163 LC_CONTROL_ALC
, wm8776_ngth_db_scale
),
1166 static int add_lc_controls(struct oxygen
*chip
)
1168 struct xonar_wm87x6
*data
= chip
->model_data
;
1170 struct snd_kcontrol
*ctl
;
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
);
1178 err
= snd_ctl_add(chip
->card
, ctl
);
1181 data
->lc_controls
[i
] = ctl
;
1186 static int xonar_ds_mixer_init(struct oxygen
*chip
)
1188 struct xonar_wm87x6
*data
= chip
->model_data
;
1190 struct snd_kcontrol
*ctl
;
1193 for (i
= 0; i
< ARRAY_SIZE(ds_controls
); ++i
) {
1194 ctl
= snd_ctl_new1(&ds_controls
[i
], chip
);
1197 err
= snd_ctl_add(chip
->card
, ctl
);
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
;
1205 if (!data
->line_adcmux_control
|| !data
->mic_adcmux_control
)
1208 return add_lc_controls(chip
);
1211 static int xonar_hdav_slim_mixer_init(struct oxygen
*chip
)
1214 struct snd_kcontrol
*ctl
;
1217 for (i
= 0; i
< ARRAY_SIZE(hdav_slim_controls
); ++i
) {
1218 ctl
= snd_ctl_new1(&hdav_slim_controls
[i
], chip
);
1221 err
= snd_ctl_add(chip
->card
, ctl
);
1226 return add_lc_controls(chip
);
1229 static void dump_wm8776_registers(struct oxygen
*chip
,
1230 struct snd_info_buffer
*buffer
)
1232 struct xonar_wm87x6
*data
= chip
->model_data
;
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");
1244 static void dump_wm87x6_registers(struct oxygen
*chip
,
1245 struct snd_info_buffer
*buffer
)
1247 struct xonar_wm87x6
*data
= chip
->model_data
;
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");
1257 static const struct oxygen_model model_xonar_ds
= {
1258 .shortname
= "Xonar DS",
1259 .longname
= "Asus Virtuoso 66",
1261 .init
= xonar_ds_init
,
1262 .mixer_init
= xonar_ds_mixer_init
,
1263 .cleanup
= xonar_ds_cleanup
,
1264 .suspend
= xonar_ds_suspend
,
1265 .resume
= xonar_ds_resume
,
1266 .pcm_hardware_filter
= wm8776_adc_hardware_filter
,
1267 .set_dac_params
= set_wm87x6_dac_params
,
1268 .set_adc_params
= set_wm8776_adc_params
,
1269 .update_dac_volume
= update_wm87x6_volume
,
1270 .update_dac_mute
= update_wm87x6_mute
,
1271 .update_center_lfe_mix
= update_wm8766_center_lfe_mix
,
1272 .gpio_changed
= xonar_ds_gpio_changed
,
1273 .dump_registers
= dump_wm87x6_registers
,
1274 .dac_tlv
= wm87x6_dac_db_scale
,
1275 .model_data_size
= sizeof(struct xonar_wm87x6
),
1276 .device_config
= PLAYBACK_0_TO_I2S
|
1277 PLAYBACK_1_TO_SPDIF
|
1278 CAPTURE_0_FROM_I2S_1
|
1279 CAPTURE_1_FROM_SPDIF
,
1280 .dac_channels_pcm
= 8,
1281 .dac_channels_mixer
= 8,
1282 .dac_volume_min
= 255 - 2*60,
1283 .dac_volume_max
= 255,
1284 .function_flags
= OXYGEN_FUNCTION_SPI
,
1285 .dac_mclks
= OXYGEN_MCLKS(256, 256, 128),
1286 .adc_mclks
= OXYGEN_MCLKS(256, 256, 128),
1287 .dac_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1288 .adc_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1291 static const struct oxygen_model model_xonar_hdav_slim
= {
1292 .shortname
= "Xonar HDAV1.3 Slim",
1293 .longname
= "Asus Virtuoso 200",
1295 .init
= xonar_hdav_slim_init
,
1296 .mixer_init
= xonar_hdav_slim_mixer_init
,
1297 .cleanup
= xonar_hdav_slim_cleanup
,
1298 .suspend
= xonar_hdav_slim_suspend
,
1299 .resume
= xonar_hdav_slim_resume
,
1300 .pcm_hardware_filter
= xonar_hdav_slim_hardware_filter
,
1301 .set_dac_params
= set_hdav_slim_dac_params
,
1302 .set_adc_params
= set_wm8776_adc_params
,
1303 .update_dac_volume
= update_wm8776_volume
,
1304 .update_dac_mute
= update_wm8776_mute
,
1305 .uart_input
= xonar_hdmi_uart_input
,
1306 .dump_registers
= dump_wm8776_registers
,
1307 .dac_tlv
= wm87x6_dac_db_scale
,
1308 .model_data_size
= sizeof(struct xonar_wm87x6
),
1309 .device_config
= PLAYBACK_0_TO_I2S
|
1310 PLAYBACK_1_TO_SPDIF
|
1311 CAPTURE_0_FROM_I2S_1
|
1312 CAPTURE_1_FROM_SPDIF
,
1313 .dac_channels_pcm
= 8,
1314 .dac_channels_mixer
= 2,
1315 .dac_volume_min
= 255 - 2*60,
1316 .dac_volume_max
= 255,
1317 .function_flags
= OXYGEN_FUNCTION_2WIRE
,
1318 .dac_mclks
= OXYGEN_MCLKS(256, 256, 128),
1319 .adc_mclks
= OXYGEN_MCLKS(256, 256, 128),
1320 .dac_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1321 .adc_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1324 int __devinit
get_xonar_wm87x6_model(struct oxygen
*chip
,
1325 const struct pci_device_id
*id
)
1327 switch (id
->subdevice
) {
1329 chip
->model
= model_xonar_ds
;
1332 chip
->model
= model_xonar_hdav_slim
;