linux/sound/pci/oxygen/xonar_wm87x6.c
<<
>>
Prefs
   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
  79struct 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
  90static 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
 101static 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
 108static 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
 125static 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
 135static 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
 154static 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
 164static 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
 189static 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
 206static 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
 223static 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
 232static 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
 257static 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
 285static 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
 305static void xonar_ds_cleanup(struct oxygen *chip)
 306{
 307        xonar_disable_output(chip);
 308        wm8776_write(chip, WM8776_RESET, 0);
 309}
 310
 311static 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
 319static void xonar_ds_suspend(struct oxygen *chip)
 320{
 321        xonar_ds_cleanup(chip);
 322}
 323
 324static void xonar_hdav_slim_suspend(struct oxygen *chip)
 325{
 326        xonar_hdav_slim_cleanup(chip);
 327}
 328
 329static 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
 337static 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
 346static 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
 360static 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
 367static void set_wm87x6_dac_params(struct oxygen *chip,
 368                                  struct snd_pcm_hw_params *params)
 369{
 370}
 371
 372static 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
 383static 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
 391static 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
 418static 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
 461static void update_wm8776_mute(struct oxygen *chip)
 462{
 463        wm8776_write_cached(chip, WM8776_DACMUTE,
 464                            chip->dac_mute ? WM8776_DMUTE : 0);
 465}
 466
 467static 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
 474static 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
 492static void xonar_ds_gpio_changed(struct oxygen *chip)
 493{
 494        xonar_ds_handle_hp_jack(chip);
 495}
 496
 497static 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
 511static 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
 533static 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
 596static 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
 606static 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
 639static 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
 659static 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
 666static 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
 673static 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
 679static 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
 685static 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
 695static 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
 710static 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
 749static 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
 761static 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
 799static 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
 809static 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
 824static 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
 844static 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
 854static 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
 870static 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
 885static 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
 931static 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
 940static 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
 950static 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
1001static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
1002static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
1003static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
1004static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
1005static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
1006static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
1007static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
1008static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
1009
1010static 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};
1065static 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};
1112static 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
1155static 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
1175static 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
1200static 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
1218static 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
1233static 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
1246static 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
1279static 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
1312int 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}
1332