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