cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xonar_wm87x6.c (38719B)


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