root/sound/pci/oxygen/xonar_wm87x6.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wm8776_write_spi
  2. wm8776_write_i2c
  3. wm8776_write
  4. wm8776_write_cached
  5. wm8766_write
  6. wm8766_write_cached
  7. wm8776_registers_init
  8. wm8766_registers_init
  9. wm8776_init
  10. wm8766_init
  11. xonar_ds_handle_hp_jack
  12. xonar_ds_init
  13. xonar_hdav_slim_init
  14. xonar_ds_cleanup
  15. xonar_hdav_slim_cleanup
  16. xonar_ds_suspend
  17. xonar_hdav_slim_suspend
  18. xonar_ds_resume
  19. xonar_hdav_slim_resume
  20. wm8776_adc_hardware_filter
  21. xonar_hdav_slim_hardware_filter
  22. set_wm87x6_dac_params
  23. set_wm8776_adc_params
  24. set_hdav_slim_dac_params
  25. update_wm8776_volume
  26. update_wm87x6_volume
  27. update_wm8776_mute
  28. update_wm87x6_mute
  29. update_wm8766_center_lfe_mix
  30. xonar_ds_gpio_changed
  31. wm8776_bit_switch_get
  32. wm8776_bit_switch_put
  33. wm8776_field_enum_info
  34. wm8776_field_volume_info
  35. wm8776_field_set_from_ctl
  36. wm8776_field_set
  37. wm8776_field_enum_get
  38. wm8776_field_volume_get
  39. wm8776_field_enum_put
  40. wm8776_field_volume_put
  41. wm8776_hp_vol_info
  42. wm8776_hp_vol_get
  43. wm8776_hp_vol_put
  44. wm8776_input_mux_get
  45. wm8776_input_mux_put
  46. wm8776_input_vol_info
  47. wm8776_input_vol_get
  48. wm8776_input_vol_put
  49. wm8776_level_control_info
  50. wm8776_level_control_get
  51. activate_control
  52. wm8776_level_control_put
  53. hpf_info
  54. hpf_get
  55. hpf_put
  56. add_lc_controls
  57. xonar_ds_mixer_init
  58. xonar_hdav_slim_mixer_init
  59. dump_wm8776_registers
  60. dump_wm87x6_registers
  61. get_xonar_wm87x6_model

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

/* [<][>][^][v][top][bottom][index][help] */