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