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