18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ALSA driver for ICEnsemble VT1724 (Envy24HT) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Lowlevel functions for Terratec Aureon cards 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * NOTES: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data. 128c2ecf20Sopenharmony_ci * both wm and akm codecs are pretty similar, so we can integrate 138c2ecf20Sopenharmony_ci * both controls in the future, once if wm codecs are reused in 148c2ecf20Sopenharmony_ci * many boards. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - DAC digital volumes are not implemented in the mixer. 178c2ecf20Sopenharmony_ci * if they show better response than DAC analog volumes, we can use them 188c2ecf20Sopenharmony_ci * instead. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards 218c2ecf20Sopenharmony_ci * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca> 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * version 0.82: Stable / not all features work yet (no communication with AC97 secondary) 248c2ecf20Sopenharmony_ci * added 64x/128x oversampling switch (should be 64x only for 96khz) 258c2ecf20Sopenharmony_ci * fixed some recording labels (still need to check the rest) 268c2ecf20Sopenharmony_ci * recording is working probably thanks to correct wm8770 initialization 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * version 0.5: Initial release: 298c2ecf20Sopenharmony_ci * working: analog output, mixer, headphone amplifier switch 308c2ecf20Sopenharmony_ci * not working: prety much everything else, at least i could verify that 318c2ecf20Sopenharmony_ci * we have no digital output, no capture, pretty bad clicks and poops 328c2ecf20Sopenharmony_ci * on mixer switch and other coll stuff. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/delay.h> 368c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 378c2ecf20Sopenharmony_ci#include <linux/init.h> 388c2ecf20Sopenharmony_ci#include <linux/slab.h> 398c2ecf20Sopenharmony_ci#include <linux/mutex.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#include <sound/core.h> 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#include "ice1712.h" 448c2ecf20Sopenharmony_ci#include "envy24ht.h" 458c2ecf20Sopenharmony_ci#include "aureon.h" 468c2ecf20Sopenharmony_ci#include <sound/tlv.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* AC97 register cache for Aureon */ 498c2ecf20Sopenharmony_cistruct aureon_spec { 508c2ecf20Sopenharmony_ci unsigned short stac9744[64]; 518c2ecf20Sopenharmony_ci unsigned int cs8415_mux; 528c2ecf20Sopenharmony_ci unsigned short master[2]; 538c2ecf20Sopenharmony_ci unsigned short vol[8]; 548c2ecf20Sopenharmony_ci unsigned char pca9554_out; 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* WM8770 registers */ 588c2ecf20Sopenharmony_ci#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ 598c2ecf20Sopenharmony_ci#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ 608c2ecf20Sopenharmony_ci#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ 618c2ecf20Sopenharmony_ci#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ 628c2ecf20Sopenharmony_ci#define WM_PHASE_SWAP 0x12 /* DAC phase */ 638c2ecf20Sopenharmony_ci#define WM_DAC_CTRL1 0x13 /* DAC control bits */ 648c2ecf20Sopenharmony_ci#define WM_MUTE 0x14 /* mute controls */ 658c2ecf20Sopenharmony_ci#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ 668c2ecf20Sopenharmony_ci#define WM_INT_CTRL 0x16 /* interface control */ 678c2ecf20Sopenharmony_ci#define WM_MASTER 0x17 /* master clock and mode */ 688c2ecf20Sopenharmony_ci#define WM_POWERDOWN 0x18 /* power-down controls */ 698c2ecf20Sopenharmony_ci#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ 708c2ecf20Sopenharmony_ci#define WM_ADC_MUX 0x1b /* input MUX */ 718c2ecf20Sopenharmony_ci#define WM_OUT_MUX1 0x1c /* output MUX */ 728c2ecf20Sopenharmony_ci#define WM_OUT_MUX2 0x1e /* output MUX */ 738c2ecf20Sopenharmony_ci#define WM_RESET 0x1f /* software reset */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* CS8415A registers */ 768c2ecf20Sopenharmony_ci#define CS8415_CTRL1 0x01 778c2ecf20Sopenharmony_ci#define CS8415_CTRL2 0x02 788c2ecf20Sopenharmony_ci#define CS8415_QSUB 0x14 798c2ecf20Sopenharmony_ci#define CS8415_RATIO 0x1E 808c2ecf20Sopenharmony_ci#define CS8415_C_BUFFER 0x20 818c2ecf20Sopenharmony_ci#define CS8415_ID 0x7F 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* PCA9554 registers */ 848c2ecf20Sopenharmony_ci#define PCA9554_DEV 0x40 /* I2C device address */ 858c2ecf20Sopenharmony_ci#define PCA9554_IN 0x00 /* input port */ 868c2ecf20Sopenharmony_ci#define PCA9554_OUT 0x01 /* output port */ 878c2ecf20Sopenharmony_ci#define PCA9554_INVERT 0x02 /* input invert */ 888c2ecf20Sopenharmony_ci#define PCA9554_DIR 0x03 /* port directions */ 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * Aureon Universe additional controls using PCA9554 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* 958c2ecf20Sopenharmony_ci * Send data to pca9554 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_cistatic void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg, 988c2ecf20Sopenharmony_ci unsigned char data) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci unsigned int tmp; 1018c2ecf20Sopenharmony_ci int i, j; 1028c2ecf20Sopenharmony_ci unsigned char dev = PCA9554_DEV; /* ID 0100000, write */ 1038c2ecf20Sopenharmony_ci unsigned char val = 0; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci tmp = snd_ice1712_gpio_read(ice); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK| 1088c2ecf20Sopenharmony_ci AUREON_WM_RW|AUREON_WM_CS| 1098c2ecf20Sopenharmony_ci AUREON_CS8415_CS)); 1108c2ecf20Sopenharmony_ci tmp |= AUREON_WM_RW; 1118c2ecf20Sopenharmony_ci tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_MOSI; 1148c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1158c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1168c2ecf20Sopenharmony_ci udelay(50); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * send i2c stop condition and start condition 1208c2ecf20Sopenharmony_ci * to obtain sane state 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 1238c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1248c2ecf20Sopenharmony_ci udelay(50); 1258c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_MOSI; 1268c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1278c2ecf20Sopenharmony_ci udelay(100); 1288c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_MOSI; 1298c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1308c2ecf20Sopenharmony_ci udelay(50); 1318c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1328c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1338c2ecf20Sopenharmony_ci udelay(100); 1348c2ecf20Sopenharmony_ci /* 1358c2ecf20Sopenharmony_ci * send device address, command and value, 1368c2ecf20Sopenharmony_ci * skipping ack cycles in between 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci for (j = 0; j < 3; j++) { 1398c2ecf20Sopenharmony_ci switch (j) { 1408c2ecf20Sopenharmony_ci case 0: 1418c2ecf20Sopenharmony_ci val = dev; 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case 1: 1448c2ecf20Sopenharmony_ci val = reg; 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci case 2: 1478c2ecf20Sopenharmony_ci val = data; 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci for (i = 7; i >= 0; i--) { 1518c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1528c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1538c2ecf20Sopenharmony_ci udelay(40); 1548c2ecf20Sopenharmony_ci if (val & (1 << i)) 1558c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_MOSI; 1568c2ecf20Sopenharmony_ci else 1578c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_MOSI; 1588c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1598c2ecf20Sopenharmony_ci udelay(40); 1608c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 1618c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1628c2ecf20Sopenharmony_ci udelay(40); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1658c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1668c2ecf20Sopenharmony_ci udelay(40); 1678c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 1688c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1698c2ecf20Sopenharmony_ci udelay(40); 1708c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1718c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1728c2ecf20Sopenharmony_ci udelay(40); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 1758c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1768c2ecf20Sopenharmony_ci udelay(40); 1778c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_MOSI; 1788c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1798c2ecf20Sopenharmony_ci udelay(40); 1808c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 1818c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1828c2ecf20Sopenharmony_ci udelay(50); 1838c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_MOSI; 1848c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 1858c2ecf20Sopenharmony_ci udelay(100); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol, 1898c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci static const char * const texts[3] = 1928c2ecf20Sopenharmony_ci {"Internal Aux", "Wavetable", "Rear Line-In"}; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 3, texts); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol, 1988c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2018c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 2028c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = spec->pca9554_out; 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol, 2078c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2108c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 2118c2ecf20Sopenharmony_ci unsigned char oval, nval; 2128c2ecf20Sopenharmony_ci int change; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci nval = ucontrol->value.enumerated.item[0]; 2158c2ecf20Sopenharmony_ci if (nval >= 3) 2168c2ecf20Sopenharmony_ci return -EINVAL; 2178c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 2188c2ecf20Sopenharmony_ci oval = spec->pca9554_out; 2198c2ecf20Sopenharmony_ci change = (oval != nval); 2208c2ecf20Sopenharmony_ci if (change) { 2218c2ecf20Sopenharmony_ci aureon_pca9554_write(ice, PCA9554_OUT, nval); 2228c2ecf20Sopenharmony_ci spec->pca9554_out = nval; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 2258c2ecf20Sopenharmony_ci return change; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, 2308c2ecf20Sopenharmony_ci unsigned short val) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 2338c2ecf20Sopenharmony_ci unsigned int tmp; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Send address to XILINX chip */ 2368c2ecf20Sopenharmony_ci tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F); 2378c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2388c2ecf20Sopenharmony_ci udelay(10); 2398c2ecf20Sopenharmony_ci tmp |= AUREON_AC97_ADDR; 2408c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2418c2ecf20Sopenharmony_ci udelay(10); 2428c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_ADDR; 2438c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2448c2ecf20Sopenharmony_ci udelay(10); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* Send low-order byte to XILINX chip */ 2478c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_DATA_MASK; 2488c2ecf20Sopenharmony_ci tmp |= val & AUREON_AC97_DATA_MASK; 2498c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2508c2ecf20Sopenharmony_ci udelay(10); 2518c2ecf20Sopenharmony_ci tmp |= AUREON_AC97_DATA_LOW; 2528c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2538c2ecf20Sopenharmony_ci udelay(10); 2548c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_DATA_LOW; 2558c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2568c2ecf20Sopenharmony_ci udelay(10); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Send high-order byte to XILINX chip */ 2598c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_DATA_MASK; 2608c2ecf20Sopenharmony_ci tmp |= (val >> 8) & AUREON_AC97_DATA_MASK; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2638c2ecf20Sopenharmony_ci udelay(10); 2648c2ecf20Sopenharmony_ci tmp |= AUREON_AC97_DATA_HIGH; 2658c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2668c2ecf20Sopenharmony_ci udelay(10); 2678c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_DATA_HIGH; 2688c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2698c2ecf20Sopenharmony_ci udelay(10); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* Instruct XILINX chip to parse the data to the STAC9744 chip */ 2728c2ecf20Sopenharmony_ci tmp |= AUREON_AC97_COMMIT; 2738c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2748c2ecf20Sopenharmony_ci udelay(10); 2758c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_COMMIT; 2768c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 2778c2ecf20Sopenharmony_ci udelay(10); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Store the data in out private buffer */ 2808c2ecf20Sopenharmony_ci spec->stac9744[(reg & 0x7F) >> 1] = val; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 2868c2ecf20Sopenharmony_ci return spec->stac9744[(reg & 0x7F) >> 1]; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* 2908c2ecf20Sopenharmony_ci * Initialize STAC9744 chip 2918c2ecf20Sopenharmony_ci */ 2928c2ecf20Sopenharmony_cistatic int aureon_ac97_init(struct snd_ice1712 *ice) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 2958c2ecf20Sopenharmony_ci int i; 2968c2ecf20Sopenharmony_ci static const unsigned short ac97_defaults[] = { 2978c2ecf20Sopenharmony_ci 0x00, 0x9640, 2988c2ecf20Sopenharmony_ci 0x02, 0x8000, 2998c2ecf20Sopenharmony_ci 0x04, 0x8000, 3008c2ecf20Sopenharmony_ci 0x06, 0x8000, 3018c2ecf20Sopenharmony_ci 0x0C, 0x8008, 3028c2ecf20Sopenharmony_ci 0x0E, 0x8008, 3038c2ecf20Sopenharmony_ci 0x10, 0x8808, 3048c2ecf20Sopenharmony_ci 0x12, 0x8808, 3058c2ecf20Sopenharmony_ci 0x14, 0x8808, 3068c2ecf20Sopenharmony_ci 0x16, 0x8808, 3078c2ecf20Sopenharmony_ci 0x18, 0x8808, 3088c2ecf20Sopenharmony_ci 0x1C, 0x8000, 3098c2ecf20Sopenharmony_ci 0x26, 0x000F, 3108c2ecf20Sopenharmony_ci 0x28, 0x0201, 3118c2ecf20Sopenharmony_ci 0x2C, 0xBB80, 3128c2ecf20Sopenharmony_ci 0x32, 0xBB80, 3138c2ecf20Sopenharmony_ci 0x7C, 0x8384, 3148c2ecf20Sopenharmony_ci 0x7E, 0x7644, 3158c2ecf20Sopenharmony_ci (unsigned short)-1 3168c2ecf20Sopenharmony_ci }; 3178c2ecf20Sopenharmony_ci unsigned int tmp; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Cold reset */ 3208c2ecf20Sopenharmony_ci tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK; 3218c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 3228c2ecf20Sopenharmony_ci udelay(3); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci tmp &= ~AUREON_AC97_RESET; 3258c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 3268c2ecf20Sopenharmony_ci udelay(3); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci tmp |= AUREON_AC97_RESET; 3298c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 3308c2ecf20Sopenharmony_ci udelay(3); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci memset(&spec->stac9744, 0, sizeof(spec->stac9744)); 3338c2ecf20Sopenharmony_ci for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2) 3348c2ecf20Sopenharmony_ci spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1]; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* Unmute AC'97 master volume permanently - muting is done by WM8770 */ 3378c2ecf20Sopenharmony_ci aureon_ac97_write(ice, AC97_MASTER, 0x0000); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci#define AUREON_AC97_STEREO 0x80 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * AC'97 volume controls 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_cistatic int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 3508c2ecf20Sopenharmony_ci uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1; 3518c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 3528c2ecf20Sopenharmony_ci uinfo->value.integer.max = 31; 3538c2ecf20Sopenharmony_ci return 0; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 3598c2ecf20Sopenharmony_ci unsigned short vol; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); 3648c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); 3658c2ecf20Sopenharmony_ci if (kcontrol->private_value & AUREON_AC97_STEREO) 3668c2ecf20Sopenharmony_ci ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 3698c2ecf20Sopenharmony_ci return 0; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 3758c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 3768c2ecf20Sopenharmony_ci int change; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); 3818c2ecf20Sopenharmony_ci nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F; 3828c2ecf20Sopenharmony_ci if (kcontrol->private_value & AUREON_AC97_STEREO) 3838c2ecf20Sopenharmony_ci nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00; 3848c2ecf20Sopenharmony_ci nvol |= ovol & ~0x1F1F; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci change = (ovol != nvol); 3878c2ecf20Sopenharmony_ci if (change) 3888c2ecf20Sopenharmony_ci aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci return change; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* 3968c2ecf20Sopenharmony_ci * AC'97 mute controls 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_ci#define aureon_ac97_mute_info snd_ctl_boolean_mono_info 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = aureon_ac97_read(ice, 4078c2ecf20Sopenharmony_ci kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 4108c2ecf20Sopenharmony_ci return 0; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 4168c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 4178c2ecf20Sopenharmony_ci int change; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); 4228c2ecf20Sopenharmony_ci nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci change = (ovol != nvol); 4258c2ecf20Sopenharmony_ci if (change) 4268c2ecf20Sopenharmony_ci aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci return change; 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci/* 4348c2ecf20Sopenharmony_ci * AC'97 mute controls 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_ci#define aureon_ac97_micboost_info snd_ctl_boolean_mono_info 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 4478c2ecf20Sopenharmony_ci return 0; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 4538c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 4548c2ecf20Sopenharmony_ci int change; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci ovol = aureon_ac97_read(ice, AC97_MIC); 4598c2ecf20Sopenharmony_ci nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci change = (ovol != nvol); 4628c2ecf20Sopenharmony_ci if (change) 4638c2ecf20Sopenharmony_ci aureon_ac97_write(ice, AC97_MIC, nvol); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci return change; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci/* 4718c2ecf20Sopenharmony_ci * write data in the SPI mode 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_cistatic void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci unsigned int tmp; 4768c2ecf20Sopenharmony_ci int i; 4778c2ecf20Sopenharmony_ci unsigned int mosi, clk; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci tmp = snd_ice1712_gpio_read(ice); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || 4828c2ecf20Sopenharmony_ci ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) { 4838c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS)); 4848c2ecf20Sopenharmony_ci mosi = PRODIGY_SPI_MOSI; 4858c2ecf20Sopenharmony_ci clk = PRODIGY_SPI_CLK; 4868c2ecf20Sopenharmony_ci } else { 4878c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK| 4888c2ecf20Sopenharmony_ci AUREON_WM_CS|AUREON_CS8415_CS)); 4898c2ecf20Sopenharmony_ci mosi = AUREON_SPI_MOSI; 4908c2ecf20Sopenharmony_ci clk = AUREON_SPI_CLK; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci tmp |= AUREON_WM_RW; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci tmp &= ~cs; 4968c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 4978c2ecf20Sopenharmony_ci udelay(1); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci for (i = bits - 1; i >= 0; i--) { 5008c2ecf20Sopenharmony_ci tmp &= ~clk; 5018c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5028c2ecf20Sopenharmony_ci udelay(1); 5038c2ecf20Sopenharmony_ci if (data & (1 << i)) 5048c2ecf20Sopenharmony_ci tmp |= mosi; 5058c2ecf20Sopenharmony_ci else 5068c2ecf20Sopenharmony_ci tmp &= ~mosi; 5078c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5088c2ecf20Sopenharmony_ci udelay(1); 5098c2ecf20Sopenharmony_ci tmp |= clk; 5108c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5118c2ecf20Sopenharmony_ci udelay(1); 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci tmp &= ~clk; 5158c2ecf20Sopenharmony_ci tmp |= cs; 5168c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5178c2ecf20Sopenharmony_ci udelay(1); 5188c2ecf20Sopenharmony_ci tmp |= clk; 5198c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5208c2ecf20Sopenharmony_ci udelay(1); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci/* 5248c2ecf20Sopenharmony_ci * Read data in SPI mode 5258c2ecf20Sopenharmony_ci */ 5268c2ecf20Sopenharmony_cistatic void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, 5278c2ecf20Sopenharmony_ci unsigned int data, int bits, unsigned char *buffer, int size) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci int i, j; 5308c2ecf20Sopenharmony_ci unsigned int tmp; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS; 5338c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5348c2ecf20Sopenharmony_ci tmp &= ~cs; 5358c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5368c2ecf20Sopenharmony_ci udelay(1); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci for (i = bits-1; i >= 0; i--) { 5398c2ecf20Sopenharmony_ci if (data & (1 << i)) 5408c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_MOSI; 5418c2ecf20Sopenharmony_ci else 5428c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_MOSI; 5438c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5448c2ecf20Sopenharmony_ci udelay(1); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 5478c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5488c2ecf20Sopenharmony_ci udelay(1); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 5518c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5528c2ecf20Sopenharmony_ci udelay(1); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci for (j = 0; j < size; j++) { 5568c2ecf20Sopenharmony_ci unsigned char outdata = 0; 5578c2ecf20Sopenharmony_ci for (i = 7; i >= 0; i--) { 5588c2ecf20Sopenharmony_ci tmp = snd_ice1712_gpio_read(ice); 5598c2ecf20Sopenharmony_ci outdata <<= 1; 5608c2ecf20Sopenharmony_ci outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0; 5618c2ecf20Sopenharmony_ci udelay(1); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci tmp |= AUREON_SPI_CLK; 5648c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5658c2ecf20Sopenharmony_ci udelay(1); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci tmp &= ~AUREON_SPI_CLK; 5688c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5698c2ecf20Sopenharmony_ci udelay(1); 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci buffer[j] = outdata; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci tmp |= cs; 5758c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci unsigned char val; 5818c2ecf20Sopenharmony_ci aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); 5828c2ecf20Sopenharmony_ci aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1); 5838c2ecf20Sopenharmony_ci return val; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, 5878c2ecf20Sopenharmony_ci unsigned char *buffer, int size) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); 5908c2ecf20Sopenharmony_ci aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size); 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, 5948c2ecf20Sopenharmony_ci unsigned char val) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci/* 6008c2ecf20Sopenharmony_ci * get the current register value of WM codec 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_cistatic unsigned short wm_get(struct snd_ice1712 *ice, int reg) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci reg <<= 1; 6058c2ecf20Sopenharmony_ci return ((unsigned short)ice->akm[0].images[reg] << 8) | 6068c2ecf20Sopenharmony_ci ice->akm[0].images[reg + 1]; 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci/* 6108c2ecf20Sopenharmony_ci * set the register value of WM codec 6118c2ecf20Sopenharmony_ci */ 6128c2ecf20Sopenharmony_cistatic void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci aureon_spi_write(ice, 6158c2ecf20Sopenharmony_ci ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || 6168c2ecf20Sopenharmony_ci ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ? 6178c2ecf20Sopenharmony_ci PRODIGY_WM_CS : AUREON_WM_CS), 6188c2ecf20Sopenharmony_ci (reg << 9) | (val & 0x1ff), 16); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci/* 6228c2ecf20Sopenharmony_ci * set the register value of WM codec and remember it 6238c2ecf20Sopenharmony_ci */ 6248c2ecf20Sopenharmony_cistatic void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) 6258c2ecf20Sopenharmony_ci{ 6268c2ecf20Sopenharmony_ci wm_put_nocache(ice, reg, val); 6278c2ecf20Sopenharmony_ci reg <<= 1; 6288c2ecf20Sopenharmony_ci ice->akm[0].images[reg] = val >> 8; 6298c2ecf20Sopenharmony_ci ice->akm[0].images[reg + 1] = val; 6308c2ecf20Sopenharmony_ci} 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci/* 6338c2ecf20Sopenharmony_ci */ 6348c2ecf20Sopenharmony_ci#define aureon_mono_bool_info snd_ctl_boolean_mono_info 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci/* 6378c2ecf20Sopenharmony_ci * AC'97 master playback mute controls (Mute on WM8770 chip) 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_ci#define aureon_ac97_mmute_info snd_ctl_boolean_mono_info 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 6508c2ecf20Sopenharmony_ci return 0; 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 6568c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 6578c2ecf20Sopenharmony_ci int change; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci ovol = wm_get(ice, WM_OUT_MUX1); 6628c2ecf20Sopenharmony_ci nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00); 6638c2ecf20Sopenharmony_ci change = (ovol != nvol); 6648c2ecf20Sopenharmony_ci if (change) 6658c2ecf20Sopenharmony_ci wm_put(ice, WM_OUT_MUX1, nvol); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return change; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1); 6738c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); 6748c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); 6758c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); 6768c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci#define WM_VOL_MAX 100 6798c2ecf20Sopenharmony_ci#define WM_VOL_CNT 101 /* 0dB .. -100dB */ 6808c2ecf20Sopenharmony_ci#define WM_VOL_MUTE 0x8000 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci unsigned char nvol; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) { 6878c2ecf20Sopenharmony_ci nvol = 0; 6888c2ecf20Sopenharmony_ci } else { 6898c2ecf20Sopenharmony_ci nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) / 6908c2ecf20Sopenharmony_ci WM_VOL_MAX; 6918c2ecf20Sopenharmony_ci nvol += 0x1b; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci wm_put(ice, index, nvol); 6958c2ecf20Sopenharmony_ci wm_put_nocache(ice, index, 0x180 | nvol); 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci/* 6998c2ecf20Sopenharmony_ci * DAC mute control 7008c2ecf20Sopenharmony_ci */ 7018c2ecf20Sopenharmony_ci#define wm_pcm_mute_info snd_ctl_boolean_mono_info 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistatic int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 7088c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; 7098c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 7108c2ecf20Sopenharmony_ci return 0; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7168c2ecf20Sopenharmony_ci unsigned short nval, oval; 7178c2ecf20Sopenharmony_ci int change; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 7208c2ecf20Sopenharmony_ci oval = wm_get(ice, WM_MUTE); 7218c2ecf20Sopenharmony_ci nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); 7228c2ecf20Sopenharmony_ci change = (oval != nval); 7238c2ecf20Sopenharmony_ci if (change) 7248c2ecf20Sopenharmony_ci wm_put(ice, WM_MUTE, nval); 7258c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci return change; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci/* 7318c2ecf20Sopenharmony_ci * Master volume attenuation mixer control 7328c2ecf20Sopenharmony_ci */ 7338c2ecf20Sopenharmony_cistatic int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 7368c2ecf20Sopenharmony_ci uinfo->count = 2; 7378c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 7388c2ecf20Sopenharmony_ci uinfo->value.integer.max = WM_VOL_MAX; 7398c2ecf20Sopenharmony_ci return 0; 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7458c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 7468c2ecf20Sopenharmony_ci int i; 7478c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) 7488c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] = 7498c2ecf20Sopenharmony_ci spec->master[i] & ~WM_VOL_MUTE; 7508c2ecf20Sopenharmony_ci return 0; 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_cistatic int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 7548c2ecf20Sopenharmony_ci{ 7558c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7568c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 7578c2ecf20Sopenharmony_ci int ch, change = 0; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 7608c2ecf20Sopenharmony_ci for (ch = 0; ch < 2; ch++) { 7618c2ecf20Sopenharmony_ci unsigned int vol = ucontrol->value.integer.value[ch]; 7628c2ecf20Sopenharmony_ci if (vol > WM_VOL_MAX) 7638c2ecf20Sopenharmony_ci vol = WM_VOL_MAX; 7648c2ecf20Sopenharmony_ci vol |= spec->master[ch] & WM_VOL_MUTE; 7658c2ecf20Sopenharmony_ci if (vol != spec->master[ch]) { 7668c2ecf20Sopenharmony_ci int dac; 7678c2ecf20Sopenharmony_ci spec->master[ch] = vol; 7688c2ecf20Sopenharmony_ci for (dac = 0; dac < ice->num_total_dacs; dac += 2) 7698c2ecf20Sopenharmony_ci wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, 7708c2ecf20Sopenharmony_ci spec->vol[dac + ch], 7718c2ecf20Sopenharmony_ci spec->master[ch]); 7728c2ecf20Sopenharmony_ci change = 1; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 7768c2ecf20Sopenharmony_ci return change; 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci/* 7808c2ecf20Sopenharmony_ci * DAC volume attenuation mixer control 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_cistatic int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci int voices = kcontrol->private_value >> 8; 7858c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 7868c2ecf20Sopenharmony_ci uinfo->count = voices; 7878c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; /* mute (-101dB) */ 7888c2ecf20Sopenharmony_ci uinfo->value.integer.max = WM_VOL_MAX; /* 0dB */ 7898c2ecf20Sopenharmony_ci return 0; 7908c2ecf20Sopenharmony_ci} 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_cistatic int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 7938c2ecf20Sopenharmony_ci{ 7948c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7958c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 7968c2ecf20Sopenharmony_ci int i, ofs, voices; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci voices = kcontrol->private_value >> 8; 7998c2ecf20Sopenharmony_ci ofs = kcontrol->private_value & 0xff; 8008c2ecf20Sopenharmony_ci for (i = 0; i < voices; i++) 8018c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] = 8028c2ecf20Sopenharmony_ci spec->vol[ofs+i] & ~WM_VOL_MUTE; 8038c2ecf20Sopenharmony_ci return 0; 8048c2ecf20Sopenharmony_ci} 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistatic int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 8098c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 8108c2ecf20Sopenharmony_ci int i, idx, ofs, voices; 8118c2ecf20Sopenharmony_ci int change = 0; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci voices = kcontrol->private_value >> 8; 8148c2ecf20Sopenharmony_ci ofs = kcontrol->private_value & 0xff; 8158c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 8168c2ecf20Sopenharmony_ci for (i = 0; i < voices; i++) { 8178c2ecf20Sopenharmony_ci unsigned int vol = ucontrol->value.integer.value[i]; 8188c2ecf20Sopenharmony_ci if (vol > WM_VOL_MAX) 8198c2ecf20Sopenharmony_ci vol = WM_VOL_MAX; 8208c2ecf20Sopenharmony_ci vol |= spec->vol[ofs+i] & WM_VOL_MUTE; 8218c2ecf20Sopenharmony_ci if (vol != spec->vol[ofs+i]) { 8228c2ecf20Sopenharmony_ci spec->vol[ofs+i] = vol; 8238c2ecf20Sopenharmony_ci idx = WM_DAC_ATTEN + ofs + i; 8248c2ecf20Sopenharmony_ci wm_set_vol(ice, idx, spec->vol[ofs + i], 8258c2ecf20Sopenharmony_ci spec->master[i]); 8268c2ecf20Sopenharmony_ci change = 1; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 8308c2ecf20Sopenharmony_ci return change; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci/* 8348c2ecf20Sopenharmony_ci * WM8770 mute control 8358c2ecf20Sopenharmony_ci */ 8368c2ecf20Sopenharmony_cistatic int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 8398c2ecf20Sopenharmony_ci uinfo->count = kcontrol->private_value >> 8; 8408c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 8418c2ecf20Sopenharmony_ci uinfo->value.integer.max = 1; 8428c2ecf20Sopenharmony_ci return 0; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 8488c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 8498c2ecf20Sopenharmony_ci int voices, ofs, i; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci voices = kcontrol->private_value >> 8; 8528c2ecf20Sopenharmony_ci ofs = kcontrol->private_value & 0xFF; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci for (i = 0; i < voices; i++) 8558c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] = 8568c2ecf20Sopenharmony_ci (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; 8578c2ecf20Sopenharmony_ci return 0; 8588c2ecf20Sopenharmony_ci} 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_cistatic int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 8638c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 8648c2ecf20Sopenharmony_ci int change = 0, voices, ofs, i; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci voices = kcontrol->private_value >> 8; 8678c2ecf20Sopenharmony_ci ofs = kcontrol->private_value & 0xFF; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 8708c2ecf20Sopenharmony_ci for (i = 0; i < voices; i++) { 8718c2ecf20Sopenharmony_ci int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; 8728c2ecf20Sopenharmony_ci if (ucontrol->value.integer.value[i] != val) { 8738c2ecf20Sopenharmony_ci spec->vol[ofs + i] &= ~WM_VOL_MUTE; 8748c2ecf20Sopenharmony_ci spec->vol[ofs + i] |= 8758c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; 8768c2ecf20Sopenharmony_ci wm_set_vol(ice, ofs + i, spec->vol[ofs + i], 8778c2ecf20Sopenharmony_ci spec->master[i]); 8788c2ecf20Sopenharmony_ci change = 1; 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci return change; 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci/* 8878c2ecf20Sopenharmony_ci * WM8770 master mute control 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci#define wm_master_mute_info snd_ctl_boolean_stereo_info 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 8948c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = 8978c2ecf20Sopenharmony_ci (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; 8988c2ecf20Sopenharmony_ci ucontrol->value.integer.value[1] = 8998c2ecf20Sopenharmony_ci (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 9068c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 9078c2ecf20Sopenharmony_ci int change = 0, i; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 9108c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 9118c2ecf20Sopenharmony_ci int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; 9128c2ecf20Sopenharmony_ci if (ucontrol->value.integer.value[i] != val) { 9138c2ecf20Sopenharmony_ci int dac; 9148c2ecf20Sopenharmony_ci spec->master[i] &= ~WM_VOL_MUTE; 9158c2ecf20Sopenharmony_ci spec->master[i] |= 9168c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; 9178c2ecf20Sopenharmony_ci for (dac = 0; dac < ice->num_total_dacs; dac += 2) 9188c2ecf20Sopenharmony_ci wm_set_vol(ice, WM_DAC_ATTEN + dac + i, 9198c2ecf20Sopenharmony_ci spec->vol[dac + i], 9208c2ecf20Sopenharmony_ci spec->master[i]); 9218c2ecf20Sopenharmony_ci change = 1; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci return change; 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci/* digital master volume */ 9308c2ecf20Sopenharmony_ci#define PCM_0dB 0xff 9318c2ecf20Sopenharmony_ci#define PCM_RES 128 /* -64dB */ 9328c2ecf20Sopenharmony_ci#define PCM_MIN (PCM_0dB - PCM_RES) 9338c2ecf20Sopenharmony_cistatic int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 9348c2ecf20Sopenharmony_ci{ 9358c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 9368c2ecf20Sopenharmony_ci uinfo->count = 1; 9378c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; /* mute (-64dB) */ 9388c2ecf20Sopenharmony_ci uinfo->value.integer.max = PCM_RES; /* 0dB */ 9398c2ecf20Sopenharmony_ci return 0; 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 9458c2ecf20Sopenharmony_ci unsigned short val; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 9488c2ecf20Sopenharmony_ci val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; 9498c2ecf20Sopenharmony_ci val = val > PCM_MIN ? (val - PCM_MIN) : 0; 9508c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = val; 9518c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 9528c2ecf20Sopenharmony_ci return 0; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 9588c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 9598c2ecf20Sopenharmony_ci int change = 0; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci nvol = ucontrol->value.integer.value[0]; 9628c2ecf20Sopenharmony_ci if (nvol > PCM_RES) 9638c2ecf20Sopenharmony_ci return -EINVAL; 9648c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 9658c2ecf20Sopenharmony_ci nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; 9668c2ecf20Sopenharmony_ci ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; 9678c2ecf20Sopenharmony_ci if (ovol != nvol) { 9688c2ecf20Sopenharmony_ci wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ 9698c2ecf20Sopenharmony_ci wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ 9708c2ecf20Sopenharmony_ci change = 1; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 9738c2ecf20Sopenharmony_ci return change; 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci/* 9778c2ecf20Sopenharmony_ci * ADC mute control 9788c2ecf20Sopenharmony_ci */ 9798c2ecf20Sopenharmony_ci#define wm_adc_mute_info snd_ctl_boolean_stereo_info 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_cistatic int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 9848c2ecf20Sopenharmony_ci unsigned short val; 9858c2ecf20Sopenharmony_ci int i; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 9888c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 9898c2ecf20Sopenharmony_ci val = wm_get(ice, WM_ADC_GAIN + i); 9908c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] = ~val>>5 & 0x1; 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 9938c2ecf20Sopenharmony_ci return 0; 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 9998c2ecf20Sopenharmony_ci unsigned short new, old; 10008c2ecf20Sopenharmony_ci int i, change = 0; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 10038c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 10048c2ecf20Sopenharmony_ci old = wm_get(ice, WM_ADC_GAIN + i); 10058c2ecf20Sopenharmony_ci new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20); 10068c2ecf20Sopenharmony_ci if (new != old) { 10078c2ecf20Sopenharmony_ci wm_put(ice, WM_ADC_GAIN + i, new); 10088c2ecf20Sopenharmony_ci change = 1; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci return change; 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci/* 10178c2ecf20Sopenharmony_ci * ADC gain mixer control 10188c2ecf20Sopenharmony_ci */ 10198c2ecf20Sopenharmony_cistatic int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 10228c2ecf20Sopenharmony_ci uinfo->count = 2; 10238c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; /* -12dB */ 10248c2ecf20Sopenharmony_ci uinfo->value.integer.max = 0x1f; /* 19dB */ 10258c2ecf20Sopenharmony_ci return 0; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 10298c2ecf20Sopenharmony_ci{ 10308c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 10318c2ecf20Sopenharmony_ci int i, idx; 10328c2ecf20Sopenharmony_ci unsigned short vol; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 10358c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 10368c2ecf20Sopenharmony_ci idx = WM_ADC_GAIN + i; 10378c2ecf20Sopenharmony_ci vol = wm_get(ice, idx) & 0x1f; 10388c2ecf20Sopenharmony_ci ucontrol->value.integer.value[i] = vol; 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 10418c2ecf20Sopenharmony_ci return 0; 10428c2ecf20Sopenharmony_ci} 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_cistatic int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 10478c2ecf20Sopenharmony_ci int i, idx; 10488c2ecf20Sopenharmony_ci unsigned short ovol, nvol; 10498c2ecf20Sopenharmony_ci int change = 0; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 10528c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 10538c2ecf20Sopenharmony_ci idx = WM_ADC_GAIN + i; 10548c2ecf20Sopenharmony_ci nvol = ucontrol->value.integer.value[i] & 0x1f; 10558c2ecf20Sopenharmony_ci ovol = wm_get(ice, idx); 10568c2ecf20Sopenharmony_ci if ((ovol & 0x1f) != nvol) { 10578c2ecf20Sopenharmony_ci wm_put(ice, idx, nvol | (ovol & ~0x1f)); 10588c2ecf20Sopenharmony_ci change = 1; 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 10628c2ecf20Sopenharmony_ci return change; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci/* 10668c2ecf20Sopenharmony_ci * ADC input mux mixer control 10678c2ecf20Sopenharmony_ci */ 10688c2ecf20Sopenharmony_cistatic int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci static const char * const texts[] = { 10718c2ecf20Sopenharmony_ci "CD", /* AIN1 */ 10728c2ecf20Sopenharmony_ci "Aux", /* AIN2 */ 10738c2ecf20Sopenharmony_ci "Line", /* AIN3 */ 10748c2ecf20Sopenharmony_ci "Mic", /* AIN4 */ 10758c2ecf20Sopenharmony_ci "AC97" /* AIN5 */ 10768c2ecf20Sopenharmony_ci }; 10778c2ecf20Sopenharmony_ci static const char * const universe_texts[] = { 10788c2ecf20Sopenharmony_ci "Aux1", /* AIN1 */ 10798c2ecf20Sopenharmony_ci "CD", /* AIN2 */ 10808c2ecf20Sopenharmony_ci "Phono", /* AIN3 */ 10818c2ecf20Sopenharmony_ci "Line", /* AIN4 */ 10828c2ecf20Sopenharmony_ci "Aux2", /* AIN5 */ 10838c2ecf20Sopenharmony_ci "Mic", /* AIN6 */ 10848c2ecf20Sopenharmony_ci "Aux3", /* AIN7 */ 10858c2ecf20Sopenharmony_ci "AC97" /* AIN8 */ 10868c2ecf20Sopenharmony_ci }; 10878c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) 10908c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 2, 8, universe_texts); 10918c2ecf20Sopenharmony_ci else 10928c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 2, 5, texts); 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 10988c2ecf20Sopenharmony_ci unsigned short val; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci mutex_lock(&ice->gpio_mutex); 11018c2ecf20Sopenharmony_ci val = wm_get(ice, WM_ADC_MUX); 11028c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = val & 7; 11038c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[1] = (val >> 4) & 7; 11048c2ecf20Sopenharmony_ci mutex_unlock(&ice->gpio_mutex); 11058c2ecf20Sopenharmony_ci return 0; 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 11118c2ecf20Sopenharmony_ci unsigned short oval, nval; 11128c2ecf20Sopenharmony_ci int change; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 11158c2ecf20Sopenharmony_ci oval = wm_get(ice, WM_ADC_MUX); 11168c2ecf20Sopenharmony_ci nval = oval & ~0x77; 11178c2ecf20Sopenharmony_ci nval |= ucontrol->value.enumerated.item[0] & 7; 11188c2ecf20Sopenharmony_ci nval |= (ucontrol->value.enumerated.item[1] & 7) << 4; 11198c2ecf20Sopenharmony_ci change = (oval != nval); 11208c2ecf20Sopenharmony_ci if (change) 11218c2ecf20Sopenharmony_ci wm_put(ice, WM_ADC_MUX, nval); 11228c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 11238c2ecf20Sopenharmony_ci return change; 11248c2ecf20Sopenharmony_ci} 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci/* 11278c2ecf20Sopenharmony_ci * CS8415 Input mux 11288c2ecf20Sopenharmony_ci */ 11298c2ecf20Sopenharmony_cistatic int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 11328c2ecf20Sopenharmony_ci static const char * const aureon_texts[] = { 11338c2ecf20Sopenharmony_ci "CD", /* RXP0 */ 11348c2ecf20Sopenharmony_ci "Optical" /* RXP1 */ 11358c2ecf20Sopenharmony_ci }; 11368c2ecf20Sopenharmony_ci static const char * const prodigy_texts[] = { 11378c2ecf20Sopenharmony_ci "CD", 11388c2ecf20Sopenharmony_ci "Coax" 11398c2ecf20Sopenharmony_ci }; 11408c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) 11418c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts); 11428c2ecf20Sopenharmony_ci else 11438c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts); 11448c2ecf20Sopenharmony_ci} 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_cistatic int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 11498c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* snd_ice1712_save_gpio_status(ice); */ 11528c2ecf20Sopenharmony_ci /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */ 11538c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = spec->cs8415_mux; 11548c2ecf20Sopenharmony_ci /* snd_ice1712_restore_gpio_status(ice); */ 11558c2ecf20Sopenharmony_ci return 0; 11568c2ecf20Sopenharmony_ci} 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_cistatic int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 11598c2ecf20Sopenharmony_ci{ 11608c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 11618c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 11628c2ecf20Sopenharmony_ci unsigned short oval, nval; 11638c2ecf20Sopenharmony_ci int change; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 11668c2ecf20Sopenharmony_ci oval = aureon_cs8415_get(ice, CS8415_CTRL2); 11678c2ecf20Sopenharmony_ci nval = oval & ~0x07; 11688c2ecf20Sopenharmony_ci nval |= ucontrol->value.enumerated.item[0] & 7; 11698c2ecf20Sopenharmony_ci change = (oval != nval); 11708c2ecf20Sopenharmony_ci if (change) 11718c2ecf20Sopenharmony_ci aureon_cs8415_put(ice, CS8415_CTRL2, nval); 11728c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 11738c2ecf20Sopenharmony_ci spec->cs8415_mux = ucontrol->value.enumerated.item[0]; 11748c2ecf20Sopenharmony_ci return change; 11758c2ecf20Sopenharmony_ci} 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_cistatic int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 11788c2ecf20Sopenharmony_ci{ 11798c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 11808c2ecf20Sopenharmony_ci uinfo->count = 1; 11818c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 11828c2ecf20Sopenharmony_ci uinfo->value.integer.max = 192000; 11838c2ecf20Sopenharmony_ci return 0; 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 11898c2ecf20Sopenharmony_ci unsigned char ratio; 11908c2ecf20Sopenharmony_ci ratio = aureon_cs8415_get(ice, CS8415_RATIO); 11918c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750); 11928c2ecf20Sopenharmony_ci return 0; 11938c2ecf20Sopenharmony_ci} 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci/* 11968c2ecf20Sopenharmony_ci * CS8415A Mute 11978c2ecf20Sopenharmony_ci */ 11988c2ecf20Sopenharmony_ci#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_cistatic int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 12038c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 12048c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1; 12058c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 12068c2ecf20Sopenharmony_ci return 0; 12078c2ecf20Sopenharmony_ci} 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cistatic int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 12108c2ecf20Sopenharmony_ci{ 12118c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 12128c2ecf20Sopenharmony_ci unsigned char oval, nval; 12138c2ecf20Sopenharmony_ci int change; 12148c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 12158c2ecf20Sopenharmony_ci oval = aureon_cs8415_get(ice, CS8415_CTRL1); 12168c2ecf20Sopenharmony_ci if (ucontrol->value.integer.value[0]) 12178c2ecf20Sopenharmony_ci nval = oval & ~0x20; 12188c2ecf20Sopenharmony_ci else 12198c2ecf20Sopenharmony_ci nval = oval | 0x20; 12208c2ecf20Sopenharmony_ci change = (oval != nval); 12218c2ecf20Sopenharmony_ci if (change) 12228c2ecf20Sopenharmony_ci aureon_cs8415_put(ice, CS8415_CTRL1, nval); 12238c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 12248c2ecf20Sopenharmony_ci return change; 12258c2ecf20Sopenharmony_ci} 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci/* 12288c2ecf20Sopenharmony_ci * CS8415A Q-Sub info 12298c2ecf20Sopenharmony_ci */ 12308c2ecf20Sopenharmony_cistatic int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 12318c2ecf20Sopenharmony_ci{ 12328c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 12338c2ecf20Sopenharmony_ci uinfo->count = 10; 12348c2ecf20Sopenharmony_ci return 0; 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_cistatic int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 12388c2ecf20Sopenharmony_ci{ 12398c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 12428c2ecf20Sopenharmony_ci aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10); 12438c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci return 0; 12468c2ecf20Sopenharmony_ci} 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_cistatic int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 12498c2ecf20Sopenharmony_ci{ 12508c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 12518c2ecf20Sopenharmony_ci uinfo->count = 1; 12528c2ecf20Sopenharmony_ci return 0; 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 12568c2ecf20Sopenharmony_ci{ 12578c2ecf20Sopenharmony_ci memset(ucontrol->value.iec958.status, 0xFF, 24); 12588c2ecf20Sopenharmony_ci return 0; 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cistatic int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 12668c2ecf20Sopenharmony_ci aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24); 12678c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 12688c2ecf20Sopenharmony_ci return 0; 12698c2ecf20Sopenharmony_ci} 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci/* 12728c2ecf20Sopenharmony_ci * Headphone Amplifier 12738c2ecf20Sopenharmony_ci */ 12748c2ecf20Sopenharmony_cistatic int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) 12758c2ecf20Sopenharmony_ci{ 12768c2ecf20Sopenharmony_ci unsigned int tmp, tmp2; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci tmp2 = tmp = snd_ice1712_gpio_read(ice); 12798c2ecf20Sopenharmony_ci if (enable) 12808c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 12818c2ecf20Sopenharmony_ci ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) 12828c2ecf20Sopenharmony_ci tmp |= AUREON_HP_SEL; 12838c2ecf20Sopenharmony_ci else 12848c2ecf20Sopenharmony_ci tmp |= PRODIGY_HP_SEL; 12858c2ecf20Sopenharmony_ci else 12868c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 12878c2ecf20Sopenharmony_ci ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) 12888c2ecf20Sopenharmony_ci tmp &= ~AUREON_HP_SEL; 12898c2ecf20Sopenharmony_ci else 12908c2ecf20Sopenharmony_ci tmp &= ~PRODIGY_HP_SEL; 12918c2ecf20Sopenharmony_ci if (tmp != tmp2) { 12928c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 12938c2ecf20Sopenharmony_ci return 1; 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci return 0; 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic int aureon_get_headphone_amp(struct snd_ice1712 *ice) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci unsigned int tmp = snd_ice1712_gpio_read(ice); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci return (tmp & AUREON_HP_SEL) != 0; 13038c2ecf20Sopenharmony_ci} 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci#define aureon_hpamp_info snd_ctl_boolean_mono_info 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_cistatic int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13088c2ecf20Sopenharmony_ci{ 13098c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice); 13128c2ecf20Sopenharmony_ci return 0; 13138c2ecf20Sopenharmony_ci} 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_cistatic int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13178c2ecf20Sopenharmony_ci{ 13188c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]); 13218c2ecf20Sopenharmony_ci} 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci/* 13248c2ecf20Sopenharmony_ci * Deemphasis 13258c2ecf20Sopenharmony_ci */ 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci#define aureon_deemp_info snd_ctl_boolean_mono_info 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_cistatic int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13308c2ecf20Sopenharmony_ci{ 13318c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13328c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; 13338c2ecf20Sopenharmony_ci return 0; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_cistatic int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13378c2ecf20Sopenharmony_ci{ 13388c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13398c2ecf20Sopenharmony_ci int temp, temp2; 13408c2ecf20Sopenharmony_ci temp2 = temp = wm_get(ice, WM_DAC_CTRL2); 13418c2ecf20Sopenharmony_ci if (ucontrol->value.integer.value[0]) 13428c2ecf20Sopenharmony_ci temp |= 0xf; 13438c2ecf20Sopenharmony_ci else 13448c2ecf20Sopenharmony_ci temp &= ~0xf; 13458c2ecf20Sopenharmony_ci if (temp != temp2) { 13468c2ecf20Sopenharmony_ci wm_put(ice, WM_DAC_CTRL2, temp); 13478c2ecf20Sopenharmony_ci return 1; 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci return 0; 13508c2ecf20Sopenharmony_ci} 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci/* 13538c2ecf20Sopenharmony_ci * ADC Oversampling 13548c2ecf20Sopenharmony_ci */ 13558c2ecf20Sopenharmony_cistatic int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) 13568c2ecf20Sopenharmony_ci{ 13578c2ecf20Sopenharmony_ci static const char * const texts[2] = { "128x", "64x" }; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 2, texts); 13608c2ecf20Sopenharmony_ci} 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_cistatic int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13638c2ecf20Sopenharmony_ci{ 13648c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13658c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; 13668c2ecf20Sopenharmony_ci return 0; 13678c2ecf20Sopenharmony_ci} 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_cistatic int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 13708c2ecf20Sopenharmony_ci{ 13718c2ecf20Sopenharmony_ci int temp, temp2; 13728c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci temp2 = temp = wm_get(ice, WM_MASTER); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci if (ucontrol->value.enumerated.item[0]) 13778c2ecf20Sopenharmony_ci temp |= 0x8; 13788c2ecf20Sopenharmony_ci else 13798c2ecf20Sopenharmony_ci temp &= ~0x8; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci if (temp != temp2) { 13828c2ecf20Sopenharmony_ci wm_put(ice, WM_MASTER, temp); 13838c2ecf20Sopenharmony_ci return 1; 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci return 0; 13868c2ecf20Sopenharmony_ci} 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci/* 13898c2ecf20Sopenharmony_ci * mixers 13908c2ecf20Sopenharmony_ci */ 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new aureon_dac_controls[] = { 13938c2ecf20Sopenharmony_ci { 13948c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 13958c2ecf20Sopenharmony_ci .name = "Master Playback Switch", 13968c2ecf20Sopenharmony_ci .info = wm_master_mute_info, 13978c2ecf20Sopenharmony_ci .get = wm_master_mute_get, 13988c2ecf20Sopenharmony_ci .put = wm_master_mute_put 13998c2ecf20Sopenharmony_ci }, 14008c2ecf20Sopenharmony_ci { 14018c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14028c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14038c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14048c2ecf20Sopenharmony_ci .name = "Master Playback Volume", 14058c2ecf20Sopenharmony_ci .info = wm_master_vol_info, 14068c2ecf20Sopenharmony_ci .get = wm_master_vol_get, 14078c2ecf20Sopenharmony_ci .put = wm_master_vol_put, 14088c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 14098c2ecf20Sopenharmony_ci }, 14108c2ecf20Sopenharmony_ci { 14118c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14128c2ecf20Sopenharmony_ci .name = "Front Playback Switch", 14138c2ecf20Sopenharmony_ci .info = wm_mute_info, 14148c2ecf20Sopenharmony_ci .get = wm_mute_get, 14158c2ecf20Sopenharmony_ci .put = wm_mute_put, 14168c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 0 14178c2ecf20Sopenharmony_ci }, 14188c2ecf20Sopenharmony_ci { 14198c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14208c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14218c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14228c2ecf20Sopenharmony_ci .name = "Front Playback Volume", 14238c2ecf20Sopenharmony_ci .info = wm_vol_info, 14248c2ecf20Sopenharmony_ci .get = wm_vol_get, 14258c2ecf20Sopenharmony_ci .put = wm_vol_put, 14268c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 0, 14278c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 14288c2ecf20Sopenharmony_ci }, 14298c2ecf20Sopenharmony_ci { 14308c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14318c2ecf20Sopenharmony_ci .name = "Rear Playback Switch", 14328c2ecf20Sopenharmony_ci .info = wm_mute_info, 14338c2ecf20Sopenharmony_ci .get = wm_mute_get, 14348c2ecf20Sopenharmony_ci .put = wm_mute_put, 14358c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 2 14368c2ecf20Sopenharmony_ci }, 14378c2ecf20Sopenharmony_ci { 14388c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14398c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14408c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14418c2ecf20Sopenharmony_ci .name = "Rear Playback Volume", 14428c2ecf20Sopenharmony_ci .info = wm_vol_info, 14438c2ecf20Sopenharmony_ci .get = wm_vol_get, 14448c2ecf20Sopenharmony_ci .put = wm_vol_put, 14458c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 2, 14468c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 14478c2ecf20Sopenharmony_ci }, 14488c2ecf20Sopenharmony_ci { 14498c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14508c2ecf20Sopenharmony_ci .name = "Center Playback Switch", 14518c2ecf20Sopenharmony_ci .info = wm_mute_info, 14528c2ecf20Sopenharmony_ci .get = wm_mute_get, 14538c2ecf20Sopenharmony_ci .put = wm_mute_put, 14548c2ecf20Sopenharmony_ci .private_value = (1 << 8) | 4 14558c2ecf20Sopenharmony_ci }, 14568c2ecf20Sopenharmony_ci { 14578c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14588c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14598c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14608c2ecf20Sopenharmony_ci .name = "Center Playback Volume", 14618c2ecf20Sopenharmony_ci .info = wm_vol_info, 14628c2ecf20Sopenharmony_ci .get = wm_vol_get, 14638c2ecf20Sopenharmony_ci .put = wm_vol_put, 14648c2ecf20Sopenharmony_ci .private_value = (1 << 8) | 4, 14658c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 14668c2ecf20Sopenharmony_ci }, 14678c2ecf20Sopenharmony_ci { 14688c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14698c2ecf20Sopenharmony_ci .name = "LFE Playback Switch", 14708c2ecf20Sopenharmony_ci .info = wm_mute_info, 14718c2ecf20Sopenharmony_ci .get = wm_mute_get, 14728c2ecf20Sopenharmony_ci .put = wm_mute_put, 14738c2ecf20Sopenharmony_ci .private_value = (1 << 8) | 5 14748c2ecf20Sopenharmony_ci }, 14758c2ecf20Sopenharmony_ci { 14768c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14778c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14788c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14798c2ecf20Sopenharmony_ci .name = "LFE Playback Volume", 14808c2ecf20Sopenharmony_ci .info = wm_vol_info, 14818c2ecf20Sopenharmony_ci .get = wm_vol_get, 14828c2ecf20Sopenharmony_ci .put = wm_vol_put, 14838c2ecf20Sopenharmony_ci .private_value = (1 << 8) | 5, 14848c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 14858c2ecf20Sopenharmony_ci }, 14868c2ecf20Sopenharmony_ci { 14878c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14888c2ecf20Sopenharmony_ci .name = "Side Playback Switch", 14898c2ecf20Sopenharmony_ci .info = wm_mute_info, 14908c2ecf20Sopenharmony_ci .get = wm_mute_get, 14918c2ecf20Sopenharmony_ci .put = wm_mute_put, 14928c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 6 14938c2ecf20Sopenharmony_ci }, 14948c2ecf20Sopenharmony_ci { 14958c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 14968c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 14978c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 14988c2ecf20Sopenharmony_ci .name = "Side Playback Volume", 14998c2ecf20Sopenharmony_ci .info = wm_vol_info, 15008c2ecf20Sopenharmony_ci .get = wm_vol_get, 15018c2ecf20Sopenharmony_ci .put = wm_vol_put, 15028c2ecf20Sopenharmony_ci .private_value = (2 << 8) | 6, 15038c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_dac } 15048c2ecf20Sopenharmony_ci } 15058c2ecf20Sopenharmony_ci}; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new wm_controls[] = { 15088c2ecf20Sopenharmony_ci { 15098c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15108c2ecf20Sopenharmony_ci .name = "PCM Playback Switch", 15118c2ecf20Sopenharmony_ci .info = wm_pcm_mute_info, 15128c2ecf20Sopenharmony_ci .get = wm_pcm_mute_get, 15138c2ecf20Sopenharmony_ci .put = wm_pcm_mute_put 15148c2ecf20Sopenharmony_ci }, 15158c2ecf20Sopenharmony_ci { 15168c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15178c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 15188c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 15198c2ecf20Sopenharmony_ci .name = "PCM Playback Volume", 15208c2ecf20Sopenharmony_ci .info = wm_pcm_vol_info, 15218c2ecf20Sopenharmony_ci .get = wm_pcm_vol_get, 15228c2ecf20Sopenharmony_ci .put = wm_pcm_vol_put, 15238c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_pcm } 15248c2ecf20Sopenharmony_ci }, 15258c2ecf20Sopenharmony_ci { 15268c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15278c2ecf20Sopenharmony_ci .name = "Capture Switch", 15288c2ecf20Sopenharmony_ci .info = wm_adc_mute_info, 15298c2ecf20Sopenharmony_ci .get = wm_adc_mute_get, 15308c2ecf20Sopenharmony_ci .put = wm_adc_mute_put, 15318c2ecf20Sopenharmony_ci }, 15328c2ecf20Sopenharmony_ci { 15338c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15348c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 15358c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 15368c2ecf20Sopenharmony_ci .name = "Capture Volume", 15378c2ecf20Sopenharmony_ci .info = wm_adc_vol_info, 15388c2ecf20Sopenharmony_ci .get = wm_adc_vol_get, 15398c2ecf20Sopenharmony_ci .put = wm_adc_vol_put, 15408c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_wm_adc } 15418c2ecf20Sopenharmony_ci }, 15428c2ecf20Sopenharmony_ci { 15438c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15448c2ecf20Sopenharmony_ci .name = "Capture Source", 15458c2ecf20Sopenharmony_ci .info = wm_adc_mux_info, 15468c2ecf20Sopenharmony_ci .get = wm_adc_mux_get, 15478c2ecf20Sopenharmony_ci .put = wm_adc_mux_put, 15488c2ecf20Sopenharmony_ci .private_value = 5 15498c2ecf20Sopenharmony_ci }, 15508c2ecf20Sopenharmony_ci { 15518c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15528c2ecf20Sopenharmony_ci .name = "External Amplifier", 15538c2ecf20Sopenharmony_ci .info = aureon_hpamp_info, 15548c2ecf20Sopenharmony_ci .get = aureon_hpamp_get, 15558c2ecf20Sopenharmony_ci .put = aureon_hpamp_put 15568c2ecf20Sopenharmony_ci }, 15578c2ecf20Sopenharmony_ci { 15588c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15598c2ecf20Sopenharmony_ci .name = "DAC Deemphasis Switch", 15608c2ecf20Sopenharmony_ci .info = aureon_deemp_info, 15618c2ecf20Sopenharmony_ci .get = aureon_deemp_get, 15628c2ecf20Sopenharmony_ci .put = aureon_deemp_put 15638c2ecf20Sopenharmony_ci }, 15648c2ecf20Sopenharmony_ci { 15658c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15668c2ecf20Sopenharmony_ci .name = "ADC Oversampling", 15678c2ecf20Sopenharmony_ci .info = aureon_oversampling_info, 15688c2ecf20Sopenharmony_ci .get = aureon_oversampling_get, 15698c2ecf20Sopenharmony_ci .put = aureon_oversampling_put 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci}; 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new ac97_controls[] = { 15748c2ecf20Sopenharmony_ci { 15758c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15768c2ecf20Sopenharmony_ci .name = "AC97 Playback Switch", 15778c2ecf20Sopenharmony_ci .info = aureon_ac97_mmute_info, 15788c2ecf20Sopenharmony_ci .get = aureon_ac97_mmute_get, 15798c2ecf20Sopenharmony_ci .put = aureon_ac97_mmute_put, 15808c2ecf20Sopenharmony_ci .private_value = AC97_MASTER 15818c2ecf20Sopenharmony_ci }, 15828c2ecf20Sopenharmony_ci { 15838c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15848c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 15858c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 15868c2ecf20Sopenharmony_ci .name = "AC97 Playback Volume", 15878c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 15888c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 15898c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 15908c2ecf20Sopenharmony_ci .private_value = AC97_MASTER|AUREON_AC97_STEREO, 15918c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_master } 15928c2ecf20Sopenharmony_ci }, 15938c2ecf20Sopenharmony_ci { 15948c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 15958c2ecf20Sopenharmony_ci .name = "CD Playback Switch", 15968c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 15978c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 15988c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 15998c2ecf20Sopenharmony_ci .private_value = AC97_CD 16008c2ecf20Sopenharmony_ci }, 16018c2ecf20Sopenharmony_ci { 16028c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16038c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 16048c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 16058c2ecf20Sopenharmony_ci .name = "CD Playback Volume", 16068c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 16078c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 16088c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 16098c2ecf20Sopenharmony_ci .private_value = AC97_CD|AUREON_AC97_STEREO, 16108c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 16118c2ecf20Sopenharmony_ci }, 16128c2ecf20Sopenharmony_ci { 16138c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16148c2ecf20Sopenharmony_ci .name = "Aux Playback Switch", 16158c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 16168c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 16178c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 16188c2ecf20Sopenharmony_ci .private_value = AC97_AUX, 16198c2ecf20Sopenharmony_ci }, 16208c2ecf20Sopenharmony_ci { 16218c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16228c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 16238c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 16248c2ecf20Sopenharmony_ci .name = "Aux Playback Volume", 16258c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 16268c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 16278c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 16288c2ecf20Sopenharmony_ci .private_value = AC97_AUX|AUREON_AC97_STEREO, 16298c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 16308c2ecf20Sopenharmony_ci }, 16318c2ecf20Sopenharmony_ci { 16328c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16338c2ecf20Sopenharmony_ci .name = "Line Playback Switch", 16348c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 16358c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 16368c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 16378c2ecf20Sopenharmony_ci .private_value = AC97_LINE 16388c2ecf20Sopenharmony_ci }, 16398c2ecf20Sopenharmony_ci { 16408c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16418c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 16428c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 16438c2ecf20Sopenharmony_ci .name = "Line Playback Volume", 16448c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 16458c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 16468c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 16478c2ecf20Sopenharmony_ci .private_value = AC97_LINE|AUREON_AC97_STEREO, 16488c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 16498c2ecf20Sopenharmony_ci }, 16508c2ecf20Sopenharmony_ci { 16518c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16528c2ecf20Sopenharmony_ci .name = "Mic Playback Switch", 16538c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 16548c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 16558c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 16568c2ecf20Sopenharmony_ci .private_value = AC97_MIC 16578c2ecf20Sopenharmony_ci }, 16588c2ecf20Sopenharmony_ci { 16598c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16608c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 16618c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 16628c2ecf20Sopenharmony_ci .name = "Mic Playback Volume", 16638c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 16648c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 16658c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 16668c2ecf20Sopenharmony_ci .private_value = AC97_MIC, 16678c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 16688c2ecf20Sopenharmony_ci }, 16698c2ecf20Sopenharmony_ci { 16708c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16718c2ecf20Sopenharmony_ci .name = "Mic Boost (+20dB)", 16728c2ecf20Sopenharmony_ci .info = aureon_ac97_micboost_info, 16738c2ecf20Sopenharmony_ci .get = aureon_ac97_micboost_get, 16748c2ecf20Sopenharmony_ci .put = aureon_ac97_micboost_put 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci}; 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new universe_ac97_controls[] = { 16798c2ecf20Sopenharmony_ci { 16808c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16818c2ecf20Sopenharmony_ci .name = "AC97 Playback Switch", 16828c2ecf20Sopenharmony_ci .info = aureon_ac97_mmute_info, 16838c2ecf20Sopenharmony_ci .get = aureon_ac97_mmute_get, 16848c2ecf20Sopenharmony_ci .put = aureon_ac97_mmute_put, 16858c2ecf20Sopenharmony_ci .private_value = AC97_MASTER 16868c2ecf20Sopenharmony_ci }, 16878c2ecf20Sopenharmony_ci { 16888c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 16898c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 16908c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 16918c2ecf20Sopenharmony_ci .name = "AC97 Playback Volume", 16928c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 16938c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 16948c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 16958c2ecf20Sopenharmony_ci .private_value = AC97_MASTER|AUREON_AC97_STEREO, 16968c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_master } 16978c2ecf20Sopenharmony_ci }, 16988c2ecf20Sopenharmony_ci { 16998c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17008c2ecf20Sopenharmony_ci .name = "CD Playback Switch", 17018c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 17028c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 17038c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 17048c2ecf20Sopenharmony_ci .private_value = AC97_AUX 17058c2ecf20Sopenharmony_ci }, 17068c2ecf20Sopenharmony_ci { 17078c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17088c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 17098c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 17108c2ecf20Sopenharmony_ci .name = "CD Playback Volume", 17118c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 17128c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 17138c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 17148c2ecf20Sopenharmony_ci .private_value = AC97_AUX|AUREON_AC97_STEREO, 17158c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 17168c2ecf20Sopenharmony_ci }, 17178c2ecf20Sopenharmony_ci { 17188c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17198c2ecf20Sopenharmony_ci .name = "Phono Playback Switch", 17208c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 17218c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 17228c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 17238c2ecf20Sopenharmony_ci .private_value = AC97_CD 17248c2ecf20Sopenharmony_ci }, 17258c2ecf20Sopenharmony_ci { 17268c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17278c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 17288c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 17298c2ecf20Sopenharmony_ci .name = "Phono Playback Volume", 17308c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 17318c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 17328c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 17338c2ecf20Sopenharmony_ci .private_value = AC97_CD|AUREON_AC97_STEREO, 17348c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 17358c2ecf20Sopenharmony_ci }, 17368c2ecf20Sopenharmony_ci { 17378c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17388c2ecf20Sopenharmony_ci .name = "Line Playback Switch", 17398c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 17408c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 17418c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 17428c2ecf20Sopenharmony_ci .private_value = AC97_LINE 17438c2ecf20Sopenharmony_ci }, 17448c2ecf20Sopenharmony_ci { 17458c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17468c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 17478c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 17488c2ecf20Sopenharmony_ci .name = "Line Playback Volume", 17498c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 17508c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 17518c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 17528c2ecf20Sopenharmony_ci .private_value = AC97_LINE|AUREON_AC97_STEREO, 17538c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 17548c2ecf20Sopenharmony_ci }, 17558c2ecf20Sopenharmony_ci { 17568c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17578c2ecf20Sopenharmony_ci .name = "Mic Playback Switch", 17588c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 17598c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 17608c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 17618c2ecf20Sopenharmony_ci .private_value = AC97_MIC 17628c2ecf20Sopenharmony_ci }, 17638c2ecf20Sopenharmony_ci { 17648c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17658c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 17668c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 17678c2ecf20Sopenharmony_ci .name = "Mic Playback Volume", 17688c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 17698c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 17708c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 17718c2ecf20Sopenharmony_ci .private_value = AC97_MIC, 17728c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 17738c2ecf20Sopenharmony_ci }, 17748c2ecf20Sopenharmony_ci { 17758c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17768c2ecf20Sopenharmony_ci .name = "Mic Boost (+20dB)", 17778c2ecf20Sopenharmony_ci .info = aureon_ac97_micboost_info, 17788c2ecf20Sopenharmony_ci .get = aureon_ac97_micboost_get, 17798c2ecf20Sopenharmony_ci .put = aureon_ac97_micboost_put 17808c2ecf20Sopenharmony_ci }, 17818c2ecf20Sopenharmony_ci { 17828c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17838c2ecf20Sopenharmony_ci .name = "Aux Playback Switch", 17848c2ecf20Sopenharmony_ci .info = aureon_ac97_mute_info, 17858c2ecf20Sopenharmony_ci .get = aureon_ac97_mute_get, 17868c2ecf20Sopenharmony_ci .put = aureon_ac97_mute_put, 17878c2ecf20Sopenharmony_ci .private_value = AC97_VIDEO, 17888c2ecf20Sopenharmony_ci }, 17898c2ecf20Sopenharmony_ci { 17908c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 17918c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 17928c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 17938c2ecf20Sopenharmony_ci .name = "Aux Playback Volume", 17948c2ecf20Sopenharmony_ci .info = aureon_ac97_vol_info, 17958c2ecf20Sopenharmony_ci .get = aureon_ac97_vol_get, 17968c2ecf20Sopenharmony_ci .put = aureon_ac97_vol_put, 17978c2ecf20Sopenharmony_ci .private_value = AC97_VIDEO|AUREON_AC97_STEREO, 17988c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_ac97_gain } 17998c2ecf20Sopenharmony_ci }, 18008c2ecf20Sopenharmony_ci { 18018c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18028c2ecf20Sopenharmony_ci .name = "Aux Source", 18038c2ecf20Sopenharmony_ci .info = aureon_universe_inmux_info, 18048c2ecf20Sopenharmony_ci .get = aureon_universe_inmux_get, 18058c2ecf20Sopenharmony_ci .put = aureon_universe_inmux_put 18068c2ecf20Sopenharmony_ci } 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci}; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cs8415_controls[] = { 18118c2ecf20Sopenharmony_ci { 18128c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18138c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), 18148c2ecf20Sopenharmony_ci .info = aureon_cs8415_mute_info, 18158c2ecf20Sopenharmony_ci .get = aureon_cs8415_mute_get, 18168c2ecf20Sopenharmony_ci .put = aureon_cs8415_mute_put 18178c2ecf20Sopenharmony_ci }, 18188c2ecf20Sopenharmony_ci { 18198c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18208c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source", 18218c2ecf20Sopenharmony_ci .info = aureon_cs8415_mux_info, 18228c2ecf20Sopenharmony_ci .get = aureon_cs8415_mux_get, 18238c2ecf20Sopenharmony_ci .put = aureon_cs8415_mux_put, 18248c2ecf20Sopenharmony_ci }, 18258c2ecf20Sopenharmony_ci { 18268c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18278c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT), 18288c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 18298c2ecf20Sopenharmony_ci .info = aureon_cs8415_qsub_info, 18308c2ecf20Sopenharmony_ci .get = aureon_cs8415_qsub_get, 18318c2ecf20Sopenharmony_ci }, 18328c2ecf20Sopenharmony_ci { 18338c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18348c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), 18358c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ, 18368c2ecf20Sopenharmony_ci .info = aureon_cs8415_spdif_info, 18378c2ecf20Sopenharmony_ci .get = aureon_cs8415_mask_get 18388c2ecf20Sopenharmony_ci }, 18398c2ecf20Sopenharmony_ci { 18408c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18418c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), 18428c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 18438c2ecf20Sopenharmony_ci .info = aureon_cs8415_spdif_info, 18448c2ecf20Sopenharmony_ci .get = aureon_cs8415_spdif_get 18458c2ecf20Sopenharmony_ci }, 18468c2ecf20Sopenharmony_ci { 18478c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18488c2ecf20Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate", 18498c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 18508c2ecf20Sopenharmony_ci .info = aureon_cs8415_rate_info, 18518c2ecf20Sopenharmony_ci .get = aureon_cs8415_rate_get 18528c2ecf20Sopenharmony_ci } 18538c2ecf20Sopenharmony_ci}; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int aureon_add_controls(struct snd_ice1712 *ice) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci unsigned int i, counts; 18588c2ecf20Sopenharmony_ci int err; 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci counts = ARRAY_SIZE(aureon_dac_controls); 18618c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) 18628c2ecf20Sopenharmony_ci counts -= 2; /* no side */ 18638c2ecf20Sopenharmony_ci for (i = 0; i < counts; i++) { 18648c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice)); 18658c2ecf20Sopenharmony_ci if (err < 0) 18668c2ecf20Sopenharmony_ci return err; 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { 18708c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice)); 18718c2ecf20Sopenharmony_ci if (err < 0) 18728c2ecf20Sopenharmony_ci return err; 18738c2ecf20Sopenharmony_ci } 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { 18768c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) { 18778c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice)); 18788c2ecf20Sopenharmony_ci if (err < 0) 18798c2ecf20Sopenharmony_ci return err; 18808c2ecf20Sopenharmony_ci } 18818c2ecf20Sopenharmony_ci } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 18828c2ecf20Sopenharmony_ci ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 18838c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { 18848c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); 18858c2ecf20Sopenharmony_ci if (err < 0) 18868c2ecf20Sopenharmony_ci return err; 18878c2ecf20Sopenharmony_ci } 18888c2ecf20Sopenharmony_ci } 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 18918c2ecf20Sopenharmony_ci ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 18928c2ecf20Sopenharmony_ci unsigned char id; 18938c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 18948c2ecf20Sopenharmony_ci id = aureon_cs8415_get(ice, CS8415_ID); 18958c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 18968c2ecf20Sopenharmony_ci if (id != 0x41) 18978c2ecf20Sopenharmony_ci dev_info(ice->card->dev, 18988c2ecf20Sopenharmony_ci "No CS8415 chip. Skipping CS8415 controls.\n"); 18998c2ecf20Sopenharmony_ci else if ((id & 0x0F) != 0x01) 19008c2ecf20Sopenharmony_ci dev_info(ice->card->dev, 19018c2ecf20Sopenharmony_ci "Detected unsupported CS8415 rev. (%c)\n", 19028c2ecf20Sopenharmony_ci (char)((id & 0x0F) + 'A' - 1)); 19038c2ecf20Sopenharmony_ci else { 19048c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { 19058c2ecf20Sopenharmony_ci struct snd_kcontrol *kctl; 19068c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice))); 19078c2ecf20Sopenharmony_ci if (err < 0) 19088c2ecf20Sopenharmony_ci return err; 19098c2ecf20Sopenharmony_ci if (i > 1) 19108c2ecf20Sopenharmony_ci kctl->id.device = ice->pcm->device; 19118c2ecf20Sopenharmony_ci } 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci } 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci return 0; 19168c2ecf20Sopenharmony_ci} 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci/* 19198c2ecf20Sopenharmony_ci * reset the chip 19208c2ecf20Sopenharmony_ci */ 19218c2ecf20Sopenharmony_cistatic int aureon_reset(struct snd_ice1712 *ice) 19228c2ecf20Sopenharmony_ci{ 19238c2ecf20Sopenharmony_ci static const unsigned short wm_inits_aureon[] = { 19248c2ecf20Sopenharmony_ci /* These come first to reduce init pop noise */ 19258c2ecf20Sopenharmony_ci 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 19268c2ecf20Sopenharmony_ci 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 19278c2ecf20Sopenharmony_ci 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci 0x18, 0x000, /* All power-up */ 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci 0x16, 0x122, /* I2S, normal polarity, 24bit */ 19328c2ecf20Sopenharmony_ci 0x17, 0x022, /* 256fs, slave mode */ 19338c2ecf20Sopenharmony_ci 0x00, 0, /* DAC1 analog mute */ 19348c2ecf20Sopenharmony_ci 0x01, 0, /* DAC2 analog mute */ 19358c2ecf20Sopenharmony_ci 0x02, 0, /* DAC3 analog mute */ 19368c2ecf20Sopenharmony_ci 0x03, 0, /* DAC4 analog mute */ 19378c2ecf20Sopenharmony_ci 0x04, 0, /* DAC5 analog mute */ 19388c2ecf20Sopenharmony_ci 0x05, 0, /* DAC6 analog mute */ 19398c2ecf20Sopenharmony_ci 0x06, 0, /* DAC7 analog mute */ 19408c2ecf20Sopenharmony_ci 0x07, 0, /* DAC8 analog mute */ 19418c2ecf20Sopenharmony_ci 0x08, 0x100, /* master analog mute */ 19428c2ecf20Sopenharmony_ci 0x09, 0xff, /* DAC1 digital full */ 19438c2ecf20Sopenharmony_ci 0x0a, 0xff, /* DAC2 digital full */ 19448c2ecf20Sopenharmony_ci 0x0b, 0xff, /* DAC3 digital full */ 19458c2ecf20Sopenharmony_ci 0x0c, 0xff, /* DAC4 digital full */ 19468c2ecf20Sopenharmony_ci 0x0d, 0xff, /* DAC5 digital full */ 19478c2ecf20Sopenharmony_ci 0x0e, 0xff, /* DAC6 digital full */ 19488c2ecf20Sopenharmony_ci 0x0f, 0xff, /* DAC7 digital full */ 19498c2ecf20Sopenharmony_ci 0x10, 0xff, /* DAC8 digital full */ 19508c2ecf20Sopenharmony_ci 0x11, 0x1ff, /* master digital full */ 19518c2ecf20Sopenharmony_ci 0x12, 0x000, /* phase normal */ 19528c2ecf20Sopenharmony_ci 0x13, 0x090, /* unmute DAC L/R */ 19538c2ecf20Sopenharmony_ci 0x14, 0x000, /* all unmute */ 19548c2ecf20Sopenharmony_ci 0x15, 0x000, /* no deemphasis, no ZFLG */ 19558c2ecf20Sopenharmony_ci 0x19, 0x000, /* -12dB ADC/L */ 19568c2ecf20Sopenharmony_ci 0x1a, 0x000, /* -12dB ADC/R */ 19578c2ecf20Sopenharmony_ci (unsigned short)-1 19588c2ecf20Sopenharmony_ci }; 19598c2ecf20Sopenharmony_ci static const unsigned short wm_inits_prodigy[] = { 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci /* These come first to reduce init pop noise */ 19628c2ecf20Sopenharmony_ci 0x1b, 0x000, /* ADC Mux */ 19638c2ecf20Sopenharmony_ci 0x1c, 0x009, /* Out Mux1 */ 19648c2ecf20Sopenharmony_ci 0x1d, 0x009, /* Out Mux2 */ 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ci 0x18, 0x000, /* All power-up */ 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */ 19698c2ecf20Sopenharmony_ci 0x17, 0x006, /* 128fs, slave mode */ 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci 0x00, 0, /* DAC1 analog mute */ 19728c2ecf20Sopenharmony_ci 0x01, 0, /* DAC2 analog mute */ 19738c2ecf20Sopenharmony_ci 0x02, 0, /* DAC3 analog mute */ 19748c2ecf20Sopenharmony_ci 0x03, 0, /* DAC4 analog mute */ 19758c2ecf20Sopenharmony_ci 0x04, 0, /* DAC5 analog mute */ 19768c2ecf20Sopenharmony_ci 0x05, 0, /* DAC6 analog mute */ 19778c2ecf20Sopenharmony_ci 0x06, 0, /* DAC7 analog mute */ 19788c2ecf20Sopenharmony_ci 0x07, 0, /* DAC8 analog mute */ 19798c2ecf20Sopenharmony_ci 0x08, 0x100, /* master analog mute */ 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci 0x09, 0x7f, /* DAC1 digital full */ 19828c2ecf20Sopenharmony_ci 0x0a, 0x7f, /* DAC2 digital full */ 19838c2ecf20Sopenharmony_ci 0x0b, 0x7f, /* DAC3 digital full */ 19848c2ecf20Sopenharmony_ci 0x0c, 0x7f, /* DAC4 digital full */ 19858c2ecf20Sopenharmony_ci 0x0d, 0x7f, /* DAC5 digital full */ 19868c2ecf20Sopenharmony_ci 0x0e, 0x7f, /* DAC6 digital full */ 19878c2ecf20Sopenharmony_ci 0x0f, 0x7f, /* DAC7 digital full */ 19888c2ecf20Sopenharmony_ci 0x10, 0x7f, /* DAC8 digital full */ 19898c2ecf20Sopenharmony_ci 0x11, 0x1FF, /* master digital full */ 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci 0x12, 0x000, /* phase normal */ 19928c2ecf20Sopenharmony_ci 0x13, 0x090, /* unmute DAC L/R */ 19938c2ecf20Sopenharmony_ci 0x14, 0x000, /* all unmute */ 19948c2ecf20Sopenharmony_ci 0x15, 0x000, /* no deemphasis, no ZFLG */ 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci 0x19, 0x000, /* -12dB ADC/L */ 19978c2ecf20Sopenharmony_ci 0x1a, 0x000, /* -12dB ADC/R */ 19988c2ecf20Sopenharmony_ci (unsigned short)-1 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci }; 20018c2ecf20Sopenharmony_ci static const unsigned short cs_inits[] = { 20028c2ecf20Sopenharmony_ci 0x0441, /* RUN */ 20038c2ecf20Sopenharmony_ci 0x0180, /* no mute, OMCK output on RMCK pin */ 20048c2ecf20Sopenharmony_ci 0x0201, /* S/PDIF source on RXP1 */ 20058c2ecf20Sopenharmony_ci 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ 20068c2ecf20Sopenharmony_ci (unsigned short)-1 20078c2ecf20Sopenharmony_ci }; 20088c2ecf20Sopenharmony_ci unsigned int tmp; 20098c2ecf20Sopenharmony_ci const unsigned short *p; 20108c2ecf20Sopenharmony_ci int err; 20118c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci err = aureon_ac97_init(ice); 20148c2ecf20Sopenharmony_ci if (err != 0) 20158c2ecf20Sopenharmony_ci return err; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci /* reset the wm codec as the SPI mode */ 20208c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 20218c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL)); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci tmp = snd_ice1712_gpio_read(ice); 20248c2ecf20Sopenharmony_ci tmp &= ~AUREON_WM_RESET; 20258c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 20268c2ecf20Sopenharmony_ci udelay(1); 20278c2ecf20Sopenharmony_ci tmp |= AUREON_WM_CS | AUREON_CS8415_CS; 20288c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 20298c2ecf20Sopenharmony_ci udelay(1); 20308c2ecf20Sopenharmony_ci tmp |= AUREON_WM_RESET; 20318c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, tmp); 20328c2ecf20Sopenharmony_ci udelay(1); 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci /* initialize WM8770 codec */ 20358c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 || 20368c2ecf20Sopenharmony_ci ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || 20378c2ecf20Sopenharmony_ci ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) 20388c2ecf20Sopenharmony_ci p = wm_inits_prodigy; 20398c2ecf20Sopenharmony_ci else 20408c2ecf20Sopenharmony_ci p = wm_inits_aureon; 20418c2ecf20Sopenharmony_ci for (; *p != (unsigned short)-1; p += 2) 20428c2ecf20Sopenharmony_ci wm_put(ice, p[0], p[1]); 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci /* initialize CS8415A codec */ 20458c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 20468c2ecf20Sopenharmony_ci ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 20478c2ecf20Sopenharmony_ci for (p = cs_inits; *p != (unsigned short)-1; p++) 20488c2ecf20Sopenharmony_ci aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); 20498c2ecf20Sopenharmony_ci spec->cs8415_mux = 1; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci aureon_set_headphone_amp(ice, 1); 20528c2ecf20Sopenharmony_ci } 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci /* initialize PCA9554 pin directions & set default input */ 20578c2ecf20Sopenharmony_ci aureon_pca9554_write(ice, PCA9554_DIR, 0x00); 20588c2ecf20Sopenharmony_ci aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ 20598c2ecf20Sopenharmony_ci return 0; 20608c2ecf20Sopenharmony_ci} 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci/* 20638c2ecf20Sopenharmony_ci * suspend/resume 20648c2ecf20Sopenharmony_ci */ 20658c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 20668c2ecf20Sopenharmony_cistatic int aureon_resume(struct snd_ice1712 *ice) 20678c2ecf20Sopenharmony_ci{ 20688c2ecf20Sopenharmony_ci struct aureon_spec *spec = ice->spec; 20698c2ecf20Sopenharmony_ci int err, i; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci err = aureon_reset(ice); 20728c2ecf20Sopenharmony_ci if (err != 0) 20738c2ecf20Sopenharmony_ci return err; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci /* workaround for poking volume with alsamixer after resume: 20768c2ecf20Sopenharmony_ci * just set stored volume again */ 20778c2ecf20Sopenharmony_ci for (i = 0; i < ice->num_total_dacs; i++) 20788c2ecf20Sopenharmony_ci wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 20798c2ecf20Sopenharmony_ci return 0; 20808c2ecf20Sopenharmony_ci} 20818c2ecf20Sopenharmony_ci#endif 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci/* 20848c2ecf20Sopenharmony_ci * initialize the chip 20858c2ecf20Sopenharmony_ci */ 20868c2ecf20Sopenharmony_cistatic int aureon_init(struct snd_ice1712 *ice) 20878c2ecf20Sopenharmony_ci{ 20888c2ecf20Sopenharmony_ci struct aureon_spec *spec; 20898c2ecf20Sopenharmony_ci int i, err; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci spec = kzalloc(sizeof(*spec), GFP_KERNEL); 20928c2ecf20Sopenharmony_ci if (!spec) 20938c2ecf20Sopenharmony_ci return -ENOMEM; 20948c2ecf20Sopenharmony_ci ice->spec = spec; 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { 20978c2ecf20Sopenharmony_ci ice->num_total_dacs = 6; 20988c2ecf20Sopenharmony_ci ice->num_total_adcs = 2; 20998c2ecf20Sopenharmony_ci } else { 21008c2ecf20Sopenharmony_ci /* aureon 7.1 and prodigy 7.1 */ 21018c2ecf20Sopenharmony_ci ice->num_total_dacs = 8; 21028c2ecf20Sopenharmony_ci ice->num_total_adcs = 2; 21038c2ecf20Sopenharmony_ci } 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci /* to remember the register values of CS8415 */ 21068c2ecf20Sopenharmony_ci ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); 21078c2ecf20Sopenharmony_ci if (!ice->akm) 21088c2ecf20Sopenharmony_ci return -ENOMEM; 21098c2ecf20Sopenharmony_ci ice->akm_codecs = 1; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci err = aureon_reset(ice); 21128c2ecf20Sopenharmony_ci if (err != 0) 21138c2ecf20Sopenharmony_ci return err; 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci spec->master[0] = WM_VOL_MUTE; 21168c2ecf20Sopenharmony_ci spec->master[1] = WM_VOL_MUTE; 21178c2ecf20Sopenharmony_ci for (i = 0; i < ice->num_total_dacs; i++) { 21188c2ecf20Sopenharmony_ci spec->vol[i] = WM_VOL_MUTE; 21198c2ecf20Sopenharmony_ci wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 21238c2ecf20Sopenharmony_ci ice->pm_resume = aureon_resume; 21248c2ecf20Sopenharmony_ci ice->pm_suspend_enabled = 1; 21258c2ecf20Sopenharmony_ci#endif 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci return 0; 21288c2ecf20Sopenharmony_ci} 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci/* 21328c2ecf20Sopenharmony_ci * Aureon boards don't provide the EEPROM data except for the vendor IDs. 21338c2ecf20Sopenharmony_ci * hence the driver needs to sets up it properly. 21348c2ecf20Sopenharmony_ci */ 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_cistatic const unsigned char aureon51_eeprom[] = { 21378c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */ 21388c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 21398c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 21408c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 21418c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR] = 0xff, 21428c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR1] = 0xff, 21438c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR2] = 0x5f, 21448c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK] = 0x00, 21458c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK1] = 0x00, 21468c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK2] = 0x00, 21478c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE] = 0x00, 21488c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE1] = 0x00, 21498c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE2] = 0x00, 21508c2ecf20Sopenharmony_ci}; 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_cistatic const unsigned char aureon71_eeprom[] = { 21538c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */ 21548c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 21558c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 21568c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 21578c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR] = 0xff, 21588c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR1] = 0xff, 21598c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR2] = 0x5f, 21608c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK] = 0x00, 21618c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK1] = 0x00, 21628c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK2] = 0x00, 21638c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE] = 0x00, 21648c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE1] = 0x00, 21658c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE2] = 0x00, 21668c2ecf20Sopenharmony_ci}; 21678c2ecf20Sopenharmony_ci#define prodigy71_eeprom aureon71_eeprom 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_cistatic const unsigned char aureon71_universe_eeprom[] = { 21708c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, 21718c2ecf20Sopenharmony_ci * 4DACs 21728c2ecf20Sopenharmony_ci */ 21738c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 21748c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 21758c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 21768c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR] = 0xff, 21778c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR1] = 0xff, 21788c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR2] = 0x5f, 21798c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK] = 0x00, 21808c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK1] = 0x00, 21818c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK2] = 0x00, 21828c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE] = 0x00, 21838c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE1] = 0x00, 21848c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE2] = 0x00, 21858c2ecf20Sopenharmony_ci}; 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_cistatic const unsigned char prodigy71lt_eeprom[] = { 21888c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */ 21898c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 21908c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 21918c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 21928c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR] = 0xff, 21938c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR1] = 0xff, 21948c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR2] = 0x5f, 21958c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK] = 0x00, 21968c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK1] = 0x00, 21978c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK2] = 0x00, 21988c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE] = 0x00, 21998c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE1] = 0x00, 22008c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE2] = 0x00, 22018c2ecf20Sopenharmony_ci}; 22028c2ecf20Sopenharmony_ci#define prodigy71xt_eeprom prodigy71lt_eeprom 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci/* entry point */ 22058c2ecf20Sopenharmony_cistruct snd_ice1712_card_info snd_vt1724_aureon_cards[] = { 22068c2ecf20Sopenharmony_ci { 22078c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_AUREON51_SKY, 22088c2ecf20Sopenharmony_ci .name = "Terratec Aureon 5.1-Sky", 22098c2ecf20Sopenharmony_ci .model = "aureon51", 22108c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22118c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22128c2ecf20Sopenharmony_ci .eeprom_size = sizeof(aureon51_eeprom), 22138c2ecf20Sopenharmony_ci .eeprom_data = aureon51_eeprom, 22148c2ecf20Sopenharmony_ci .driver = "Aureon51", 22158c2ecf20Sopenharmony_ci }, 22168c2ecf20Sopenharmony_ci { 22178c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE, 22188c2ecf20Sopenharmony_ci .name = "Terratec Aureon 7.1-Space", 22198c2ecf20Sopenharmony_ci .model = "aureon71", 22208c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22218c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22228c2ecf20Sopenharmony_ci .eeprom_size = sizeof(aureon71_eeprom), 22238c2ecf20Sopenharmony_ci .eeprom_data = aureon71_eeprom, 22248c2ecf20Sopenharmony_ci .driver = "Aureon71", 22258c2ecf20Sopenharmony_ci }, 22268c2ecf20Sopenharmony_ci { 22278c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE, 22288c2ecf20Sopenharmony_ci .name = "Terratec Aureon 7.1-Universe", 22298c2ecf20Sopenharmony_ci .model = "universe", 22308c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22318c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22328c2ecf20Sopenharmony_ci .eeprom_size = sizeof(aureon71_universe_eeprom), 22338c2ecf20Sopenharmony_ci .eeprom_data = aureon71_universe_eeprom, 22348c2ecf20Sopenharmony_ci .driver = "Aureon71Univ", /* keep in 15 letters */ 22358c2ecf20Sopenharmony_ci }, 22368c2ecf20Sopenharmony_ci { 22378c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_PRODIGY71, 22388c2ecf20Sopenharmony_ci .name = "Audiotrak Prodigy 7.1", 22398c2ecf20Sopenharmony_ci .model = "prodigy71", 22408c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22418c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22428c2ecf20Sopenharmony_ci .eeprom_size = sizeof(prodigy71_eeprom), 22438c2ecf20Sopenharmony_ci .eeprom_data = prodigy71_eeprom, 22448c2ecf20Sopenharmony_ci .driver = "Prodigy71", /* should be identical with Aureon71 */ 22458c2ecf20Sopenharmony_ci }, 22468c2ecf20Sopenharmony_ci { 22478c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_PRODIGY71LT, 22488c2ecf20Sopenharmony_ci .name = "Audiotrak Prodigy 7.1 LT", 22498c2ecf20Sopenharmony_ci .model = "prodigy71lt", 22508c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22518c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22528c2ecf20Sopenharmony_ci .eeprom_size = sizeof(prodigy71lt_eeprom), 22538c2ecf20Sopenharmony_ci .eeprom_data = prodigy71lt_eeprom, 22548c2ecf20Sopenharmony_ci .driver = "Prodigy71LT", 22558c2ecf20Sopenharmony_ci }, 22568c2ecf20Sopenharmony_ci { 22578c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_PRODIGY71XT, 22588c2ecf20Sopenharmony_ci .name = "Audiotrak Prodigy 7.1 XT", 22598c2ecf20Sopenharmony_ci .model = "prodigy71xt", 22608c2ecf20Sopenharmony_ci .chip_init = aureon_init, 22618c2ecf20Sopenharmony_ci .build_controls = aureon_add_controls, 22628c2ecf20Sopenharmony_ci .eeprom_size = sizeof(prodigy71xt_eeprom), 22638c2ecf20Sopenharmony_ci .eeprom_data = prodigy71xt_eeprom, 22648c2ecf20Sopenharmony_ci .driver = "Prodigy71LT", 22658c2ecf20Sopenharmony_ci }, 22668c2ecf20Sopenharmony_ci { } /* terminator */ 22678c2ecf20Sopenharmony_ci}; 2268