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