]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/pci/oxygen/xonar_wm87x6.c
Merge branch 'for-rmk' of git://git.pengutronix.de/git/imx/linux-2.6
[net-next-2.6.git] / sound / pci / oxygen / xonar_wm87x6.c
CommitLineData
d1db38c0
CL
1/*
2 * card driver for models with WM8776/WM8766 DACs (Xonar DS)
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
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.
9 *
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.
14 *
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/>.
17 */
18
19/*
20 * Xonar DS
21 * --------
22 *
23 * CMI8788:
24 *
25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input)
27 *
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
32 */
33
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>
41#include "xonar.h"
42#include "wm8776.h"
43#include "wm8766.h"
44
45#define GPIO_DS_HP_DETECT 0x0010
46#define GPIO_DS_INPUT_ROUTE 0x0040
47#define GPIO_DS_OUTPUT_ENABLE 0x0180
48
49#define LC_CONTROL_LIMITER 0x40000000
50#define LC_CONTROL_ALC 0x20000000
51
52struct xonar_wm87x6 {
53 struct xonar_generic generic;
54 u16 wm8776_regs[0x17];
55 u16 wm8766_regs[0x10];
fe6ce80a
CL
56 struct snd_kcontrol *line_adcmux_control;
57 struct snd_kcontrol *mic_adcmux_control;
d1db38c0
CL
58 struct snd_kcontrol *lc_controls[13];
59};
60
61static void wm8776_write(struct oxygen *chip,
62 unsigned int reg, unsigned int value)
63{
64 struct xonar_wm87x6 *data = chip->model_data;
65
66 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
67 OXYGEN_SPI_DATA_LENGTH_2 |
68 OXYGEN_SPI_CLOCK_160 |
69 (1 << OXYGEN_SPI_CODEC_SHIFT) |
70 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
71 (reg << 9) | value);
72 if (reg < ARRAY_SIZE(data->wm8776_regs)) {
faf4eb23 73 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
d1db38c0
CL
74 value &= ~WM8776_UPDATE;
75 data->wm8776_regs[reg] = value;
76 }
77}
78
79static void wm8776_write_cached(struct oxygen *chip,
80 unsigned int reg, unsigned int value)
81{
82 struct xonar_wm87x6 *data = chip->model_data;
83
84 if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
85 value != data->wm8776_regs[reg])
86 wm8776_write(chip, reg, value);
87}
88
89static void wm8766_write(struct oxygen *chip,
90 unsigned int reg, unsigned int value)
91{
92 struct xonar_wm87x6 *data = chip->model_data;
93
94 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
95 OXYGEN_SPI_DATA_LENGTH_2 |
96 OXYGEN_SPI_CLOCK_160 |
97 (0 << OXYGEN_SPI_CODEC_SHIFT) |
98 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
99 (reg << 9) | value);
100 if (reg < ARRAY_SIZE(data->wm8766_regs))
101 data->wm8766_regs[reg] = value;
102}
103
104static void wm8766_write_cached(struct oxygen *chip,
105 unsigned int reg, unsigned int value)
106{
107 struct xonar_wm87x6 *data = chip->model_data;
108
109 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
110 value != data->wm8766_regs[reg]) {
111 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113 value &= ~WM8766_UPDATE;
114 wm8766_write(chip, reg, value);
115 }
116}
117
118static void wm8776_registers_init(struct oxygen *chip)
119{
120 struct xonar_wm87x6 *data = chip->model_data;
121
122 wm8776_write(chip, WM8776_RESET, 0);
123 wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
124 WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
125 wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
126 wm8776_write(chip, WM8776_DACIFCTRL,
127 WM8776_DACFMT_LJUST | WM8776_DACWL_24);
128 wm8776_write(chip, WM8776_ADCIFCTRL,
129 data->wm8776_regs[WM8776_ADCIFCTRL]);
130 wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
131 wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
132 wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
133 wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
134 WM8776_UPDATE);
135 wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
136 wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
137 wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
138 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
139 wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
140}
141
142static void wm8766_registers_init(struct oxygen *chip)
143{
144 wm8766_write(chip, WM8766_RESET, 0);
145 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
146 wm8766_write(chip, WM8766_DAC_CTRL2,
147 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
148 wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
149 wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
150 wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
151 wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
152 wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
153 wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
154}
155
156static void wm8776_init(struct oxygen *chip)
157{
158 struct xonar_wm87x6 *data = chip->model_data;
159
160 data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
161 data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
162 data->wm8776_regs[WM8776_ADCIFCTRL] =
163 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
164 data->wm8776_regs[WM8776_MSTRCTRL] =
165 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
166 data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
167 data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
168 data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
169 data->wm8776_regs[WM8776_ADCMUX] = 0x001;
170 wm8776_registers_init(chip);
171}
172
173static void xonar_ds_init(struct oxygen *chip)
174{
175 struct xonar_wm87x6 *data = chip->model_data;
176
177 data->generic.anti_pop_delay = 300;
178 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
179
180 wm8776_init(chip);
181 wm8766_registers_init(chip);
182
183 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
184 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
185 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
186 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
187 chip->interrupt_mask |= OXYGEN_INT_GPIO;
188
189 xonar_enable_output(chip);
190
191 snd_component_add(chip->card, "WM8776");
192 snd_component_add(chip->card, "WM8766");
193}
194
195static void xonar_ds_cleanup(struct oxygen *chip)
196{
197 xonar_disable_output(chip);
4c25b932 198 wm8776_write(chip, WM8776_RESET, 0);
d1db38c0
CL
199}
200
201static void xonar_ds_suspend(struct oxygen *chip)
202{
203 xonar_ds_cleanup(chip);
204}
205
206static void xonar_ds_resume(struct oxygen *chip)
207{
208 wm8776_registers_init(chip);
209 wm8766_registers_init(chip);
210 xonar_enable_output(chip);
211}
212
213static void wm8776_adc_hardware_filter(unsigned int channel,
214 struct snd_pcm_hardware *hardware)
215{
216 if (channel == PCM_A) {
217 hardware->rates = SNDRV_PCM_RATE_32000 |
218 SNDRV_PCM_RATE_44100 |
219 SNDRV_PCM_RATE_48000 |
220 SNDRV_PCM_RATE_64000 |
221 SNDRV_PCM_RATE_88200 |
222 SNDRV_PCM_RATE_96000;
223 hardware->rate_max = 96000;
224 }
225}
226
227static void set_wm87x6_dac_params(struct oxygen *chip,
228 struct snd_pcm_hw_params *params)
229{
230}
231
232static void set_wm8776_adc_params(struct oxygen *chip,
233 struct snd_pcm_hw_params *params)
234{
235 u16 reg;
236
237 reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
238 if (params_rate(params) > 48000)
239 reg |= WM8776_ADCOSR;
240 wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
241}
242
243static void update_wm8776_volume(struct oxygen *chip)
244{
245 struct xonar_wm87x6 *data = chip->model_data;
246 u8 to_change;
247
248 if (chip->dac_volume[0] == chip->dac_volume[1]) {
249 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
250 chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
251 wm8776_write(chip, WM8776_DACMASTER,
252 chip->dac_volume[0] | WM8776_UPDATE);
253 data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
254 data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
255 }
256 } else {
257 to_change = (chip->dac_volume[0] !=
258 data->wm8776_regs[WM8776_DACLVOL]) << 0;
259 to_change |= (chip->dac_volume[1] !=
260 data->wm8776_regs[WM8776_DACLVOL]) << 1;
261 if (to_change & 1)
262 wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
263 ((to_change & 2) ? 0 : WM8776_UPDATE));
264 if (to_change & 2)
265 wm8776_write(chip, WM8776_DACRVOL,
266 chip->dac_volume[1] | WM8776_UPDATE);
267 }
268}
269
270static void update_wm87x6_volume(struct oxygen *chip)
271{
272 static const u8 wm8766_regs[6] = {
273 WM8766_LDA1, WM8766_RDA1,
274 WM8766_LDA2, WM8766_RDA2,
275 WM8766_LDA3, WM8766_RDA3,
276 };
277 struct xonar_wm87x6 *data = chip->model_data;
278 unsigned int i;
279 u8 to_change;
280
281 update_wm8776_volume(chip);
282 if (chip->dac_volume[2] == chip->dac_volume[3] &&
283 chip->dac_volume[2] == chip->dac_volume[4] &&
284 chip->dac_volume[2] == chip->dac_volume[5] &&
285 chip->dac_volume[2] == chip->dac_volume[6] &&
286 chip->dac_volume[2] == chip->dac_volume[7]) {
287 to_change = 0;
288 for (i = 0; i < 6; ++i)
289 if (chip->dac_volume[2] !=
290 data->wm8766_regs[wm8766_regs[i]])
291 to_change = 1;
292 if (to_change) {
293 wm8766_write(chip, WM8766_MASTDA,
294 chip->dac_volume[2] | WM8766_UPDATE);
295 for (i = 0; i < 6; ++i)
296 data->wm8766_regs[wm8766_regs[i]] =
297 chip->dac_volume[2];
298 }
299 } else {
300 to_change = 0;
301 for (i = 0; i < 6; ++i)
302 to_change |= (chip->dac_volume[2 + i] !=
303 data->wm8766_regs[wm8766_regs[i]]) << i;
304 for (i = 0; i < 6; ++i)
305 if (to_change & (1 << i))
306 wm8766_write(chip, wm8766_regs[i],
307 chip->dac_volume[2 + i] |
308 ((to_change & (0x3e << i))
309 ? 0 : WM8766_UPDATE));
310 }
311}
312
313static void update_wm8776_mute(struct oxygen *chip)
314{
315 wm8776_write_cached(chip, WM8776_DACMUTE,
316 chip->dac_mute ? WM8776_DMUTE : 0);
317}
318
319static void update_wm87x6_mute(struct oxygen *chip)
320{
321 update_wm8776_mute(chip);
322 wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
323 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
324}
325
326static void xonar_ds_gpio_changed(struct oxygen *chip)
327{
328 u16 bits;
329
330 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
331 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
332}
333
334static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
335 struct snd_ctl_elem_value *value)
336{
337 struct oxygen *chip = ctl->private_data;
338 struct xonar_wm87x6 *data = chip->model_data;
339 u16 bit = ctl->private_value & 0xffff;
340 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
341 bool invert = (ctl->private_value >> 24) & 1;
342
343 value->value.integer.value[0] =
344 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
345 return 0;
346}
347
348static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
349 struct snd_ctl_elem_value *value)
350{
351 struct oxygen *chip = ctl->private_data;
352 struct xonar_wm87x6 *data = chip->model_data;
353 u16 bit = ctl->private_value & 0xffff;
354 u16 reg_value;
355 unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
356 bool invert = (ctl->private_value >> 24) & 1;
357 int changed;
358
359 mutex_lock(&chip->mutex);
360 reg_value = data->wm8776_regs[reg_index] & ~bit;
361 if (value->value.integer.value[0] ^ invert)
362 reg_value |= bit;
363 changed = reg_value != data->wm8776_regs[reg_index];
364 if (changed)
365 wm8776_write(chip, reg_index, reg_value);
366 mutex_unlock(&chip->mutex);
367 return changed;
368}
369
370static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
371 struct snd_ctl_elem_info *info)
372{
373 static const char *const hld[16] = {
374 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
375 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
376 "341 ms", "683 ms", "1.37 s", "2.73 s",
377 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
378 };
379 static const char *const atk_lim[11] = {
380 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
381 "4 ms", "8 ms", "16 ms", "32 ms",
382 "64 ms", "128 ms", "256 ms",
383 };
384 static const char *const atk_alc[11] = {
385 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
386 "134 ms", "269 ms", "538 ms", "1.08 s",
387 "2.15 s", "4.3 s", "8.6 s",
388 };
389 static const char *const dcy_lim[11] = {
390 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
391 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
392 "307 ms", "614 ms", "1.23 s",
393 };
394 static const char *const dcy_alc[11] = {
395 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
396 "536 ms", "1.07 s", "2.14 s", "4.29 s",
397 "8.58 s", "17.2 s", "34.3 s",
398 };
399 static const char *const tranwin[8] = {
400 "0 us", "62.5 us", "125 us", "250 us",
401 "500 us", "1 ms", "2 ms", "4 ms",
402 };
403 u8 max;
404 const char *const *names;
405
406 max = (ctl->private_value >> 12) & 0xf;
407 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
408 info->count = 1;
409 info->value.enumerated.items = max + 1;
410 if (info->value.enumerated.item > max)
411 info->value.enumerated.item = max;
412 switch ((ctl->private_value >> 24) & 0x1f) {
413 case WM8776_ALCCTRL2:
414 names = hld;
415 break;
416 case WM8776_ALCCTRL3:
417 if (((ctl->private_value >> 20) & 0xf) == 0) {
418 if (ctl->private_value & LC_CONTROL_LIMITER)
419 names = atk_lim;
420 else
421 names = atk_alc;
422 } else {
423 if (ctl->private_value & LC_CONTROL_LIMITER)
424 names = dcy_lim;
425 else
426 names = dcy_alc;
427 }
428 break;
429 case WM8776_LIMITER:
430 names = tranwin;
431 break;
432 default:
433 return -ENXIO;
434 }
435 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
436 return 0;
437}
438
439static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
440 struct snd_ctl_elem_info *info)
441{
442 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
443 info->count = 1;
444 info->value.integer.min = (ctl->private_value >> 8) & 0xf;
445 info->value.integer.max = (ctl->private_value >> 12) & 0xf;
446 return 0;
447}
448
449static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
450{
451 struct oxygen *chip = ctl->private_data;
452 struct xonar_wm87x6 *data = chip->model_data;
453 unsigned int value, reg_index, mode;
454 u8 min, max, shift;
455 u16 mask, reg_value;
456 bool invert;
457
458 if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
459 WM8776_LCSEL_LIMITER)
460 mode = LC_CONTROL_LIMITER;
461 else
462 mode = LC_CONTROL_ALC;
463 if (!(ctl->private_value & mode))
464 return;
465
466 value = ctl->private_value & 0xf;
467 min = (ctl->private_value >> 8) & 0xf;
468 max = (ctl->private_value >> 12) & 0xf;
469 mask = (ctl->private_value >> 16) & 0xf;
470 shift = (ctl->private_value >> 20) & 0xf;
471 reg_index = (ctl->private_value >> 24) & 0x1f;
472 invert = (ctl->private_value >> 29) & 0x1;
473
474 if (invert)
475 value = max - (value - min);
476 reg_value = data->wm8776_regs[reg_index];
477 reg_value &= ~(mask << shift);
478 reg_value |= value << shift;
479 wm8776_write_cached(chip, reg_index, reg_value);
480}
481
482static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
483{
484 struct oxygen *chip = ctl->private_data;
485 u8 min, max;
486 int changed;
487
488 min = (ctl->private_value >> 8) & 0xf;
489 max = (ctl->private_value >> 12) & 0xf;
490 if (value < min || value > max)
491 return -EINVAL;
492 mutex_lock(&chip->mutex);
493 changed = value != (ctl->private_value & 0xf);
494 if (changed) {
495 ctl->private_value = (ctl->private_value & ~0xf) | value;
496 wm8776_field_set_from_ctl(ctl);
497 }
498 mutex_unlock(&chip->mutex);
499 return changed;
500}
501
502static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
503 struct snd_ctl_elem_value *value)
504{
505 value->value.enumerated.item[0] = ctl->private_value & 0xf;
506 return 0;
507}
508
509static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
510 struct snd_ctl_elem_value *value)
511{
512 value->value.integer.value[0] = ctl->private_value & 0xf;
513 return 0;
514}
515
516static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
517 struct snd_ctl_elem_value *value)
518{
519 return wm8776_field_set(ctl, value->value.enumerated.item[0]);
520}
521
522static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
523 struct snd_ctl_elem_value *value)
524{
525 return wm8776_field_set(ctl, value->value.integer.value[0]);
526}
527
528static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
529 struct snd_ctl_elem_info *info)
530{
531 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
532 info->count = 2;
533 info->value.integer.min = 0x79 - 60;
534 info->value.integer.max = 0x7f;
535 return 0;
536}
537
538static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
539 struct snd_ctl_elem_value *value)
540{
541 struct oxygen *chip = ctl->private_data;
542 struct xonar_wm87x6 *data = chip->model_data;
543
544 mutex_lock(&chip->mutex);
545 value->value.integer.value[0] =
546 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
547 value->value.integer.value[1] =
548 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
549 mutex_unlock(&chip->mutex);
550 return 0;
551}
552
553static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
554 struct snd_ctl_elem_value *value)
555{
556 struct oxygen *chip = ctl->private_data;
557 struct xonar_wm87x6 *data = chip->model_data;
558 u8 to_update;
559
560 mutex_lock(&chip->mutex);
561 to_update = (value->value.integer.value[0] !=
562 (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
563 << 0;
564 to_update |= (value->value.integer.value[1] !=
565 (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
566 << 1;
567 if (value->value.integer.value[0] == value->value.integer.value[1]) {
568 if (to_update) {
569 wm8776_write(chip, WM8776_HPMASTER,
570 value->value.integer.value[0] |
571 WM8776_HPZCEN | WM8776_UPDATE);
572 data->wm8776_regs[WM8776_HPLVOL] =
573 value->value.integer.value[0] | WM8776_HPZCEN;
574 data->wm8776_regs[WM8776_HPRVOL] =
575 value->value.integer.value[0] | WM8776_HPZCEN;
576 }
577 } else {
578 if (to_update & 1)
579 wm8776_write(chip, WM8776_HPLVOL,
580 value->value.integer.value[0] |
581 WM8776_HPZCEN |
582 ((to_update & 2) ? 0 : WM8776_UPDATE));
583 if (to_update & 2)
584 wm8776_write(chip, WM8776_HPRVOL,
585 value->value.integer.value[1] |
586 WM8776_HPZCEN | WM8776_UPDATE);
587 }
588 mutex_unlock(&chip->mutex);
589 return to_update != 0;
590}
591
592static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
593 struct snd_ctl_elem_value *value)
594{
595 struct oxygen *chip = ctl->private_data;
596 struct xonar_wm87x6 *data = chip->model_data;
597 unsigned int mux_bit = ctl->private_value;
598
599 value->value.integer.value[0] =
600 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
601 return 0;
602}
603
604static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
605 struct snd_ctl_elem_value *value)
606{
607 struct oxygen *chip = ctl->private_data;
608 struct xonar_wm87x6 *data = chip->model_data;
fe6ce80a 609 struct snd_kcontrol *other_ctl;
d1db38c0
CL
610 unsigned int mux_bit = ctl->private_value;
611 u16 reg;
612 int changed;
613
614 mutex_lock(&chip->mutex);
615 reg = data->wm8776_regs[WM8776_ADCMUX];
616 if (value->value.integer.value[0]) {
d1db38c0 617 reg |= mux_bit;
fe6ce80a
CL
618 /* line-in and mic-in are exclusive */
619 mux_bit ^= 3;
620 if (reg & mux_bit) {
621 reg &= ~mux_bit;
622 if (mux_bit == 1)
623 other_ctl = data->line_adcmux_control;
624 else
625 other_ctl = data->mic_adcmux_control;
626 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
627 &other_ctl->id);
628 }
d1db38c0
CL
629 } else
630 reg &= ~mux_bit;
631 changed = reg != data->wm8776_regs[WM8776_ADCMUX];
632 if (changed) {
633 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
634 reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
635 GPIO_DS_INPUT_ROUTE);
636 wm8776_write(chip, WM8776_ADCMUX, reg);
637 }
638 mutex_unlock(&chip->mutex);
639 return changed;
640}
641
642static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
643 struct snd_ctl_elem_info *info)
644{
645 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
646 info->count = 2;
647 info->value.integer.min = 0xa5;
648 info->value.integer.max = 0xff;
649 return 0;
650}
651
652static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
653 struct snd_ctl_elem_value *value)
654{
655 struct oxygen *chip = ctl->private_data;
656 struct xonar_wm87x6 *data = chip->model_data;
657
658 mutex_lock(&chip->mutex);
659 value->value.integer.value[0] =
660 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
661 value->value.integer.value[1] =
662 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
663 mutex_unlock(&chip->mutex);
664 return 0;
665}
666
667static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
668 struct snd_ctl_elem_value *value)
669{
670 struct oxygen *chip = ctl->private_data;
671 struct xonar_wm87x6 *data = chip->model_data;
672 int changed = 0;
673
674 mutex_lock(&chip->mutex);
675 changed = (value->value.integer.value[0] !=
676 (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
677 (value->value.integer.value[1] !=
678 (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
679 wm8776_write_cached(chip, WM8776_ADCLVOL,
680 value->value.integer.value[0] | WM8776_ZCA);
681 wm8776_write_cached(chip, WM8776_ADCRVOL,
682 value->value.integer.value[1] | WM8776_ZCA);
683 mutex_unlock(&chip->mutex);
684 return changed;
685}
686
687static int wm8776_level_control_info(struct snd_kcontrol *ctl,
688 struct snd_ctl_elem_info *info)
689{
690 static const char *const names[3] = {
691 "None", "Peak Limiter", "Automatic Level Control"
692 };
693 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
694 info->count = 1;
695 info->value.enumerated.items = 3;
696 if (info->value.enumerated.item >= 3)
697 info->value.enumerated.item = 2;
698 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
699 return 0;
700}
701
702static int wm8776_level_control_get(struct snd_kcontrol *ctl,
703 struct snd_ctl_elem_value *value)
704{
705 struct oxygen *chip = ctl->private_data;
706 struct xonar_wm87x6 *data = chip->model_data;
707
708 if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
709 value->value.enumerated.item[0] = 0;
710 else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
711 WM8776_LCSEL_LIMITER)
712 value->value.enumerated.item[0] = 1;
713 else
714 value->value.enumerated.item[0] = 2;
715 return 0;
716}
717
718static void activate_control(struct oxygen *chip,
719 struct snd_kcontrol *ctl, unsigned int mode)
720{
721 unsigned int access;
722
723 if (ctl->private_value & mode)
724 access = 0;
725 else
726 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
727 if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
728 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
729 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
730 }
731}
732
733static int wm8776_level_control_put(struct snd_kcontrol *ctl,
734 struct snd_ctl_elem_value *value)
735{
736 struct oxygen *chip = ctl->private_data;
737 struct xonar_wm87x6 *data = chip->model_data;
738 unsigned int mode = 0, i;
739 u16 ctrl1, ctrl2;
740 int changed;
741
742 if (value->value.enumerated.item[0] >= 3)
743 return -EINVAL;
744 mutex_lock(&chip->mutex);
745 changed = value->value.enumerated.item[0] != ctl->private_value;
746 if (changed) {
747 ctl->private_value = value->value.enumerated.item[0];
748 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
749 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
750 switch (value->value.enumerated.item[0]) {
751 default:
752 wm8776_write_cached(chip, WM8776_ALCCTRL2,
753 ctrl2 & ~WM8776_LCEN);
754 break;
755 case 1:
756 wm8776_write_cached(chip, WM8776_ALCCTRL1,
757 (ctrl1 & ~WM8776_LCSEL_MASK) |
758 WM8776_LCSEL_LIMITER);
759 wm8776_write_cached(chip, WM8776_ALCCTRL2,
760 ctrl2 | WM8776_LCEN);
761 mode = LC_CONTROL_LIMITER;
762 break;
763 case 2:
764 wm8776_write_cached(chip, WM8776_ALCCTRL1,
765 (ctrl1 & ~WM8776_LCSEL_MASK) |
766 WM8776_LCSEL_ALC_STEREO);
767 wm8776_write_cached(chip, WM8776_ALCCTRL2,
768 ctrl2 | WM8776_LCEN);
769 mode = LC_CONTROL_ALC;
770 break;
771 }
772 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
773 activate_control(chip, data->lc_controls[i], mode);
774 }
775 mutex_unlock(&chip->mutex);
776 return changed;
777}
778
779static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
780{
781 static const char *const names[2] = {
782 "None", "High-pass Filter"
783 };
784
785 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
786 info->count = 1;
787 info->value.enumerated.items = 2;
788 if (info->value.enumerated.item >= 2)
789 info->value.enumerated.item = 1;
790 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
791 return 0;
792}
793
794static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
795{
796 struct oxygen *chip = ctl->private_data;
797 struct xonar_wm87x6 *data = chip->model_data;
798
799 value->value.enumerated.item[0] =
800 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
801 return 0;
802}
803
804static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
805{
806 struct oxygen *chip = ctl->private_data;
807 struct xonar_wm87x6 *data = chip->model_data;
808 unsigned int reg;
809 int changed;
810
811 mutex_lock(&chip->mutex);
812 reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
813 if (!value->value.enumerated.item[0])
814 reg |= WM8776_ADCHPD;
815 changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
816 if (changed)
817 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
818 mutex_unlock(&chip->mutex);
819 return changed;
820}
821
822#define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
824 .name = xname, \
825 .info = snd_ctl_boolean_mono_info, \
826 .get = wm8776_bit_switch_get, \
827 .put = wm8776_bit_switch_put, \
828 .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
829}
830#define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
832 .name = xname, \
833 .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
834 ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
835#define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
836 _WM8776_FIELD_CTL(xname " Capture Enum", \
837 reg, shift, init, min, max, mask, flags), \
838 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
839 SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
840 .info = wm8776_field_enum_info, \
841 .get = wm8776_field_enum_get, \
842 .put = wm8776_field_enum_put, \
843}
844#define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
845 _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
846 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
847 SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
848 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
849 .info = wm8776_field_volume_info, \
850 .get = wm8776_field_volume_get, \
851 .put = wm8776_field_volume_put, \
852 .tlv = { .p = tlv_p }, \
853}
854
855static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
856static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
857static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
858static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
859static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
860static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
861static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
862static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
863
864static const struct snd_kcontrol_new ds_controls[] = {
865 {
866 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
867 .name = "Headphone Playback Volume",
868 .info = wm8776_hp_vol_info,
869 .get = wm8776_hp_vol_get,
870 .put = wm8776_hp_vol_put,
871 .tlv = { .p = wm8776_hp_db_scale },
872 },
873 WM8776_BIT_SWITCH("Headphone Playback Switch",
874 WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
875 {
876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877 .name = "Input Capture Volume",
878 .info = wm8776_input_vol_info,
879 .get = wm8776_input_vol_get,
880 .put = wm8776_input_vol_put,
881 .tlv = { .p = wm8776_adc_db_scale },
882 },
883 {
884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
885 .name = "Line Capture Switch",
886 .info = snd_ctl_boolean_mono_info,
887 .get = wm8776_input_mux_get,
888 .put = wm8776_input_mux_put,
889 .private_value = 1 << 0,
890 },
891 {
892 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
893 .name = "Mic Capture Switch",
894 .info = snd_ctl_boolean_mono_info,
895 .get = wm8776_input_mux_get,
896 .put = wm8776_input_mux_put,
897 .private_value = 1 << 1,
898 },
899 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
900 {
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .name = "ADC Filter Capture Enum",
903 .info = hpf_info,
904 .get = hpf_get,
905 .put = hpf_put,
906 },
907 {
908 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
909 .name = "Level Control Capture Enum",
910 .info = wm8776_level_control_info,
911 .get = wm8776_level_control_get,
912 .put = wm8776_level_control_put,
913 .private_value = 0,
914 },
915};
916static const struct snd_kcontrol_new lc_controls[] = {
917 WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
918 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
919 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
920 WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
921 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
922 LC_CONTROL_LIMITER),
923 WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
924 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
925 LC_CONTROL_LIMITER),
926 WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
927 WM8776_LIMITER, 4, 2, 0, 7, 0x7,
928 LC_CONTROL_LIMITER),
929 WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
930 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
931 LC_CONTROL_LIMITER,
932 wm8776_maxatten_lim_db_scale),
933 WM8776_FIELD_CTL_VOLUME("ALC Target Level",
934 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
935 LC_CONTROL_ALC, wm8776_lct_db_scale),
936 WM8776_FIELD_CTL_ENUM("ALC Attack Time",
937 WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
938 LC_CONTROL_ALC),
939 WM8776_FIELD_CTL_ENUM("ALC Decay Time",
940 WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
941 LC_CONTROL_ALC),
942 WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
943 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
944 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
945 WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
946 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
947 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
948 WM8776_FIELD_CTL_ENUM("ALC Hold Time",
949 WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
950 LC_CONTROL_ALC),
951 WM8776_BIT_SWITCH("Noise Gate Capture Switch",
952 WM8776_NOISEGATE, WM8776_NGAT, 0,
953 LC_CONTROL_ALC),
954 WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
955 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
956 LC_CONTROL_ALC, wm8776_ngth_db_scale),
957};
958
959static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
960{
961 if (!strncmp(template->name, "CD Capture ", 11))
962 return 1; /* no CD input */
963 return 0;
964}
965
966static int xonar_ds_mixer_init(struct oxygen *chip)
967{
968 struct xonar_wm87x6 *data = chip->model_data;
969 unsigned int i;
970 struct snd_kcontrol *ctl;
971 int err;
972
973 for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
974 ctl = snd_ctl_new1(&ds_controls[i], chip);
975 if (!ctl)
976 return -ENOMEM;
977 err = snd_ctl_add(chip->card, ctl);
978 if (err < 0)
979 return err;
fe6ce80a
CL
980 if (!strcmp(ctl->id.name, "Line Capture Switch"))
981 data->line_adcmux_control = ctl;
982 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
983 data->mic_adcmux_control = ctl;
d1db38c0 984 }
fe6ce80a
CL
985 if (!data->line_adcmux_control || !data->mic_adcmux_control)
986 return -ENXIO;
d1db38c0
CL
987 BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
988 for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
989 ctl = snd_ctl_new1(&lc_controls[i], chip);
990 if (!ctl)
991 return -ENOMEM;
992 err = snd_ctl_add(chip->card, ctl);
993 if (err < 0)
994 return err;
995 data->lc_controls[i] = ctl;
996 }
997 return 0;
998}
999
1000static const struct oxygen_model model_xonar_ds = {
1001 .shortname = "Xonar DS",
1002 .longname = "Asus Virtuoso 200",
1003 .chip = "AV200",
1004 .init = xonar_ds_init,
1005 .control_filter = xonar_ds_control_filter,
1006 .mixer_init = xonar_ds_mixer_init,
1007 .cleanup = xonar_ds_cleanup,
1008 .suspend = xonar_ds_suspend,
1009 .resume = xonar_ds_resume,
1010 .pcm_hardware_filter = wm8776_adc_hardware_filter,
1011 .get_i2s_mclk = oxygen_default_i2s_mclk,
1012 .set_dac_params = set_wm87x6_dac_params,
1013 .set_adc_params = set_wm8776_adc_params,
1014 .update_dac_volume = update_wm87x6_volume,
1015 .update_dac_mute = update_wm87x6_mute,
1016 .gpio_changed = xonar_ds_gpio_changed,
1017 .dac_tlv = wm87x6_dac_db_scale,
1018 .model_data_size = sizeof(struct xonar_wm87x6),
1019 .device_config = PLAYBACK_0_TO_I2S |
1020 PLAYBACK_1_TO_SPDIF |
1021 CAPTURE_0_FROM_I2S_1,
1022 .dac_channels = 8,
1023 .dac_volume_min = 255 - 2*60,
1024 .dac_volume_max = 255,
1025 .function_flags = OXYGEN_FUNCTION_SPI,
1026 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1027 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1028};
1029
1030int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
1031 const struct pci_device_id *id)
1032{
1033 switch (id->subdevice) {
1034 case 0x838e:
1035 chip->model = model_xonar_ds;
1036 break;
1037 default:
1038 return -EINVAL;
1039 }
1040 return 0;
1041}