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