2 * card driver for models with WM8776/WM8766 DACs (Xonar DS)
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
29 * GPIO 6 -> route input jack to input 1/2 (1/0)
30 * GPIO 7 -> enable output to speakers
31 * GPIO 8 -> enable output to speakers
34 #include <linux/pci.h>
35 #include <linux/delay.h>
36 #include <sound/control.h>
37 #include <sound/core.h>
38 #include <sound/pcm.h>
39 #include <sound/pcm_params.h>
40 #include <sound/tlv.h>
45 #define GPIO_DS_HP_DETECT 0x0010
46 #define GPIO_DS_INPUT_ROUTE 0x0040
47 #define GPIO_DS_OUTPUT_ENABLE 0x0180
49 #define LC_CONTROL_LIMITER 0x40000000
50 #define LC_CONTROL_ALC 0x20000000
53 struct xonar_generic generic
;
54 u16 wm8776_regs
[0x17];
55 u16 wm8766_regs
[0x10];
56 struct snd_kcontrol
*lc_controls
[13];
59 static void wm8776_write(struct oxygen
*chip
,
60 unsigned int reg
, unsigned int value
)
62 struct xonar_wm87x6
*data
= chip
->model_data
;
64 oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
65 OXYGEN_SPI_DATA_LENGTH_2
|
66 OXYGEN_SPI_CLOCK_160
|
67 (1 << OXYGEN_SPI_CODEC_SHIFT
) |
68 OXYGEN_SPI_CEN_LATCH_CLOCK_LO
,
70 if (reg
< ARRAY_SIZE(data
->wm8776_regs
)) {
71 if (reg
>= WM8776_HPLVOL
&& reg
<= WM8776_DACMASTER
)
72 value
&= ~WM8776_UPDATE
;
73 data
->wm8776_regs
[reg
] = value
;
77 static void wm8776_write_cached(struct oxygen
*chip
,
78 unsigned int reg
, unsigned int value
)
80 struct xonar_wm87x6
*data
= chip
->model_data
;
82 if (reg
>= ARRAY_SIZE(data
->wm8776_regs
) ||
83 value
!= data
->wm8776_regs
[reg
])
84 wm8776_write(chip
, reg
, value
);
87 static void wm8766_write(struct oxygen
*chip
,
88 unsigned int reg
, unsigned int value
)
90 struct xonar_wm87x6
*data
= chip
->model_data
;
92 oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
93 OXYGEN_SPI_DATA_LENGTH_2
|
94 OXYGEN_SPI_CLOCK_160
|
95 (0 << OXYGEN_SPI_CODEC_SHIFT
) |
96 OXYGEN_SPI_CEN_LATCH_CLOCK_LO
,
98 if (reg
< ARRAY_SIZE(data
->wm8766_regs
))
99 data
->wm8766_regs
[reg
] = value
;
102 static void wm8766_write_cached(struct oxygen
*chip
,
103 unsigned int reg
, unsigned int value
)
105 struct xonar_wm87x6
*data
= chip
->model_data
;
107 if (reg
>= ARRAY_SIZE(data
->wm8766_regs
) ||
108 value
!= data
->wm8766_regs
[reg
]) {
109 if ((reg
>= WM8766_LDA1
&& reg
<= WM8766_RDA1
) ||
110 (reg
>= WM8766_LDA2
&& reg
<= WM8766_MASTDA
))
111 value
&= ~WM8766_UPDATE
;
112 wm8766_write(chip
, reg
, value
);
116 static void wm8776_registers_init(struct oxygen
*chip
)
118 struct xonar_wm87x6
*data
= chip
->model_data
;
120 wm8776_write(chip
, WM8776_RESET
, 0);
121 wm8776_write(chip
, WM8776_DACCTRL1
, WM8776_DZCEN
|
122 WM8776_PL_LEFT_LEFT
| WM8776_PL_RIGHT_RIGHT
);
123 wm8776_write(chip
, WM8776_DACMUTE
, chip
->dac_mute
? WM8776_DMUTE
: 0);
124 wm8776_write(chip
, WM8776_DACIFCTRL
,
125 WM8776_DACFMT_LJUST
| WM8776_DACWL_24
);
126 wm8776_write(chip
, WM8776_ADCIFCTRL
,
127 data
->wm8776_regs
[WM8776_ADCIFCTRL
]);
128 wm8776_write(chip
, WM8776_MSTRCTRL
, data
->wm8776_regs
[WM8776_MSTRCTRL
]);
129 wm8776_write(chip
, WM8776_PWRDOWN
, data
->wm8776_regs
[WM8776_PWRDOWN
]);
130 wm8776_write(chip
, WM8776_HPLVOL
, data
->wm8776_regs
[WM8776_HPLVOL
]);
131 wm8776_write(chip
, WM8776_HPRVOL
, data
->wm8776_regs
[WM8776_HPRVOL
] |
133 wm8776_write(chip
, WM8776_ADCLVOL
, data
->wm8776_regs
[WM8776_ADCLVOL
]);
134 wm8776_write(chip
, WM8776_ADCRVOL
, data
->wm8776_regs
[WM8776_ADCRVOL
]);
135 wm8776_write(chip
, WM8776_ADCMUX
, data
->wm8776_regs
[WM8776_ADCMUX
]);
136 wm8776_write(chip
, WM8776_DACLVOL
, chip
->dac_volume
[0]);
137 wm8776_write(chip
, WM8776_DACRVOL
, chip
->dac_volume
[1] | WM8776_UPDATE
);
140 static void wm8766_registers_init(struct oxygen
*chip
)
142 wm8766_write(chip
, WM8766_RESET
, 0);
143 wm8766_write(chip
, WM8766_INT_CTRL
, WM8766_FMT_LJUST
| WM8766_IWL_24
);
144 wm8766_write(chip
, WM8766_DAC_CTRL2
,
145 WM8766_ZCD
| (chip
->dac_mute
? WM8766_DMUTE_MASK
: 0));
146 wm8766_write(chip
, WM8766_LDA1
, chip
->dac_volume
[2]);
147 wm8766_write(chip
, WM8766_RDA1
, chip
->dac_volume
[3]);
148 wm8766_write(chip
, WM8766_LDA2
, chip
->dac_volume
[4]);
149 wm8766_write(chip
, WM8766_RDA2
, chip
->dac_volume
[5]);
150 wm8766_write(chip
, WM8766_LDA3
, chip
->dac_volume
[6]);
151 wm8766_write(chip
, WM8766_RDA3
, chip
->dac_volume
[7] | WM8766_UPDATE
);
154 static void wm8776_init(struct oxygen
*chip
)
156 struct xonar_wm87x6
*data
= chip
->model_data
;
158 data
->wm8776_regs
[WM8776_HPLVOL
] = (0x79 - 60) | WM8776_HPZCEN
;
159 data
->wm8776_regs
[WM8776_HPRVOL
] = (0x79 - 60) | WM8776_HPZCEN
;
160 data
->wm8776_regs
[WM8776_ADCIFCTRL
] =
161 WM8776_ADCFMT_LJUST
| WM8776_ADCWL_24
| WM8776_ADCMCLK
;
162 data
->wm8776_regs
[WM8776_MSTRCTRL
] =
163 WM8776_ADCRATE_256
| WM8776_DACRATE_256
;
164 data
->wm8776_regs
[WM8776_PWRDOWN
] = WM8776_HPPD
;
165 data
->wm8776_regs
[WM8776_ADCLVOL
] = 0xa5 | WM8776_ZCA
;
166 data
->wm8776_regs
[WM8776_ADCRVOL
] = 0xa5 | WM8776_ZCA
;
167 data
->wm8776_regs
[WM8776_ADCMUX
] = 0x001;
168 wm8776_registers_init(chip
);
171 static void xonar_ds_init(struct oxygen
*chip
)
173 struct xonar_wm87x6
*data
= chip
->model_data
;
175 data
->generic
.anti_pop_delay
= 300;
176 data
->generic
.output_enable_bit
= GPIO_DS_OUTPUT_ENABLE
;
179 wm8766_registers_init(chip
);
181 oxygen_write16_masked(chip
, OXYGEN_GPIO_CONTROL
, GPIO_DS_INPUT_ROUTE
,
182 GPIO_DS_HP_DETECT
| GPIO_DS_INPUT_ROUTE
);
183 oxygen_set_bits16(chip
, OXYGEN_GPIO_DATA
, GPIO_DS_INPUT_ROUTE
);
184 oxygen_set_bits16(chip
, OXYGEN_GPIO_INTERRUPT_MASK
, GPIO_DS_HP_DETECT
);
185 chip
->interrupt_mask
|= OXYGEN_INT_GPIO
;
187 xonar_enable_output(chip
);
189 snd_component_add(chip
->card
, "WM8776");
190 snd_component_add(chip
->card
, "WM8766");
193 static void xonar_ds_cleanup(struct oxygen
*chip
)
195 xonar_disable_output(chip
);
198 static void xonar_ds_suspend(struct oxygen
*chip
)
200 xonar_ds_cleanup(chip
);
203 static void xonar_ds_resume(struct oxygen
*chip
)
205 wm8776_registers_init(chip
);
206 wm8766_registers_init(chip
);
207 xonar_enable_output(chip
);
210 static void wm8776_adc_hardware_filter(unsigned int channel
,
211 struct snd_pcm_hardware
*hardware
)
213 if (channel
== PCM_A
) {
214 hardware
->rates
= SNDRV_PCM_RATE_32000
|
215 SNDRV_PCM_RATE_44100
|
216 SNDRV_PCM_RATE_48000
|
217 SNDRV_PCM_RATE_64000
|
218 SNDRV_PCM_RATE_88200
|
219 SNDRV_PCM_RATE_96000
;
220 hardware
->rate_max
= 96000;
224 static void set_wm87x6_dac_params(struct oxygen
*chip
,
225 struct snd_pcm_hw_params
*params
)
229 static void set_wm8776_adc_params(struct oxygen
*chip
,
230 struct snd_pcm_hw_params
*params
)
234 reg
= WM8776_ADCRATE_256
| WM8776_DACRATE_256
;
235 if (params_rate(params
) > 48000)
236 reg
|= WM8776_ADCOSR
;
237 wm8776_write_cached(chip
, WM8776_MSTRCTRL
, reg
);
240 static void update_wm8776_volume(struct oxygen
*chip
)
242 struct xonar_wm87x6
*data
= chip
->model_data
;
245 if (chip
->dac_volume
[0] == chip
->dac_volume
[1]) {
246 if (chip
->dac_volume
[0] != data
->wm8776_regs
[WM8776_DACLVOL
] ||
247 chip
->dac_volume
[1] != data
->wm8776_regs
[WM8776_DACRVOL
]) {
248 wm8776_write(chip
, WM8776_DACMASTER
,
249 chip
->dac_volume
[0] | WM8776_UPDATE
);
250 data
->wm8776_regs
[WM8776_DACLVOL
] = chip
->dac_volume
[0];
251 data
->wm8776_regs
[WM8776_DACRVOL
] = chip
->dac_volume
[0];
254 to_change
= (chip
->dac_volume
[0] !=
255 data
->wm8776_regs
[WM8776_DACLVOL
]) << 0;
256 to_change
|= (chip
->dac_volume
[1] !=
257 data
->wm8776_regs
[WM8776_DACLVOL
]) << 1;
259 wm8776_write(chip
, WM8776_DACLVOL
, chip
->dac_volume
[0] |
260 ((to_change
& 2) ? 0 : WM8776_UPDATE
));
262 wm8776_write(chip
, WM8776_DACRVOL
,
263 chip
->dac_volume
[1] | WM8776_UPDATE
);
267 static void update_wm87x6_volume(struct oxygen
*chip
)
269 static const u8 wm8766_regs
[6] = {
270 WM8766_LDA1
, WM8766_RDA1
,
271 WM8766_LDA2
, WM8766_RDA2
,
272 WM8766_LDA3
, WM8766_RDA3
,
274 struct xonar_wm87x6
*data
= chip
->model_data
;
278 update_wm8776_volume(chip
);
279 if (chip
->dac_volume
[2] == chip
->dac_volume
[3] &&
280 chip
->dac_volume
[2] == chip
->dac_volume
[4] &&
281 chip
->dac_volume
[2] == chip
->dac_volume
[5] &&
282 chip
->dac_volume
[2] == chip
->dac_volume
[6] &&
283 chip
->dac_volume
[2] == chip
->dac_volume
[7]) {
285 for (i
= 0; i
< 6; ++i
)
286 if (chip
->dac_volume
[2] !=
287 data
->wm8766_regs
[wm8766_regs
[i
]])
290 wm8766_write(chip
, WM8766_MASTDA
,
291 chip
->dac_volume
[2] | WM8766_UPDATE
);
292 for (i
= 0; i
< 6; ++i
)
293 data
->wm8766_regs
[wm8766_regs
[i
]] =
298 for (i
= 0; i
< 6; ++i
)
299 to_change
|= (chip
->dac_volume
[2 + i
] !=
300 data
->wm8766_regs
[wm8766_regs
[i
]]) << i
;
301 for (i
= 0; i
< 6; ++i
)
302 if (to_change
& (1 << i
))
303 wm8766_write(chip
, wm8766_regs
[i
],
304 chip
->dac_volume
[2 + i
] |
305 ((to_change
& (0x3e << i
))
306 ? 0 : WM8766_UPDATE
));
310 static void update_wm8776_mute(struct oxygen
*chip
)
312 wm8776_write_cached(chip
, WM8776_DACMUTE
,
313 chip
->dac_mute
? WM8776_DMUTE
: 0);
316 static void update_wm87x6_mute(struct oxygen
*chip
)
318 update_wm8776_mute(chip
);
319 wm8766_write_cached(chip
, WM8766_DAC_CTRL2
, WM8766_ZCD
|
320 (chip
->dac_mute
? WM8766_DMUTE_MASK
: 0));
323 static void xonar_ds_gpio_changed(struct oxygen
*chip
)
327 bits
= oxygen_read16(chip
, OXYGEN_GPIO_DATA
);
328 snd_printk(KERN_INFO
"HP detect: %d\n", !!(bits
& GPIO_DS_HP_DETECT
));
331 static int wm8776_bit_switch_get(struct snd_kcontrol
*ctl
,
332 struct snd_ctl_elem_value
*value
)
334 struct oxygen
*chip
= ctl
->private_data
;
335 struct xonar_wm87x6
*data
= chip
->model_data
;
336 u16 bit
= ctl
->private_value
& 0xffff;
337 unsigned int reg_index
= (ctl
->private_value
>> 16) & 0xff;
338 bool invert
= (ctl
->private_value
>> 24) & 1;
340 value
->value
.integer
.value
[0] =
341 ((data
->wm8776_regs
[reg_index
] & bit
) != 0) ^ invert
;
345 static int wm8776_bit_switch_put(struct snd_kcontrol
*ctl
,
346 struct snd_ctl_elem_value
*value
)
348 struct oxygen
*chip
= ctl
->private_data
;
349 struct xonar_wm87x6
*data
= chip
->model_data
;
350 u16 bit
= ctl
->private_value
& 0xffff;
352 unsigned int reg_index
= (ctl
->private_value
>> 16) & 0xff;
353 bool invert
= (ctl
->private_value
>> 24) & 1;
356 mutex_lock(&chip
->mutex
);
357 reg_value
= data
->wm8776_regs
[reg_index
] & ~bit
;
358 if (value
->value
.integer
.value
[0] ^ invert
)
360 changed
= reg_value
!= data
->wm8776_regs
[reg_index
];
362 wm8776_write(chip
, reg_index
, reg_value
);
363 mutex_unlock(&chip
->mutex
);
367 static int wm8776_field_enum_info(struct snd_kcontrol
*ctl
,
368 struct snd_ctl_elem_info
*info
)
370 static const char *const hld
[16] = {
371 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
372 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
373 "341 ms", "683 ms", "1.37 s", "2.73 s",
374 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
376 static const char *const atk_lim
[11] = {
377 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
378 "4 ms", "8 ms", "16 ms", "32 ms",
379 "64 ms", "128 ms", "256 ms",
381 static const char *const atk_alc
[11] = {
382 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
383 "134 ms", "269 ms", "538 ms", "1.08 s",
384 "2.15 s", "4.3 s", "8.6 s",
386 static const char *const dcy_lim
[11] = {
387 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
388 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
389 "307 ms", "614 ms", "1.23 s",
391 static const char *const dcy_alc
[11] = {
392 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
393 "536 ms", "1.07 s", "2.14 s", "4.29 s",
394 "8.58 s", "17.2 s", "34.3 s",
396 static const char *const tranwin
[8] = {
397 "0 us", "62.5 us", "125 us", "250 us",
398 "500 us", "1 ms", "2 ms", "4 ms",
401 const char *const *names
;
403 max
= (ctl
->private_value
>> 12) & 0xf;
404 info
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
406 info
->value
.enumerated
.items
= max
+ 1;
407 if (info
->value
.enumerated
.item
> max
)
408 info
->value
.enumerated
.item
= max
;
409 switch ((ctl
->private_value
>> 24) & 0x1f) {
410 case WM8776_ALCCTRL2
:
413 case WM8776_ALCCTRL3
:
414 if (((ctl
->private_value
>> 20) & 0xf) == 0) {
415 if (ctl
->private_value
& LC_CONTROL_LIMITER
)
420 if (ctl
->private_value
& LC_CONTROL_LIMITER
)
432 strcpy(info
->value
.enumerated
.name
, names
[info
->value
.enumerated
.item
]);
436 static int wm8776_field_volume_info(struct snd_kcontrol
*ctl
,
437 struct snd_ctl_elem_info
*info
)
439 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
441 info
->value
.integer
.min
= (ctl
->private_value
>> 8) & 0xf;
442 info
->value
.integer
.max
= (ctl
->private_value
>> 12) & 0xf;
446 static void wm8776_field_set_from_ctl(struct snd_kcontrol
*ctl
)
448 struct oxygen
*chip
= ctl
->private_data
;
449 struct xonar_wm87x6
*data
= chip
->model_data
;
450 unsigned int value
, reg_index
, mode
;
455 if ((data
->wm8776_regs
[WM8776_ALCCTRL1
] & WM8776_LCSEL_MASK
) ==
456 WM8776_LCSEL_LIMITER
)
457 mode
= LC_CONTROL_LIMITER
;
459 mode
= LC_CONTROL_ALC
;
460 if (!(ctl
->private_value
& mode
))
463 value
= ctl
->private_value
& 0xf;
464 min
= (ctl
->private_value
>> 8) & 0xf;
465 max
= (ctl
->private_value
>> 12) & 0xf;
466 mask
= (ctl
->private_value
>> 16) & 0xf;
467 shift
= (ctl
->private_value
>> 20) & 0xf;
468 reg_index
= (ctl
->private_value
>> 24) & 0x1f;
469 invert
= (ctl
->private_value
>> 29) & 0x1;
472 value
= max
- (value
- min
);
473 reg_value
= data
->wm8776_regs
[reg_index
];
474 reg_value
&= ~(mask
<< shift
);
475 reg_value
|= value
<< shift
;
476 wm8776_write_cached(chip
, reg_index
, reg_value
);
479 static int wm8776_field_set(struct snd_kcontrol
*ctl
, unsigned int value
)
481 struct oxygen
*chip
= ctl
->private_data
;
485 min
= (ctl
->private_value
>> 8) & 0xf;
486 max
= (ctl
->private_value
>> 12) & 0xf;
487 if (value
< min
|| value
> max
)
489 mutex_lock(&chip
->mutex
);
490 changed
= value
!= (ctl
->private_value
& 0xf);
492 ctl
->private_value
= (ctl
->private_value
& ~0xf) | value
;
493 wm8776_field_set_from_ctl(ctl
);
495 mutex_unlock(&chip
->mutex
);
499 static int wm8776_field_enum_get(struct snd_kcontrol
*ctl
,
500 struct snd_ctl_elem_value
*value
)
502 value
->value
.enumerated
.item
[0] = ctl
->private_value
& 0xf;
506 static int wm8776_field_volume_get(struct snd_kcontrol
*ctl
,
507 struct snd_ctl_elem_value
*value
)
509 value
->value
.integer
.value
[0] = ctl
->private_value
& 0xf;
513 static int wm8776_field_enum_put(struct snd_kcontrol
*ctl
,
514 struct snd_ctl_elem_value
*value
)
516 return wm8776_field_set(ctl
, value
->value
.enumerated
.item
[0]);
519 static int wm8776_field_volume_put(struct snd_kcontrol
*ctl
,
520 struct snd_ctl_elem_value
*value
)
522 return wm8776_field_set(ctl
, value
->value
.integer
.value
[0]);
525 static int wm8776_hp_vol_info(struct snd_kcontrol
*ctl
,
526 struct snd_ctl_elem_info
*info
)
528 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
530 info
->value
.integer
.min
= 0x79 - 60;
531 info
->value
.integer
.max
= 0x7f;
535 static int wm8776_hp_vol_get(struct snd_kcontrol
*ctl
,
536 struct snd_ctl_elem_value
*value
)
538 struct oxygen
*chip
= ctl
->private_data
;
539 struct xonar_wm87x6
*data
= chip
->model_data
;
541 mutex_lock(&chip
->mutex
);
542 value
->value
.integer
.value
[0] =
543 data
->wm8776_regs
[WM8776_HPLVOL
] & WM8776_HPATT_MASK
;
544 value
->value
.integer
.value
[1] =
545 data
->wm8776_regs
[WM8776_HPRVOL
] & WM8776_HPATT_MASK
;
546 mutex_unlock(&chip
->mutex
);
550 static int wm8776_hp_vol_put(struct snd_kcontrol
*ctl
,
551 struct snd_ctl_elem_value
*value
)
553 struct oxygen
*chip
= ctl
->private_data
;
554 struct xonar_wm87x6
*data
= chip
->model_data
;
557 mutex_lock(&chip
->mutex
);
558 to_update
= (value
->value
.integer
.value
[0] !=
559 (data
->wm8776_regs
[WM8776_HPLVOL
] & WM8776_HPATT_MASK
))
561 to_update
|= (value
->value
.integer
.value
[1] !=
562 (data
->wm8776_regs
[WM8776_HPRVOL
] & WM8776_HPATT_MASK
))
564 if (value
->value
.integer
.value
[0] == value
->value
.integer
.value
[1]) {
566 wm8776_write(chip
, WM8776_HPMASTER
,
567 value
->value
.integer
.value
[0] |
568 WM8776_HPZCEN
| WM8776_UPDATE
);
569 data
->wm8776_regs
[WM8776_HPLVOL
] =
570 value
->value
.integer
.value
[0] | WM8776_HPZCEN
;
571 data
->wm8776_regs
[WM8776_HPRVOL
] =
572 value
->value
.integer
.value
[0] | WM8776_HPZCEN
;
576 wm8776_write(chip
, WM8776_HPLVOL
,
577 value
->value
.integer
.value
[0] |
579 ((to_update
& 2) ? 0 : WM8776_UPDATE
));
581 wm8776_write(chip
, WM8776_HPRVOL
,
582 value
->value
.integer
.value
[1] |
583 WM8776_HPZCEN
| WM8776_UPDATE
);
585 mutex_unlock(&chip
->mutex
);
586 return to_update
!= 0;
589 static int wm8776_input_mux_get(struct snd_kcontrol
*ctl
,
590 struct snd_ctl_elem_value
*value
)
592 struct oxygen
*chip
= ctl
->private_data
;
593 struct xonar_wm87x6
*data
= chip
->model_data
;
594 unsigned int mux_bit
= ctl
->private_value
;
596 value
->value
.integer
.value
[0] =
597 !!(data
->wm8776_regs
[WM8776_ADCMUX
] & mux_bit
);
601 static int wm8776_input_mux_put(struct snd_kcontrol
*ctl
,
602 struct snd_ctl_elem_value
*value
)
604 struct oxygen
*chip
= ctl
->private_data
;
605 struct xonar_wm87x6
*data
= chip
->model_data
;
606 unsigned int mux_bit
= ctl
->private_value
;
610 mutex_lock(&chip
->mutex
);
611 reg
= data
->wm8776_regs
[WM8776_ADCMUX
];
612 if (value
->value
.integer
.value
[0]) {
617 changed
= reg
!= data
->wm8776_regs
[WM8776_ADCMUX
];
619 oxygen_write16_masked(chip
, OXYGEN_GPIO_DATA
,
620 reg
& 1 ? GPIO_DS_INPUT_ROUTE
: 0,
621 GPIO_DS_INPUT_ROUTE
);
622 wm8776_write(chip
, WM8776_ADCMUX
, reg
);
624 mutex_unlock(&chip
->mutex
);
628 static int wm8776_input_vol_info(struct snd_kcontrol
*ctl
,
629 struct snd_ctl_elem_info
*info
)
631 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
633 info
->value
.integer
.min
= 0xa5;
634 info
->value
.integer
.max
= 0xff;
638 static int wm8776_input_vol_get(struct snd_kcontrol
*ctl
,
639 struct snd_ctl_elem_value
*value
)
641 struct oxygen
*chip
= ctl
->private_data
;
642 struct xonar_wm87x6
*data
= chip
->model_data
;
644 mutex_lock(&chip
->mutex
);
645 value
->value
.integer
.value
[0] =
646 data
->wm8776_regs
[WM8776_ADCLVOL
] & WM8776_AGMASK
;
647 value
->value
.integer
.value
[1] =
648 data
->wm8776_regs
[WM8776_ADCRVOL
] & WM8776_AGMASK
;
649 mutex_unlock(&chip
->mutex
);
653 static int wm8776_input_vol_put(struct snd_kcontrol
*ctl
,
654 struct snd_ctl_elem_value
*value
)
656 struct oxygen
*chip
= ctl
->private_data
;
657 struct xonar_wm87x6
*data
= chip
->model_data
;
660 mutex_lock(&chip
->mutex
);
661 changed
= (value
->value
.integer
.value
[0] !=
662 (data
->wm8776_regs
[WM8776_ADCLVOL
] & WM8776_AGMASK
)) ||
663 (value
->value
.integer
.value
[1] !=
664 (data
->wm8776_regs
[WM8776_ADCRVOL
] & WM8776_AGMASK
));
665 wm8776_write_cached(chip
, WM8776_ADCLVOL
,
666 value
->value
.integer
.value
[0] | WM8776_ZCA
);
667 wm8776_write_cached(chip
, WM8776_ADCRVOL
,
668 value
->value
.integer
.value
[1] | WM8776_ZCA
);
669 mutex_unlock(&chip
->mutex
);
673 static int wm8776_level_control_info(struct snd_kcontrol
*ctl
,
674 struct snd_ctl_elem_info
*info
)
676 static const char *const names
[3] = {
677 "None", "Peak Limiter", "Automatic Level Control"
679 info
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
681 info
->value
.enumerated
.items
= 3;
682 if (info
->value
.enumerated
.item
>= 3)
683 info
->value
.enumerated
.item
= 2;
684 strcpy(info
->value
.enumerated
.name
, names
[info
->value
.enumerated
.item
]);
688 static int wm8776_level_control_get(struct snd_kcontrol
*ctl
,
689 struct snd_ctl_elem_value
*value
)
691 struct oxygen
*chip
= ctl
->private_data
;
692 struct xonar_wm87x6
*data
= chip
->model_data
;
694 if (!(data
->wm8776_regs
[WM8776_ALCCTRL2
] & WM8776_LCEN
))
695 value
->value
.enumerated
.item
[0] = 0;
696 else if ((data
->wm8776_regs
[WM8776_ALCCTRL1
] & WM8776_LCSEL_MASK
) ==
697 WM8776_LCSEL_LIMITER
)
698 value
->value
.enumerated
.item
[0] = 1;
700 value
->value
.enumerated
.item
[0] = 2;
704 static void activate_control(struct oxygen
*chip
,
705 struct snd_kcontrol
*ctl
, unsigned int mode
)
709 if (ctl
->private_value
& mode
)
712 access
= SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
713 if ((ctl
->vd
[0].access
& SNDRV_CTL_ELEM_ACCESS_INACTIVE
) != access
) {
714 ctl
->vd
[0].access
^= SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
715 snd_ctl_notify(chip
->card
, SNDRV_CTL_EVENT_MASK_INFO
, &ctl
->id
);
719 static int wm8776_level_control_put(struct snd_kcontrol
*ctl
,
720 struct snd_ctl_elem_value
*value
)
722 struct oxygen
*chip
= ctl
->private_data
;
723 struct xonar_wm87x6
*data
= chip
->model_data
;
724 unsigned int mode
= 0, i
;
728 if (value
->value
.enumerated
.item
[0] >= 3)
730 mutex_lock(&chip
->mutex
);
731 changed
= value
->value
.enumerated
.item
[0] != ctl
->private_value
;
733 ctl
->private_value
= value
->value
.enumerated
.item
[0];
734 ctrl1
= data
->wm8776_regs
[WM8776_ALCCTRL1
];
735 ctrl2
= data
->wm8776_regs
[WM8776_ALCCTRL2
];
736 switch (value
->value
.enumerated
.item
[0]) {
738 wm8776_write_cached(chip
, WM8776_ALCCTRL2
,
739 ctrl2
& ~WM8776_LCEN
);
742 wm8776_write_cached(chip
, WM8776_ALCCTRL1
,
743 (ctrl1
& ~WM8776_LCSEL_MASK
) |
744 WM8776_LCSEL_LIMITER
);
745 wm8776_write_cached(chip
, WM8776_ALCCTRL2
,
746 ctrl2
| WM8776_LCEN
);
747 mode
= LC_CONTROL_LIMITER
;
750 wm8776_write_cached(chip
, WM8776_ALCCTRL1
,
751 (ctrl1
& ~WM8776_LCSEL_MASK
) |
752 WM8776_LCSEL_ALC_STEREO
);
753 wm8776_write_cached(chip
, WM8776_ALCCTRL2
,
754 ctrl2
| WM8776_LCEN
);
755 mode
= LC_CONTROL_ALC
;
758 for (i
= 0; i
< ARRAY_SIZE(data
->lc_controls
); ++i
)
759 activate_control(chip
, data
->lc_controls
[i
], mode
);
761 mutex_unlock(&chip
->mutex
);
765 static int hpf_info(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_info
*info
)
767 static const char *const names
[2] = {
768 "None", "High-pass Filter"
771 info
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
773 info
->value
.enumerated
.items
= 2;
774 if (info
->value
.enumerated
.item
>= 2)
775 info
->value
.enumerated
.item
= 1;
776 strcpy(info
->value
.enumerated
.name
, names
[info
->value
.enumerated
.item
]);
780 static int hpf_get(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
782 struct oxygen
*chip
= ctl
->private_data
;
783 struct xonar_wm87x6
*data
= chip
->model_data
;
785 value
->value
.enumerated
.item
[0] =
786 !(data
->wm8776_regs
[WM8776_ADCIFCTRL
] & WM8776_ADCHPD
);
790 static int hpf_put(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
792 struct oxygen
*chip
= ctl
->private_data
;
793 struct xonar_wm87x6
*data
= chip
->model_data
;
797 mutex_lock(&chip
->mutex
);
798 reg
= data
->wm8776_regs
[WM8776_ADCIFCTRL
] & ~WM8776_ADCHPD
;
799 if (!value
->value
.enumerated
.item
[0])
800 reg
|= WM8776_ADCHPD
;
801 changed
= reg
!= data
->wm8776_regs
[WM8776_ADCIFCTRL
];
803 wm8776_write(chip
, WM8776_ADCIFCTRL
, reg
);
804 mutex_unlock(&chip
->mutex
);
808 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
809 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
811 .info = snd_ctl_boolean_mono_info, \
812 .get = wm8776_bit_switch_get, \
813 .put = wm8776_bit_switch_put, \
814 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
816 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
817 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
819 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
820 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
821 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
822 _WM8776_FIELD_CTL(xname " Capture Enum", \
823 reg, shift, init, min, max, mask, flags), \
824 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
825 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
826 .info = wm8776_field_enum_info, \
827 .get = wm8776_field_enum_get, \
828 .put = wm8776_field_enum_put, \
830 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
831 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
832 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
833 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
834 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
835 .info = wm8776_field_volume_info, \
836 .get = wm8776_field_volume_get, \
837 .put = wm8776_field_volume_put, \
838 .tlv = { .p = tlv_p }, \
841 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale
, -6000, 50, 0);
842 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale
, -2100, 50, 0);
843 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale
, -6000, 100, 0);
844 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale
, -1600, 100, 0);
845 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale
, 0, 400, 0);
846 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale
, -7800, 600, 0);
847 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale
, -1200, 100, 0);
848 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale
, -2100, 400, 0);
850 static const struct snd_kcontrol_new ds_controls
[] = {
852 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
853 .name
= "Headphone Playback Volume",
854 .info
= wm8776_hp_vol_info
,
855 .get
= wm8776_hp_vol_get
,
856 .put
= wm8776_hp_vol_put
,
857 .tlv
= { .p
= wm8776_hp_db_scale
},
859 WM8776_BIT_SWITCH("Headphone Playback Switch",
860 WM8776_PWRDOWN
, WM8776_HPPD
, 1, 0),
862 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
863 .name
= "Input Capture Volume",
864 .info
= wm8776_input_vol_info
,
865 .get
= wm8776_input_vol_get
,
866 .put
= wm8776_input_vol_put
,
867 .tlv
= { .p
= wm8776_adc_db_scale
},
870 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
871 .name
= "Line Capture Switch",
872 .info
= snd_ctl_boolean_mono_info
,
873 .get
= wm8776_input_mux_get
,
874 .put
= wm8776_input_mux_put
,
875 .private_value
= 1 << 0,
878 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
879 .name
= "Mic Capture Switch",
880 .info
= snd_ctl_boolean_mono_info
,
881 .get
= wm8776_input_mux_get
,
882 .put
= wm8776_input_mux_put
,
883 .private_value
= 1 << 1,
885 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX
, 1 << 2, 0, 0),
887 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
888 .name
= "ADC Filter Capture Enum",
894 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
895 .name
= "Level Control Capture Enum",
896 .info
= wm8776_level_control_info
,
897 .get
= wm8776_level_control_get
,
898 .put
= wm8776_level_control_put
,
902 static const struct snd_kcontrol_new lc_controls
[] = {
903 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
904 WM8776_ALCCTRL1
, 0, 11, 0, 15, 0xf,
905 LC_CONTROL_LIMITER
, wm8776_lct_db_scale
),
906 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
907 WM8776_ALCCTRL3
, 0, 2, 0, 10, 0xf,
909 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
910 WM8776_ALCCTRL3
, 4, 3, 0, 10, 0xf,
912 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
913 WM8776_LIMITER
, 4, 2, 0, 7, 0x7,
915 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
916 WM8776_LIMITER
, 0, 6, 3, 12, 0xf,
918 wm8776_maxatten_lim_db_scale
),
919 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
920 WM8776_ALCCTRL1
, 0, 11, 0, 15, 0xf,
921 LC_CONTROL_ALC
, wm8776_lct_db_scale
),
922 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
923 WM8776_ALCCTRL3
, 0, 2, 0, 10, 0xf,
925 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
926 WM8776_ALCCTRL3
, 4, 3, 0, 10, 0xf,
928 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
929 WM8776_ALCCTRL1
, 4, 7, 1, 7, 0x7,
930 LC_CONTROL_ALC
, wm8776_maxgain_db_scale
),
931 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
932 WM8776_LIMITER
, 0, 10, 10, 15, 0xf,
933 LC_CONTROL_ALC
, wm8776_maxatten_alc_db_scale
),
934 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
935 WM8776_ALCCTRL2
, 0, 0, 0, 15, 0xf,
937 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
938 WM8776_NOISEGATE
, WM8776_NGAT
, 0,
940 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
941 WM8776_NOISEGATE
, 2, 0, 0, 7, 0x7,
942 LC_CONTROL_ALC
, wm8776_ngth_db_scale
),
945 static int xonar_ds_control_filter(struct snd_kcontrol_new
*template)
947 if (!strncmp(template->name
, "CD Capture ", 11))
948 return 1; /* no CD input */
952 static int xonar_ds_mixer_init(struct oxygen
*chip
)
954 struct xonar_wm87x6
*data
= chip
->model_data
;
956 struct snd_kcontrol
*ctl
;
959 for (i
= 0; i
< ARRAY_SIZE(ds_controls
); ++i
) {
960 ctl
= snd_ctl_new1(&ds_controls
[i
], chip
);
963 err
= snd_ctl_add(chip
->card
, ctl
);
967 BUILD_BUG_ON(ARRAY_SIZE(lc_controls
) != ARRAY_SIZE(data
->lc_controls
));
968 for (i
= 0; i
< ARRAY_SIZE(lc_controls
); ++i
) {
969 ctl
= snd_ctl_new1(&lc_controls
[i
], chip
);
972 err
= snd_ctl_add(chip
->card
, ctl
);
975 data
->lc_controls
[i
] = ctl
;
980 static const struct oxygen_model model_xonar_ds
= {
981 .shortname
= "Xonar DS",
982 .longname
= "Asus Virtuoso 200",
984 .init
= xonar_ds_init
,
985 .control_filter
= xonar_ds_control_filter
,
986 .mixer_init
= xonar_ds_mixer_init
,
987 .cleanup
= xonar_ds_cleanup
,
988 .suspend
= xonar_ds_suspend
,
989 .resume
= xonar_ds_resume
,
990 .pcm_hardware_filter
= wm8776_adc_hardware_filter
,
991 .get_i2s_mclk
= oxygen_default_i2s_mclk
,
992 .set_dac_params
= set_wm87x6_dac_params
,
993 .set_adc_params
= set_wm8776_adc_params
,
994 .update_dac_volume
= update_wm87x6_volume
,
995 .update_dac_mute
= update_wm87x6_mute
,
996 .gpio_changed
= xonar_ds_gpio_changed
,
997 .dac_tlv
= wm87x6_dac_db_scale
,
998 .model_data_size
= sizeof(struct xonar_wm87x6
),
999 .device_config
= PLAYBACK_0_TO_I2S
|
1000 PLAYBACK_1_TO_SPDIF
|
1001 CAPTURE_0_FROM_I2S_1
,
1003 .dac_volume_min
= 255 - 2*60,
1004 .dac_volume_max
= 255,
1005 .function_flags
= OXYGEN_FUNCTION_SPI
,
1006 .dac_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1007 .adc_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
1010 int __devinit
get_xonar_wm87x6_model(struct oxygen
*chip
,
1011 const struct pci_device_id
*id
)
1013 switch (id
->subdevice
) {
1015 chip
->model
= model_xonar_ds
;