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