11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * ALSA driver for ICEnsemble VT1724 (Envy24HT)
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Lowlevel functions for Terratec Aureon cards
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * NOTES:
101da177e4SLinus Torvalds *
11ab0c7d72STakashi Iwai * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
121da177e4SLinus Torvalds * both wm and akm codecs are pretty similar, so we can integrate
131da177e4SLinus Torvalds * both controls in the future, once if wm codecs are reused in
141da177e4SLinus Torvalds * many boards.
151da177e4SLinus Torvalds *
161da177e4SLinus Torvalds * - DAC digital volumes are not implemented in the mixer.
171da177e4SLinus Torvalds * if they show better response than DAC analog volumes, we can use them
181da177e4SLinus Torvalds * instead.
191da177e4SLinus Torvalds *
201da177e4SLinus Torvalds * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
211da177e4SLinus Torvalds * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
221da177e4SLinus Torvalds *
231da177e4SLinus Torvalds * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
241da177e4SLinus Torvalds * added 64x/128x oversampling switch (should be 64x only for 96khz)
251da177e4SLinus Torvalds * fixed some recording labels (still need to check the rest)
261da177e4SLinus Torvalds * recording is working probably thanks to correct wm8770 initialization
271da177e4SLinus Torvalds *
281da177e4SLinus Torvalds * version 0.5: Initial release:
291da177e4SLinus Torvalds * working: analog output, mixer, headphone amplifier switch
301da177e4SLinus Torvalds * not working: prety much everything else, at least i could verify that
311da177e4SLinus Torvalds * we have no digital output, no capture, pretty bad clicks and poops
321da177e4SLinus Torvalds * on mixer switch and other coll stuff.
331da177e4SLinus Torvalds */
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds #include <linux/delay.h>
361da177e4SLinus Torvalds #include <linux/interrupt.h>
371da177e4SLinus Torvalds #include <linux/init.h>
381da177e4SLinus Torvalds #include <linux/slab.h>
3962932df8SIngo Molnar #include <linux/mutex.h>
4062932df8SIngo Molnar
411da177e4SLinus Torvalds #include <sound/core.h>
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds #include "ice1712.h"
441da177e4SLinus Torvalds #include "envy24ht.h"
451da177e4SLinus Torvalds #include "aureon.h"
46f640c320STakashi Iwai #include <sound/tlv.h>
471da177e4SLinus Torvalds
487cda8ba9STakashi Iwai /* AC97 register cache for Aureon */
497cda8ba9STakashi Iwai struct aureon_spec {
507cda8ba9STakashi Iwai unsigned short stac9744[64];
517cda8ba9STakashi Iwai unsigned int cs8415_mux;
527cda8ba9STakashi Iwai unsigned short master[2];
537cda8ba9STakashi Iwai unsigned short vol[8];
547cda8ba9STakashi Iwai unsigned char pca9554_out;
557cda8ba9STakashi Iwai };
567cda8ba9STakashi Iwai
571da177e4SLinus Torvalds /* WM8770 registers */
581da177e4SLinus Torvalds #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
591da177e4SLinus Torvalds #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
601da177e4SLinus Torvalds #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
611da177e4SLinus Torvalds #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
621da177e4SLinus Torvalds #define WM_PHASE_SWAP 0x12 /* DAC phase */
631da177e4SLinus Torvalds #define WM_DAC_CTRL1 0x13 /* DAC control bits */
641da177e4SLinus Torvalds #define WM_MUTE 0x14 /* mute controls */
651da177e4SLinus Torvalds #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
661da177e4SLinus Torvalds #define WM_INT_CTRL 0x16 /* interface control */
671da177e4SLinus Torvalds #define WM_MASTER 0x17 /* master clock and mode */
681da177e4SLinus Torvalds #define WM_POWERDOWN 0x18 /* power-down controls */
691da177e4SLinus Torvalds #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
701da177e4SLinus Torvalds #define WM_ADC_MUX 0x1b /* input MUX */
711da177e4SLinus Torvalds #define WM_OUT_MUX1 0x1c /* output MUX */
721da177e4SLinus Torvalds #define WM_OUT_MUX2 0x1e /* output MUX */
731da177e4SLinus Torvalds #define WM_RESET 0x1f /* software reset */
741da177e4SLinus Torvalds
751da177e4SLinus Torvalds /* CS8415A registers */
761da177e4SLinus Torvalds #define CS8415_CTRL1 0x01
771da177e4SLinus Torvalds #define CS8415_CTRL2 0x02
781da177e4SLinus Torvalds #define CS8415_QSUB 0x14
791da177e4SLinus Torvalds #define CS8415_RATIO 0x1E
801da177e4SLinus Torvalds #define CS8415_C_BUFFER 0x20
811da177e4SLinus Torvalds #define CS8415_ID 0x7F
821da177e4SLinus Torvalds
83af9b70acSMaximilian Rehkopf /* PCA9554 registers */
84af9b70acSMaximilian Rehkopf #define PCA9554_DEV 0x40 /* I2C device address */
85af9b70acSMaximilian Rehkopf #define PCA9554_IN 0x00 /* input port */
86af9b70acSMaximilian Rehkopf #define PCA9554_OUT 0x01 /* output port */
87af9b70acSMaximilian Rehkopf #define PCA9554_INVERT 0x02 /* input invert */
88af9b70acSMaximilian Rehkopf #define PCA9554_DIR 0x03 /* port directions */
89af9b70acSMaximilian Rehkopf
90af9b70acSMaximilian Rehkopf /*
91af9b70acSMaximilian Rehkopf * Aureon Universe additional controls using PCA9554
92af9b70acSMaximilian Rehkopf */
93af9b70acSMaximilian Rehkopf
94af9b70acSMaximilian Rehkopf /*
95af9b70acSMaximilian Rehkopf * Send data to pca9554
96af9b70acSMaximilian Rehkopf */
aureon_pca9554_write(struct snd_ice1712 * ice,unsigned char reg,unsigned char data)97af9b70acSMaximilian Rehkopf static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
98af9b70acSMaximilian Rehkopf unsigned char data)
99af9b70acSMaximilian Rehkopf {
100af9b70acSMaximilian Rehkopf unsigned int tmp;
101af9b70acSMaximilian Rehkopf int i, j;
102af9b70acSMaximilian Rehkopf unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
103af9b70acSMaximilian Rehkopf unsigned char val = 0;
104af9b70acSMaximilian Rehkopf
105af9b70acSMaximilian Rehkopf tmp = snd_ice1712_gpio_read(ice);
106af9b70acSMaximilian Rehkopf
107af9b70acSMaximilian Rehkopf snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
108af9b70acSMaximilian Rehkopf AUREON_WM_RW|AUREON_WM_CS|
109af9b70acSMaximilian Rehkopf AUREON_CS8415_CS));
110af9b70acSMaximilian Rehkopf tmp |= AUREON_WM_RW;
111af9b70acSMaximilian Rehkopf tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
112af9b70acSMaximilian Rehkopf
113af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_MOSI;
114af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
115af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
116af9b70acSMaximilian Rehkopf udelay(50);
117af9b70acSMaximilian Rehkopf
118af9b70acSMaximilian Rehkopf /*
119af9b70acSMaximilian Rehkopf * send i2c stop condition and start condition
120af9b70acSMaximilian Rehkopf * to obtain sane state
121af9b70acSMaximilian Rehkopf */
122af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_CLK;
123af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
124af9b70acSMaximilian Rehkopf udelay(50);
125af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_MOSI;
126af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
127af9b70acSMaximilian Rehkopf udelay(100);
128af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_MOSI;
129af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
130af9b70acSMaximilian Rehkopf udelay(50);
131af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
132af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
133af9b70acSMaximilian Rehkopf udelay(100);
134af9b70acSMaximilian Rehkopf /*
135af9b70acSMaximilian Rehkopf * send device address, command and value,
136af9b70acSMaximilian Rehkopf * skipping ack cycles in between
137af9b70acSMaximilian Rehkopf */
138af9b70acSMaximilian Rehkopf for (j = 0; j < 3; j++) {
139af9b70acSMaximilian Rehkopf switch (j) {
1401ce211a9SAlexander Beregalov case 0:
1411ce211a9SAlexander Beregalov val = dev;
1421ce211a9SAlexander Beregalov break;
1431ce211a9SAlexander Beregalov case 1:
1441ce211a9SAlexander Beregalov val = reg;
1451ce211a9SAlexander Beregalov break;
1461ce211a9SAlexander Beregalov case 2:
1471ce211a9SAlexander Beregalov val = data;
1481ce211a9SAlexander Beregalov break;
149af9b70acSMaximilian Rehkopf }
150af9b70acSMaximilian Rehkopf for (i = 7; i >= 0; i--) {
151af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
152af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
153af9b70acSMaximilian Rehkopf udelay(40);
154af9b70acSMaximilian Rehkopf if (val & (1 << i))
155af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_MOSI;
156af9b70acSMaximilian Rehkopf else
157af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_MOSI;
158af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
159af9b70acSMaximilian Rehkopf udelay(40);
160af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_CLK;
161af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
162af9b70acSMaximilian Rehkopf udelay(40);
163af9b70acSMaximilian Rehkopf }
164af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
165af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
166af9b70acSMaximilian Rehkopf udelay(40);
167af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_CLK;
168af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
169af9b70acSMaximilian Rehkopf udelay(40);
170af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
171af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
172af9b70acSMaximilian Rehkopf udelay(40);
173af9b70acSMaximilian Rehkopf }
174af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_CLK;
175af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
176af9b70acSMaximilian Rehkopf udelay(40);
177af9b70acSMaximilian Rehkopf tmp &= ~AUREON_SPI_MOSI;
178af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
179af9b70acSMaximilian Rehkopf udelay(40);
180af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_CLK;
181af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
182af9b70acSMaximilian Rehkopf udelay(50);
183af9b70acSMaximilian Rehkopf tmp |= AUREON_SPI_MOSI;
184af9b70acSMaximilian Rehkopf snd_ice1712_gpio_write(ice, tmp);
185af9b70acSMaximilian Rehkopf udelay(100);
186af9b70acSMaximilian Rehkopf }
187af9b70acSMaximilian Rehkopf
aureon_universe_inmux_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)188af9b70acSMaximilian Rehkopf static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
189af9b70acSMaximilian Rehkopf struct snd_ctl_elem_info *uinfo)
190af9b70acSMaximilian Rehkopf {
191a2af050fSTakashi Iwai static const char * const texts[3] =
192a2af050fSTakashi Iwai {"Internal Aux", "Wavetable", "Rear Line-In"};
193af9b70acSMaximilian Rehkopf
194597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 3, texts);
195af9b70acSMaximilian Rehkopf }
196af9b70acSMaximilian Rehkopf
aureon_universe_inmux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)197af9b70acSMaximilian Rehkopf static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
198af9b70acSMaximilian Rehkopf struct snd_ctl_elem_value *ucontrol)
199af9b70acSMaximilian Rehkopf {
200af9b70acSMaximilian Rehkopf struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2017cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
2027cda8ba9STakashi Iwai ucontrol->value.enumerated.item[0] = spec->pca9554_out;
203af9b70acSMaximilian Rehkopf return 0;
204af9b70acSMaximilian Rehkopf }
205af9b70acSMaximilian Rehkopf
aureon_universe_inmux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)206af9b70acSMaximilian Rehkopf static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
207af9b70acSMaximilian Rehkopf struct snd_ctl_elem_value *ucontrol)
208af9b70acSMaximilian Rehkopf {
209af9b70acSMaximilian Rehkopf struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2107cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
211af9b70acSMaximilian Rehkopf unsigned char oval, nval;
212af9b70acSMaximilian Rehkopf int change;
213af9b70acSMaximilian Rehkopf
2149cd17cd2STakashi Iwai nval = ucontrol->value.enumerated.item[0];
2159cd17cd2STakashi Iwai if (nval >= 3)
2169cd17cd2STakashi Iwai return -EINVAL;
217af9b70acSMaximilian Rehkopf snd_ice1712_save_gpio_status(ice);
2187cda8ba9STakashi Iwai oval = spec->pca9554_out;
2191ce211a9SAlexander Beregalov change = (oval != nval);
2201ce211a9SAlexander Beregalov if (change) {
221af9b70acSMaximilian Rehkopf aureon_pca9554_write(ice, PCA9554_OUT, nval);
2227cda8ba9STakashi Iwai spec->pca9554_out = nval;
223af9b70acSMaximilian Rehkopf }
224af9b70acSMaximilian Rehkopf snd_ice1712_restore_gpio_status(ice);
225af9b70acSMaximilian Rehkopf return change;
226af9b70acSMaximilian Rehkopf }
227af9b70acSMaximilian Rehkopf
228af9b70acSMaximilian Rehkopf
aureon_ac97_write(struct snd_ice1712 * ice,unsigned short reg,unsigned short val)229af9b70acSMaximilian Rehkopf static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
230af9b70acSMaximilian Rehkopf unsigned short val)
231af9b70acSMaximilian Rehkopf {
2327cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
2331da177e4SLinus Torvalds unsigned int tmp;
2341da177e4SLinus Torvalds
2351da177e4SLinus Torvalds /* Send address to XILINX chip */
2361da177e4SLinus Torvalds tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
2371da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2381da177e4SLinus Torvalds udelay(10);
2391da177e4SLinus Torvalds tmp |= AUREON_AC97_ADDR;
2401da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2411da177e4SLinus Torvalds udelay(10);
2421da177e4SLinus Torvalds tmp &= ~AUREON_AC97_ADDR;
2431da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2441da177e4SLinus Torvalds udelay(10);
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds /* Send low-order byte to XILINX chip */
2471da177e4SLinus Torvalds tmp &= ~AUREON_AC97_DATA_MASK;
2481da177e4SLinus Torvalds tmp |= val & AUREON_AC97_DATA_MASK;
2491da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2501da177e4SLinus Torvalds udelay(10);
2511da177e4SLinus Torvalds tmp |= AUREON_AC97_DATA_LOW;
2521da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2531da177e4SLinus Torvalds udelay(10);
2541da177e4SLinus Torvalds tmp &= ~AUREON_AC97_DATA_LOW;
2551da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2561da177e4SLinus Torvalds udelay(10);
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds /* Send high-order byte to XILINX chip */
2591da177e4SLinus Torvalds tmp &= ~AUREON_AC97_DATA_MASK;
2601da177e4SLinus Torvalds tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
2611da177e4SLinus Torvalds
2621da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2631da177e4SLinus Torvalds udelay(10);
2641da177e4SLinus Torvalds tmp |= AUREON_AC97_DATA_HIGH;
2651da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2661da177e4SLinus Torvalds udelay(10);
2671da177e4SLinus Torvalds tmp &= ~AUREON_AC97_DATA_HIGH;
2681da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2691da177e4SLinus Torvalds udelay(10);
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds /* Instruct XILINX chip to parse the data to the STAC9744 chip */
2721da177e4SLinus Torvalds tmp |= AUREON_AC97_COMMIT;
2731da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2741da177e4SLinus Torvalds udelay(10);
2751da177e4SLinus Torvalds tmp &= ~AUREON_AC97_COMMIT;
2761da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
2771da177e4SLinus Torvalds udelay(10);
2781da177e4SLinus Torvalds
2791da177e4SLinus Torvalds /* Store the data in out private buffer */
2807cda8ba9STakashi Iwai spec->stac9744[(reg & 0x7F) >> 1] = val;
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds
aureon_ac97_read(struct snd_ice1712 * ice,unsigned short reg)283ab0c7d72STakashi Iwai static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
2841da177e4SLinus Torvalds {
2857cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
2867cda8ba9STakashi Iwai return spec->stac9744[(reg & 0x7F) >> 1];
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds
2891da177e4SLinus Torvalds /*
2901da177e4SLinus Torvalds * Initialize STAC9744 chip
2911da177e4SLinus Torvalds */
aureon_ac97_init(struct snd_ice1712 * ice)292af9b70acSMaximilian Rehkopf static int aureon_ac97_init(struct snd_ice1712 *ice)
293af9b70acSMaximilian Rehkopf {
2947cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
2951da177e4SLinus Torvalds int i;
29632b47da0STakashi Iwai static const unsigned short ac97_defaults[] = {
2971da177e4SLinus Torvalds 0x00, 0x9640,
2981da177e4SLinus Torvalds 0x02, 0x8000,
2991da177e4SLinus Torvalds 0x04, 0x8000,
3001da177e4SLinus Torvalds 0x06, 0x8000,
3011da177e4SLinus Torvalds 0x0C, 0x8008,
3021da177e4SLinus Torvalds 0x0E, 0x8008,
3031da177e4SLinus Torvalds 0x10, 0x8808,
3041da177e4SLinus Torvalds 0x12, 0x8808,
3051da177e4SLinus Torvalds 0x14, 0x8808,
3061da177e4SLinus Torvalds 0x16, 0x8808,
3071da177e4SLinus Torvalds 0x18, 0x8808,
3081da177e4SLinus Torvalds 0x1C, 0x8000,
3091da177e4SLinus Torvalds 0x26, 0x000F,
3101da177e4SLinus Torvalds 0x28, 0x0201,
3111da177e4SLinus Torvalds 0x2C, 0xBB80,
3121da177e4SLinus Torvalds 0x32, 0xBB80,
3131da177e4SLinus Torvalds 0x7C, 0x8384,
3141da177e4SLinus Torvalds 0x7E, 0x7644,
3151da177e4SLinus Torvalds (unsigned short)-1
3161da177e4SLinus Torvalds };
3171da177e4SLinus Torvalds unsigned int tmp;
3181da177e4SLinus Torvalds
3191da177e4SLinus Torvalds /* Cold reset */
3201da177e4SLinus Torvalds tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
3211da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
3221da177e4SLinus Torvalds udelay(3);
3231da177e4SLinus Torvalds
3241da177e4SLinus Torvalds tmp &= ~AUREON_AC97_RESET;
3251da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
3261da177e4SLinus Torvalds udelay(3);
3271da177e4SLinus Torvalds
3281da177e4SLinus Torvalds tmp |= AUREON_AC97_RESET;
3291da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
3301da177e4SLinus Torvalds udelay(3);
3311da177e4SLinus Torvalds
3327cda8ba9STakashi Iwai memset(&spec->stac9744, 0, sizeof(spec->stac9744));
3331da177e4SLinus Torvalds for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2)
3347cda8ba9STakashi Iwai spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
3351da177e4SLinus Torvalds
3361ce211a9SAlexander Beregalov /* Unmute AC'97 master volume permanently - muting is done by WM8770 */
3371ce211a9SAlexander Beregalov aureon_ac97_write(ice, AC97_MASTER, 0x0000);
3381da177e4SLinus Torvalds
3391da177e4SLinus Torvalds return 0;
3401da177e4SLinus Torvalds }
3411da177e4SLinus Torvalds
3421da177e4SLinus Torvalds #define AUREON_AC97_STEREO 0x80
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvalds /*
3451da177e4SLinus Torvalds * AC'97 volume controls
3461da177e4SLinus Torvalds */
aureon_ac97_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)347ab0c7d72STakashi Iwai static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3481da177e4SLinus Torvalds {
3491da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3501da177e4SLinus Torvalds uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
3511da177e4SLinus Torvalds uinfo->value.integer.min = 0;
3521da177e4SLinus Torvalds uinfo->value.integer.max = 31;
3531da177e4SLinus Torvalds return 0;
3541da177e4SLinus Torvalds }
3551da177e4SLinus Torvalds
aureon_ac97_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)356ab0c7d72STakashi Iwai static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3571da177e4SLinus Torvalds {
358ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
3591da177e4SLinus Torvalds unsigned short vol;
3601da177e4SLinus Torvalds
36162932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
3621da177e4SLinus Torvalds
3631da177e4SLinus Torvalds vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
3641da177e4SLinus Torvalds ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
3651da177e4SLinus Torvalds if (kcontrol->private_value & AUREON_AC97_STEREO)
3661da177e4SLinus Torvalds ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
3671da177e4SLinus Torvalds
36862932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
3691da177e4SLinus Torvalds return 0;
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds
aureon_ac97_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)372ab0c7d72STakashi Iwai static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3731da177e4SLinus Torvalds {
374ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
3751da177e4SLinus Torvalds unsigned short ovol, nvol;
3761da177e4SLinus Torvalds int change;
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
3791da177e4SLinus Torvalds
3801da177e4SLinus Torvalds ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
3811da177e4SLinus Torvalds nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
3821da177e4SLinus Torvalds if (kcontrol->private_value & AUREON_AC97_STEREO)
3831da177e4SLinus Torvalds nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
3841da177e4SLinus Torvalds nvol |= ovol & ~0x1F1F;
3851da177e4SLinus Torvalds
3861ce211a9SAlexander Beregalov change = (ovol != nvol);
3871ce211a9SAlexander Beregalov if (change)
3881da177e4SLinus Torvalds aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
3891da177e4SLinus Torvalds
3901da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
3911da177e4SLinus Torvalds
3921da177e4SLinus Torvalds return change;
3931da177e4SLinus Torvalds }
3941da177e4SLinus Torvalds
3951da177e4SLinus Torvalds /*
3961da177e4SLinus Torvalds * AC'97 mute controls
3971da177e4SLinus Torvalds */
398a5ce8890STakashi Iwai #define aureon_ac97_mute_info snd_ctl_boolean_mono_info
3991da177e4SLinus Torvalds
aureon_ac97_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)400ab0c7d72STakashi Iwai static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4011da177e4SLinus Torvalds {
402ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
4031da177e4SLinus Torvalds
40462932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
4051da177e4SLinus Torvalds
4061ce211a9SAlexander Beregalov ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
4071ce211a9SAlexander Beregalov kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
4081da177e4SLinus Torvalds
40962932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
4101da177e4SLinus Torvalds return 0;
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds
aureon_ac97_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)413ab0c7d72STakashi Iwai static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4141da177e4SLinus Torvalds {
415ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
4161da177e4SLinus Torvalds unsigned short ovol, nvol;
4171da177e4SLinus Torvalds int change;
4181da177e4SLinus Torvalds
4191da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
4201da177e4SLinus Torvalds
4211da177e4SLinus Torvalds ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
4221da177e4SLinus Torvalds nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
4231da177e4SLinus Torvalds
4241ce211a9SAlexander Beregalov change = (ovol != nvol);
4251ce211a9SAlexander Beregalov if (change)
4261da177e4SLinus Torvalds aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
4271da177e4SLinus Torvalds
4281da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
4291da177e4SLinus Torvalds
4301da177e4SLinus Torvalds return change;
4311da177e4SLinus Torvalds }
4321da177e4SLinus Torvalds
4331da177e4SLinus Torvalds /*
4341da177e4SLinus Torvalds * AC'97 mute controls
4351da177e4SLinus Torvalds */
436a5ce8890STakashi Iwai #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
4371da177e4SLinus Torvalds
aureon_ac97_micboost_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)438ab0c7d72STakashi Iwai static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4391da177e4SLinus Torvalds {
440ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
4411da177e4SLinus Torvalds
44262932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
4431da177e4SLinus Torvalds
4441da177e4SLinus Torvalds ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
4451da177e4SLinus Torvalds
44662932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
4471da177e4SLinus Torvalds return 0;
4481da177e4SLinus Torvalds }
4491da177e4SLinus Torvalds
aureon_ac97_micboost_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)450ab0c7d72STakashi Iwai static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
4511da177e4SLinus Torvalds {
452ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
4531da177e4SLinus Torvalds unsigned short ovol, nvol;
4541da177e4SLinus Torvalds int change;
4551da177e4SLinus Torvalds
4561da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
4571da177e4SLinus Torvalds
4581da177e4SLinus Torvalds ovol = aureon_ac97_read(ice, AC97_MIC);
4591da177e4SLinus Torvalds nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
4601da177e4SLinus Torvalds
4611ce211a9SAlexander Beregalov change = (ovol != nvol);
4621ce211a9SAlexander Beregalov if (change)
4631da177e4SLinus Torvalds aureon_ac97_write(ice, AC97_MIC, nvol);
4641da177e4SLinus Torvalds
4651da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
4661da177e4SLinus Torvalds
4671da177e4SLinus Torvalds return change;
4681da177e4SLinus Torvalds }
4691da177e4SLinus Torvalds
4701da177e4SLinus Torvalds /*
4711da177e4SLinus Torvalds * write data in the SPI mode
4721da177e4SLinus Torvalds */
aureon_spi_write(struct snd_ice1712 * ice,unsigned int cs,unsigned int data,int bits)473ab0c7d72STakashi Iwai static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
4741da177e4SLinus Torvalds {
4751da177e4SLinus Torvalds unsigned int tmp;
4761da177e4SLinus Torvalds int i;
47745fe722bSTakashi Iwai unsigned int mosi, clk;
4781da177e4SLinus Torvalds
4791da177e4SLinus Torvalds tmp = snd_ice1712_gpio_read(ice);
4801da177e4SLinus Torvalds
481cdf88efaSToshimune Konno if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
482cdf88efaSToshimune Konno ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
48345fe722bSTakashi Iwai snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
48445fe722bSTakashi Iwai mosi = PRODIGY_SPI_MOSI;
48545fe722bSTakashi Iwai clk = PRODIGY_SPI_CLK;
4861ce211a9SAlexander Beregalov } else {
4871da177e4SLinus Torvalds snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
4881da177e4SLinus Torvalds AUREON_WM_CS|AUREON_CS8415_CS));
48945fe722bSTakashi Iwai mosi = AUREON_SPI_MOSI;
49045fe722bSTakashi Iwai clk = AUREON_SPI_CLK;
49145fe722bSTakashi Iwai
4921da177e4SLinus Torvalds tmp |= AUREON_WM_RW;
49345fe722bSTakashi Iwai }
49445fe722bSTakashi Iwai
4951da177e4SLinus Torvalds tmp &= ~cs;
4961da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
4971da177e4SLinus Torvalds udelay(1);
4981da177e4SLinus Torvalds
4991da177e4SLinus Torvalds for (i = bits - 1; i >= 0; i--) {
50045fe722bSTakashi Iwai tmp &= ~clk;
5011da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5021da177e4SLinus Torvalds udelay(1);
5031da177e4SLinus Torvalds if (data & (1 << i))
50445fe722bSTakashi Iwai tmp |= mosi;
5051da177e4SLinus Torvalds else
50645fe722bSTakashi Iwai tmp &= ~mosi;
5071da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5081da177e4SLinus Torvalds udelay(1);
50945fe722bSTakashi Iwai tmp |= clk;
5101da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5111da177e4SLinus Torvalds udelay(1);
5121da177e4SLinus Torvalds }
5131da177e4SLinus Torvalds
51445fe722bSTakashi Iwai tmp &= ~clk;
5151da177e4SLinus Torvalds tmp |= cs;
5161da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5171da177e4SLinus Torvalds udelay(1);
51845fe722bSTakashi Iwai tmp |= clk;
5191da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5201da177e4SLinus Torvalds udelay(1);
5211da177e4SLinus Torvalds }
5221da177e4SLinus Torvalds
5231da177e4SLinus Torvalds /*
5241da177e4SLinus Torvalds * Read data in SPI mode
5251da177e4SLinus Torvalds */
aureon_spi_read(struct snd_ice1712 * ice,unsigned int cs,unsigned int data,int bits,unsigned char * buffer,int size)5261ce211a9SAlexander Beregalov static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
5271ce211a9SAlexander Beregalov unsigned int data, int bits, unsigned char *buffer, int size)
5281ce211a9SAlexander Beregalov {
5291da177e4SLinus Torvalds int i, j;
5301da177e4SLinus Torvalds unsigned int tmp;
5311da177e4SLinus Torvalds
5321da177e4SLinus Torvalds tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
5331da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5341da177e4SLinus Torvalds tmp &= ~cs;
5351da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5361da177e4SLinus Torvalds udelay(1);
5371da177e4SLinus Torvalds
5381da177e4SLinus Torvalds for (i = bits-1; i >= 0; i--) {
5391da177e4SLinus Torvalds if (data & (1 << i))
5401da177e4SLinus Torvalds tmp |= AUREON_SPI_MOSI;
5411da177e4SLinus Torvalds else
5421da177e4SLinus Torvalds tmp &= ~AUREON_SPI_MOSI;
5431da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5441da177e4SLinus Torvalds udelay(1);
5451da177e4SLinus Torvalds
5461da177e4SLinus Torvalds tmp |= AUREON_SPI_CLK;
5471da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5481da177e4SLinus Torvalds udelay(1);
5491da177e4SLinus Torvalds
5501da177e4SLinus Torvalds tmp &= ~AUREON_SPI_CLK;
5511da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5521da177e4SLinus Torvalds udelay(1);
5531da177e4SLinus Torvalds }
5541da177e4SLinus Torvalds
5551da177e4SLinus Torvalds for (j = 0; j < size; j++) {
5561da177e4SLinus Torvalds unsigned char outdata = 0;
5571da177e4SLinus Torvalds for (i = 7; i >= 0; i--) {
5581da177e4SLinus Torvalds tmp = snd_ice1712_gpio_read(ice);
5591da177e4SLinus Torvalds outdata <<= 1;
5601da177e4SLinus Torvalds outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
5611da177e4SLinus Torvalds udelay(1);
5621da177e4SLinus Torvalds
5631da177e4SLinus Torvalds tmp |= AUREON_SPI_CLK;
5641da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5651da177e4SLinus Torvalds udelay(1);
5661da177e4SLinus Torvalds
5671da177e4SLinus Torvalds tmp &= ~AUREON_SPI_CLK;
5681da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5691da177e4SLinus Torvalds udelay(1);
5701da177e4SLinus Torvalds }
5711da177e4SLinus Torvalds buffer[j] = outdata;
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds
5741da177e4SLinus Torvalds tmp |= cs;
5751da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
5761da177e4SLinus Torvalds }
5771da177e4SLinus Torvalds
aureon_cs8415_get(struct snd_ice1712 * ice,int reg)5781ce211a9SAlexander Beregalov static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
5791ce211a9SAlexander Beregalov {
5801da177e4SLinus Torvalds unsigned char val;
5811da177e4SLinus Torvalds aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
5821da177e4SLinus Torvalds aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
5831da177e4SLinus Torvalds return val;
5841da177e4SLinus Torvalds }
5851da177e4SLinus Torvalds
aureon_cs8415_read(struct snd_ice1712 * ice,int reg,unsigned char * buffer,int size)5861ce211a9SAlexander Beregalov static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
5871ce211a9SAlexander Beregalov unsigned char *buffer, int size)
5881ce211a9SAlexander Beregalov {
5891da177e4SLinus Torvalds aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
5901da177e4SLinus Torvalds aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
5911da177e4SLinus Torvalds }
5921da177e4SLinus Torvalds
aureon_cs8415_put(struct snd_ice1712 * ice,int reg,unsigned char val)5931ce211a9SAlexander Beregalov static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
5941ce211a9SAlexander Beregalov unsigned char val)
5951ce211a9SAlexander Beregalov {
5961da177e4SLinus Torvalds aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
5971da177e4SLinus Torvalds }
5981da177e4SLinus Torvalds
5991da177e4SLinus Torvalds /*
6001da177e4SLinus Torvalds * get the current register value of WM codec
6011da177e4SLinus Torvalds */
wm_get(struct snd_ice1712 * ice,int reg)602ab0c7d72STakashi Iwai static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
6031da177e4SLinus Torvalds {
6041da177e4SLinus Torvalds reg <<= 1;
6051da177e4SLinus Torvalds return ((unsigned short)ice->akm[0].images[reg] << 8) |
6061da177e4SLinus Torvalds ice->akm[0].images[reg + 1];
6071da177e4SLinus Torvalds }
6081da177e4SLinus Torvalds
6091da177e4SLinus Torvalds /*
6101da177e4SLinus Torvalds * set the register value of WM codec
6111da177e4SLinus Torvalds */
wm_put_nocache(struct snd_ice1712 * ice,int reg,unsigned short val)612ab0c7d72STakashi Iwai static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
6131da177e4SLinus Torvalds {
61445fe722bSTakashi Iwai aureon_spi_write(ice,
615cdf88efaSToshimune Konno ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
616cdf88efaSToshimune Konno ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
617cdf88efaSToshimune Konno PRODIGY_WM_CS : AUREON_WM_CS),
61845fe722bSTakashi Iwai (reg << 9) | (val & 0x1ff), 16);
6191da177e4SLinus Torvalds }
6201da177e4SLinus Torvalds
6211da177e4SLinus Torvalds /*
6221da177e4SLinus Torvalds * set the register value of WM codec and remember it
6231da177e4SLinus Torvalds */
wm_put(struct snd_ice1712 * ice,int reg,unsigned short val)624ab0c7d72STakashi Iwai static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
6251da177e4SLinus Torvalds {
6261da177e4SLinus Torvalds wm_put_nocache(ice, reg, val);
6271da177e4SLinus Torvalds reg <<= 1;
6281da177e4SLinus Torvalds ice->akm[0].images[reg] = val >> 8;
6291da177e4SLinus Torvalds ice->akm[0].images[reg + 1] = val;
6301da177e4SLinus Torvalds }
6311da177e4SLinus Torvalds
6321da177e4SLinus Torvalds /*
6331da177e4SLinus Torvalds */
634a5ce8890STakashi Iwai #define aureon_mono_bool_info snd_ctl_boolean_mono_info
6351da177e4SLinus Torvalds
6361da177e4SLinus Torvalds /*
6371da177e4SLinus Torvalds * AC'97 master playback mute controls (Mute on WM8770 chip)
6381da177e4SLinus Torvalds */
639a5ce8890STakashi Iwai #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
6401da177e4SLinus Torvalds
aureon_ac97_mmute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)641ab0c7d72STakashi Iwai static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
6421da177e4SLinus Torvalds {
643ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
6441da177e4SLinus Torvalds
64562932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
6461da177e4SLinus Torvalds
6471da177e4SLinus Torvalds ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
6481da177e4SLinus Torvalds
64962932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
6501da177e4SLinus Torvalds return 0;
6511da177e4SLinus Torvalds }
6521da177e4SLinus Torvalds
aureon_ac97_mmute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6531ce211a9SAlexander Beregalov static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
6541ce211a9SAlexander Beregalov {
655ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
6561da177e4SLinus Torvalds unsigned short ovol, nvol;
6571da177e4SLinus Torvalds int change;
6581da177e4SLinus Torvalds
6591da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
6601da177e4SLinus Torvalds
6611da177e4SLinus Torvalds ovol = wm_get(ice, WM_OUT_MUX1);
6621da177e4SLinus Torvalds nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
6631ce211a9SAlexander Beregalov change = (ovol != nvol);
6641ce211a9SAlexander Beregalov if (change)
6651da177e4SLinus Torvalds wm_put(ice, WM_OUT_MUX1, nvol);
6661da177e4SLinus Torvalds
6671da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
6681da177e4SLinus Torvalds
6691da177e4SLinus Torvalds return change;
6701da177e4SLinus Torvalds }
6711da177e4SLinus Torvalds
672482e46d4SJaroslav Kysela static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1);
6730cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
6740cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
6750cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
6760cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
677f640c320STakashi Iwai
678482e46d4SJaroslav Kysela #define WM_VOL_MAX 100
679482e46d4SJaroslav Kysela #define WM_VOL_CNT 101 /* 0dB .. -100dB */
6801da177e4SLinus Torvalds #define WM_VOL_MUTE 0x8000
6811da177e4SLinus Torvalds
wm_set_vol(struct snd_ice1712 * ice,unsigned int index,unsigned short vol,unsigned short master)682ab0c7d72STakashi Iwai static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
6831da177e4SLinus Torvalds {
6841da177e4SLinus Torvalds unsigned char nvol;
6851da177e4SLinus Torvalds
6869d4c7464SJaroslav Kysela if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
6871da177e4SLinus Torvalds nvol = 0;
6889d4c7464SJaroslav Kysela } else {
689482e46d4SJaroslav Kysela nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
690482e46d4SJaroslav Kysela WM_VOL_MAX;
6919d4c7464SJaroslav Kysela nvol += 0x1b;
6929d4c7464SJaroslav Kysela }
6931da177e4SLinus Torvalds
6941da177e4SLinus Torvalds wm_put(ice, index, nvol);
6951da177e4SLinus Torvalds wm_put_nocache(ice, index, 0x180 | nvol);
6961da177e4SLinus Torvalds }
6971da177e4SLinus Torvalds
6981da177e4SLinus Torvalds /*
6991da177e4SLinus Torvalds * DAC mute control
7001da177e4SLinus Torvalds */
701a5ce8890STakashi Iwai #define wm_pcm_mute_info snd_ctl_boolean_mono_info
7021da177e4SLinus Torvalds
wm_pcm_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)703ab0c7d72STakashi Iwai static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7041da177e4SLinus Torvalds {
705ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7061da177e4SLinus Torvalds
70762932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
7081da177e4SLinus Torvalds ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
70962932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
7101da177e4SLinus Torvalds return 0;
7111da177e4SLinus Torvalds }
7121da177e4SLinus Torvalds
wm_pcm_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)713ab0c7d72STakashi Iwai static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7141da177e4SLinus Torvalds {
715ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7161da177e4SLinus Torvalds unsigned short nval, oval;
7171da177e4SLinus Torvalds int change;
7181da177e4SLinus Torvalds
7191da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
7201da177e4SLinus Torvalds oval = wm_get(ice, WM_MUTE);
7211da177e4SLinus Torvalds nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
7221ce211a9SAlexander Beregalov change = (oval != nval);
7231ce211a9SAlexander Beregalov if (change)
7241da177e4SLinus Torvalds wm_put(ice, WM_MUTE, nval);
7251da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
7261da177e4SLinus Torvalds
7271da177e4SLinus Torvalds return change;
7281da177e4SLinus Torvalds }
7291da177e4SLinus Torvalds
7301da177e4SLinus Torvalds /*
7311da177e4SLinus Torvalds * Master volume attenuation mixer control
7321da177e4SLinus Torvalds */
wm_master_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)733ab0c7d72STakashi Iwai static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
7341da177e4SLinus Torvalds {
7351da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7361da177e4SLinus Torvalds uinfo->count = 2;
7371da177e4SLinus Torvalds uinfo->value.integer.min = 0;
7381da177e4SLinus Torvalds uinfo->value.integer.max = WM_VOL_MAX;
7391da177e4SLinus Torvalds return 0;
7401da177e4SLinus Torvalds }
7411da177e4SLinus Torvalds
wm_master_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)742ab0c7d72STakashi Iwai static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7431da177e4SLinus Torvalds {
744ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7457cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
7461da177e4SLinus Torvalds int i;
7471da177e4SLinus Torvalds for (i = 0; i < 2; i++)
7487cda8ba9STakashi Iwai ucontrol->value.integer.value[i] =
7497cda8ba9STakashi Iwai spec->master[i] & ~WM_VOL_MUTE;
7501da177e4SLinus Torvalds return 0;
7511da177e4SLinus Torvalds }
7521da177e4SLinus Torvalds
wm_master_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)753ab0c7d72STakashi Iwai static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7541da177e4SLinus Torvalds {
755ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7567cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
7571da177e4SLinus Torvalds int ch, change = 0;
7581da177e4SLinus Torvalds
7591da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
7601da177e4SLinus Torvalds for (ch = 0; ch < 2; ch++) {
7619cd17cd2STakashi Iwai unsigned int vol = ucontrol->value.integer.value[ch];
7629cd17cd2STakashi Iwai if (vol > WM_VOL_MAX)
7639d4c7464SJaroslav Kysela vol = WM_VOL_MAX;
7647cda8ba9STakashi Iwai vol |= spec->master[ch] & WM_VOL_MUTE;
7657cda8ba9STakashi Iwai if (vol != spec->master[ch]) {
7661da177e4SLinus Torvalds int dac;
7677cda8ba9STakashi Iwai spec->master[ch] = vol;
7681da177e4SLinus Torvalds for (dac = 0; dac < ice->num_total_dacs; dac += 2)
7691da177e4SLinus Torvalds wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
7707cda8ba9STakashi Iwai spec->vol[dac + ch],
7717cda8ba9STakashi Iwai spec->master[ch]);
7721da177e4SLinus Torvalds change = 1;
7731da177e4SLinus Torvalds }
7741da177e4SLinus Torvalds }
7751da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
7761da177e4SLinus Torvalds return change;
7771da177e4SLinus Torvalds }
7781da177e4SLinus Torvalds
7791da177e4SLinus Torvalds /*
7801da177e4SLinus Torvalds * DAC volume attenuation mixer control
7811da177e4SLinus Torvalds */
wm_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)782ab0c7d72STakashi Iwai static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
7831da177e4SLinus Torvalds {
7841da177e4SLinus Torvalds int voices = kcontrol->private_value >> 8;
7851da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7861da177e4SLinus Torvalds uinfo->count = voices;
7871da177e4SLinus Torvalds uinfo->value.integer.min = 0; /* mute (-101dB) */
788482e46d4SJaroslav Kysela uinfo->value.integer.max = WM_VOL_MAX; /* 0dB */
7891da177e4SLinus Torvalds return 0;
7901da177e4SLinus Torvalds }
7911da177e4SLinus Torvalds
wm_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)792ab0c7d72STakashi Iwai static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7931da177e4SLinus Torvalds {
794ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7957cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
7961da177e4SLinus Torvalds int i, ofs, voices;
7971da177e4SLinus Torvalds
7981da177e4SLinus Torvalds voices = kcontrol->private_value >> 8;
7991da177e4SLinus Torvalds ofs = kcontrol->private_value & 0xff;
8001da177e4SLinus Torvalds for (i = 0; i < voices; i++)
8017cda8ba9STakashi Iwai ucontrol->value.integer.value[i] =
8027cda8ba9STakashi Iwai spec->vol[ofs+i] & ~WM_VOL_MUTE;
8031da177e4SLinus Torvalds return 0;
8041da177e4SLinus Torvalds }
8051da177e4SLinus Torvalds
wm_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)806ab0c7d72STakashi Iwai static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8071da177e4SLinus Torvalds {
808ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
8097cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
8101da177e4SLinus Torvalds int i, idx, ofs, voices;
8111da177e4SLinus Torvalds int change = 0;
8121da177e4SLinus Torvalds
8131da177e4SLinus Torvalds voices = kcontrol->private_value >> 8;
8141da177e4SLinus Torvalds ofs = kcontrol->private_value & 0xff;
8151da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
8161da177e4SLinus Torvalds for (i = 0; i < voices; i++) {
8179cd17cd2STakashi Iwai unsigned int vol = ucontrol->value.integer.value[i];
818482e46d4SJaroslav Kysela if (vol > WM_VOL_MAX)
8199d4c7464SJaroslav Kysela vol = WM_VOL_MAX;
8209d4c7464SJaroslav Kysela vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
8217cda8ba9STakashi Iwai if (vol != spec->vol[ofs+i]) {
8227cda8ba9STakashi Iwai spec->vol[ofs+i] = vol;
8231da177e4SLinus Torvalds idx = WM_DAC_ATTEN + ofs + i;
8247cda8ba9STakashi Iwai wm_set_vol(ice, idx, spec->vol[ofs + i],
8257cda8ba9STakashi Iwai spec->master[i]);
8261da177e4SLinus Torvalds change = 1;
8271da177e4SLinus Torvalds }
8281da177e4SLinus Torvalds }
8291da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
8301da177e4SLinus Torvalds return change;
8311da177e4SLinus Torvalds }
8321da177e4SLinus Torvalds
8331da177e4SLinus Torvalds /*
8341da177e4SLinus Torvalds * WM8770 mute control
8351da177e4SLinus Torvalds */
wm_mute_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)8361ce211a9SAlexander Beregalov static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
8371ce211a9SAlexander Beregalov {
8381da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
8391da177e4SLinus Torvalds uinfo->count = kcontrol->private_value >> 8;
8401da177e4SLinus Torvalds uinfo->value.integer.min = 0;
8411da177e4SLinus Torvalds uinfo->value.integer.max = 1;
8421da177e4SLinus Torvalds return 0;
8431da177e4SLinus Torvalds }
8441da177e4SLinus Torvalds
wm_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)845ab0c7d72STakashi Iwai static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8461da177e4SLinus Torvalds {
847ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
8487cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
8491da177e4SLinus Torvalds int voices, ofs, i;
8501da177e4SLinus Torvalds
8511da177e4SLinus Torvalds voices = kcontrol->private_value >> 8;
8521da177e4SLinus Torvalds ofs = kcontrol->private_value & 0xFF;
8531da177e4SLinus Torvalds
8541da177e4SLinus Torvalds for (i = 0; i < voices; i++)
8557cda8ba9STakashi Iwai ucontrol->value.integer.value[i] =
8567cda8ba9STakashi Iwai (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
8571da177e4SLinus Torvalds return 0;
8581da177e4SLinus Torvalds }
8591da177e4SLinus Torvalds
wm_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)860ab0c7d72STakashi Iwai static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8611da177e4SLinus Torvalds {
862ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
8637cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
8641da177e4SLinus Torvalds int change = 0, voices, ofs, i;
8651da177e4SLinus Torvalds
8661da177e4SLinus Torvalds voices = kcontrol->private_value >> 8;
8671da177e4SLinus Torvalds ofs = kcontrol->private_value & 0xFF;
8681da177e4SLinus Torvalds
8691da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
8701da177e4SLinus Torvalds for (i = 0; i < voices; i++) {
8717cda8ba9STakashi Iwai int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
8721da177e4SLinus Torvalds if (ucontrol->value.integer.value[i] != val) {
8737cda8ba9STakashi Iwai spec->vol[ofs + i] &= ~WM_VOL_MUTE;
8747cda8ba9STakashi Iwai spec->vol[ofs + i] |=
8751da177e4SLinus Torvalds ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
8767cda8ba9STakashi Iwai wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
8777cda8ba9STakashi Iwai spec->master[i]);
8781da177e4SLinus Torvalds change = 1;
8791da177e4SLinus Torvalds }
8801da177e4SLinus Torvalds }
8811da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
8821da177e4SLinus Torvalds
8831da177e4SLinus Torvalds return change;
8841da177e4SLinus Torvalds }
8851da177e4SLinus Torvalds
8861da177e4SLinus Torvalds /*
8871da177e4SLinus Torvalds * WM8770 master mute control
8881da177e4SLinus Torvalds */
889a5ce8890STakashi Iwai #define wm_master_mute_info snd_ctl_boolean_stereo_info
8901da177e4SLinus Torvalds
wm_master_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)891ab0c7d72STakashi Iwai static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8921da177e4SLinus Torvalds {
893ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
8947cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
8951da177e4SLinus Torvalds
8967cda8ba9STakashi Iwai ucontrol->value.integer.value[0] =
8977cda8ba9STakashi Iwai (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
8987cda8ba9STakashi Iwai ucontrol->value.integer.value[1] =
8997cda8ba9STakashi Iwai (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
9001da177e4SLinus Torvalds return 0;
9011da177e4SLinus Torvalds }
9021da177e4SLinus Torvalds
wm_master_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)903ab0c7d72STakashi Iwai static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9041da177e4SLinus Torvalds {
905ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
9067cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
9071da177e4SLinus Torvalds int change = 0, i;
9081da177e4SLinus Torvalds
9091da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
9101da177e4SLinus Torvalds for (i = 0; i < 2; i++) {
9117cda8ba9STakashi Iwai int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
9121da177e4SLinus Torvalds if (ucontrol->value.integer.value[i] != val) {
9131da177e4SLinus Torvalds int dac;
9147cda8ba9STakashi Iwai spec->master[i] &= ~WM_VOL_MUTE;
9157cda8ba9STakashi Iwai spec->master[i] |=
9161da177e4SLinus Torvalds ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
9171da177e4SLinus Torvalds for (dac = 0; dac < ice->num_total_dacs; dac += 2)
9181da177e4SLinus Torvalds wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
9197cda8ba9STakashi Iwai spec->vol[dac + i],
9207cda8ba9STakashi Iwai spec->master[i]);
9211da177e4SLinus Torvalds change = 1;
9221da177e4SLinus Torvalds }
9231da177e4SLinus Torvalds }
9241da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
9251da177e4SLinus Torvalds
9261da177e4SLinus Torvalds return change;
9271da177e4SLinus Torvalds }
9281da177e4SLinus Torvalds
9291da177e4SLinus Torvalds /* digital master volume */
9301da177e4SLinus Torvalds #define PCM_0dB 0xff
9311da177e4SLinus Torvalds #define PCM_RES 128 /* -64dB */
9321da177e4SLinus Torvalds #define PCM_MIN (PCM_0dB - PCM_RES)
wm_pcm_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)933ab0c7d72STakashi Iwai static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
9341da177e4SLinus Torvalds {
9351da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
9361da177e4SLinus Torvalds uinfo->count = 1;
9371da177e4SLinus Torvalds uinfo->value.integer.min = 0; /* mute (-64dB) */
9381da177e4SLinus Torvalds uinfo->value.integer.max = PCM_RES; /* 0dB */
9391da177e4SLinus Torvalds return 0;
9401da177e4SLinus Torvalds }
9411da177e4SLinus Torvalds
wm_pcm_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)942ab0c7d72STakashi Iwai static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9431da177e4SLinus Torvalds {
944ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
9451da177e4SLinus Torvalds unsigned short val;
9461da177e4SLinus Torvalds
94762932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
9481da177e4SLinus Torvalds val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
9491da177e4SLinus Torvalds val = val > PCM_MIN ? (val - PCM_MIN) : 0;
9501da177e4SLinus Torvalds ucontrol->value.integer.value[0] = val;
95162932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
9521da177e4SLinus Torvalds return 0;
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds
wm_pcm_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)955ab0c7d72STakashi Iwai static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9561da177e4SLinus Torvalds {
957ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
9581da177e4SLinus Torvalds unsigned short ovol, nvol;
9591da177e4SLinus Torvalds int change = 0;
9601da177e4SLinus Torvalds
9611da177e4SLinus Torvalds nvol = ucontrol->value.integer.value[0];
9629cd17cd2STakashi Iwai if (nvol > PCM_RES)
9639cd17cd2STakashi Iwai return -EINVAL;
9649cd17cd2STakashi Iwai snd_ice1712_save_gpio_status(ice);
9651da177e4SLinus Torvalds nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
9661da177e4SLinus Torvalds ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
9671da177e4SLinus Torvalds if (ovol != nvol) {
9681da177e4SLinus Torvalds wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
9691da177e4SLinus Torvalds wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
9701da177e4SLinus Torvalds change = 1;
9711da177e4SLinus Torvalds }
9721da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
9731da177e4SLinus Torvalds return change;
9741da177e4SLinus Torvalds }
9751da177e4SLinus Torvalds
9761da177e4SLinus Torvalds /*
9771da177e4SLinus Torvalds * ADC mute control
9781da177e4SLinus Torvalds */
979a5ce8890STakashi Iwai #define wm_adc_mute_info snd_ctl_boolean_stereo_info
9801da177e4SLinus Torvalds
wm_adc_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)981ab0c7d72STakashi Iwai static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9821da177e4SLinus Torvalds {
983ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
9841da177e4SLinus Torvalds unsigned short val;
9851da177e4SLinus Torvalds int i;
9861da177e4SLinus Torvalds
98762932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
9881da177e4SLinus Torvalds for (i = 0; i < 2; i++) {
9891da177e4SLinus Torvalds val = wm_get(ice, WM_ADC_GAIN + i);
9901da177e4SLinus Torvalds ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
9911da177e4SLinus Torvalds }
99262932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
9931da177e4SLinus Torvalds return 0;
9941da177e4SLinus Torvalds }
9951da177e4SLinus Torvalds
wm_adc_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)996ab0c7d72STakashi Iwai static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9971da177e4SLinus Torvalds {
998ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
9991da177e4SLinus Torvalds unsigned short new, old;
10001da177e4SLinus Torvalds int i, change = 0;
10011da177e4SLinus Torvalds
10021da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
10031da177e4SLinus Torvalds for (i = 0; i < 2; i++) {
10041da177e4SLinus Torvalds old = wm_get(ice, WM_ADC_GAIN + i);
10051da177e4SLinus Torvalds new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
10061da177e4SLinus Torvalds if (new != old) {
10071da177e4SLinus Torvalds wm_put(ice, WM_ADC_GAIN + i, new);
10081da177e4SLinus Torvalds change = 1;
10091da177e4SLinus Torvalds }
10101da177e4SLinus Torvalds }
10111da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
10121da177e4SLinus Torvalds
10131da177e4SLinus Torvalds return change;
10141da177e4SLinus Torvalds }
10151da177e4SLinus Torvalds
10161da177e4SLinus Torvalds /*
10171da177e4SLinus Torvalds * ADC gain mixer control
10181da177e4SLinus Torvalds */
wm_adc_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1019ab0c7d72STakashi Iwai static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
10201da177e4SLinus Torvalds {
10211da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
10221da177e4SLinus Torvalds uinfo->count = 2;
10231da177e4SLinus Torvalds uinfo->value.integer.min = 0; /* -12dB */
10241da177e4SLinus Torvalds uinfo->value.integer.max = 0x1f; /* 19dB */
10251da177e4SLinus Torvalds return 0;
10261da177e4SLinus Torvalds }
10271da177e4SLinus Torvalds
wm_adc_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1028ab0c7d72STakashi Iwai static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
10291da177e4SLinus Torvalds {
1030ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
10311da177e4SLinus Torvalds int i, idx;
10321da177e4SLinus Torvalds unsigned short vol;
10331da177e4SLinus Torvalds
103462932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
10351da177e4SLinus Torvalds for (i = 0; i < 2; i++) {
10361da177e4SLinus Torvalds idx = WM_ADC_GAIN + i;
10371da177e4SLinus Torvalds vol = wm_get(ice, idx) & 0x1f;
10381da177e4SLinus Torvalds ucontrol->value.integer.value[i] = vol;
10391da177e4SLinus Torvalds }
104062932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
10411da177e4SLinus Torvalds return 0;
10421da177e4SLinus Torvalds }
10431da177e4SLinus Torvalds
wm_adc_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1044ab0c7d72STakashi Iwai static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
10451da177e4SLinus Torvalds {
1046ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
10471da177e4SLinus Torvalds int i, idx;
10481da177e4SLinus Torvalds unsigned short ovol, nvol;
10491da177e4SLinus Torvalds int change = 0;
10501da177e4SLinus Torvalds
10511da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
10521da177e4SLinus Torvalds for (i = 0; i < 2; i++) {
10531da177e4SLinus Torvalds idx = WM_ADC_GAIN + i;
10549cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[i] & 0x1f;
10551da177e4SLinus Torvalds ovol = wm_get(ice, idx);
10561da177e4SLinus Torvalds if ((ovol & 0x1f) != nvol) {
10571da177e4SLinus Torvalds wm_put(ice, idx, nvol | (ovol & ~0x1f));
10581da177e4SLinus Torvalds change = 1;
10591da177e4SLinus Torvalds }
10601da177e4SLinus Torvalds }
10611da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
10621da177e4SLinus Torvalds return change;
10631da177e4SLinus Torvalds }
10641da177e4SLinus Torvalds
10651da177e4SLinus Torvalds /*
10661da177e4SLinus Torvalds * ADC input mux mixer control
10671da177e4SLinus Torvalds */
wm_adc_mux_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1068ab0c7d72STakashi Iwai static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
10691da177e4SLinus Torvalds {
107032b47da0STakashi Iwai static const char * const texts[] = {
10711ce211a9SAlexander Beregalov "CD", /* AIN1 */
10721ce211a9SAlexander Beregalov "Aux", /* AIN2 */
10731ce211a9SAlexander Beregalov "Line", /* AIN3 */
10741ce211a9SAlexander Beregalov "Mic", /* AIN4 */
10751ce211a9SAlexander Beregalov "AC97" /* AIN5 */
10761da177e4SLinus Torvalds };
107732b47da0STakashi Iwai static const char * const universe_texts[] = {
10781ce211a9SAlexander Beregalov "Aux1", /* AIN1 */
10791ce211a9SAlexander Beregalov "CD", /* AIN2 */
10801ce211a9SAlexander Beregalov "Phono", /* AIN3 */
10811ce211a9SAlexander Beregalov "Line", /* AIN4 */
10821ce211a9SAlexander Beregalov "Aux2", /* AIN5 */
10831ce211a9SAlexander Beregalov "Mic", /* AIN6 */
10841ce211a9SAlexander Beregalov "Aux3", /* AIN7 */
10851ce211a9SAlexander Beregalov "AC97" /* AIN8 */
10861da177e4SLinus Torvalds };
1087ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
10881da177e4SLinus Torvalds
1089597da2e4STakashi Iwai if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE)
1090597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 2, 8, universe_texts);
1091597da2e4STakashi Iwai else
1092597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 2, 5, texts);
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds
wm_adc_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1095ab0c7d72STakashi Iwai static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
10961da177e4SLinus Torvalds {
1097ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
10981da177e4SLinus Torvalds unsigned short val;
10991da177e4SLinus Torvalds
110062932df8SIngo Molnar mutex_lock(&ice->gpio_mutex);
11011da177e4SLinus Torvalds val = wm_get(ice, WM_ADC_MUX);
11026682025eSTakashi Iwai ucontrol->value.enumerated.item[0] = val & 7;
11036682025eSTakashi Iwai ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
110462932df8SIngo Molnar mutex_unlock(&ice->gpio_mutex);
11051da177e4SLinus Torvalds return 0;
11061da177e4SLinus Torvalds }
11071da177e4SLinus Torvalds
wm_adc_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1108ab0c7d72STakashi Iwai static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11091da177e4SLinus Torvalds {
1110ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
11111da177e4SLinus Torvalds unsigned short oval, nval;
11121da177e4SLinus Torvalds int change;
11131da177e4SLinus Torvalds
11141da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
11151da177e4SLinus Torvalds oval = wm_get(ice, WM_ADC_MUX);
11161da177e4SLinus Torvalds nval = oval & ~0x77;
11176682025eSTakashi Iwai nval |= ucontrol->value.enumerated.item[0] & 7;
11186682025eSTakashi Iwai nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
11191da177e4SLinus Torvalds change = (oval != nval);
11201da177e4SLinus Torvalds if (change)
11211da177e4SLinus Torvalds wm_put(ice, WM_ADC_MUX, nval);
11221da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
112363786d06STakashi Iwai return change;
11241da177e4SLinus Torvalds }
11251da177e4SLinus Torvalds
11261da177e4SLinus Torvalds /*
11271da177e4SLinus Torvalds * CS8415 Input mux
11281da177e4SLinus Torvalds */
aureon_cs8415_mux_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1129ab0c7d72STakashi Iwai static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
11301da177e4SLinus Torvalds {
1131ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
113232b47da0STakashi Iwai static const char * const aureon_texts[] = {
11331ce211a9SAlexander Beregalov "CD", /* RXP0 */
11341ce211a9SAlexander Beregalov "Optical" /* RXP1 */
11351da177e4SLinus Torvalds };
113632b47da0STakashi Iwai static const char * const prodigy_texts[] = {
11371da177e4SLinus Torvalds "CD",
11381da177e4SLinus Torvalds "Coax"
11391da177e4SLinus Torvalds };
11401da177e4SLinus Torvalds if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1141597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts);
11421da177e4SLinus Torvalds else
1143597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts);
11441da177e4SLinus Torvalds }
11451da177e4SLinus Torvalds
aureon_cs8415_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1146ab0c7d72STakashi Iwai static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11471da177e4SLinus Torvalds {
1148ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
11497cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
11501da177e4SLinus Torvalds
11511ce211a9SAlexander Beregalov /* snd_ice1712_save_gpio_status(ice); */
11521ce211a9SAlexander Beregalov /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
11537cda8ba9STakashi Iwai ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
11541ce211a9SAlexander Beregalov /* snd_ice1712_restore_gpio_status(ice); */
11551da177e4SLinus Torvalds return 0;
11561da177e4SLinus Torvalds }
11571da177e4SLinus Torvalds
aureon_cs8415_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1158ab0c7d72STakashi Iwai static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11591da177e4SLinus Torvalds {
1160ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
11617cda8ba9STakashi Iwai struct aureon_spec *spec = ice->spec;
11621da177e4SLinus Torvalds unsigned short oval, nval;
11631da177e4SLinus Torvalds int change;
11641da177e4SLinus Torvalds
11651da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
11661da177e4SLinus Torvalds oval = aureon_cs8415_get(ice, CS8415_CTRL2);
11671da177e4SLinus Torvalds nval = oval & ~0x07;
11686682025eSTakashi Iwai nval |= ucontrol->value.enumerated.item[0] & 7;
11691da177e4SLinus Torvalds change = (oval != nval);
11701da177e4SLinus Torvalds if (change)
11711da177e4SLinus Torvalds aureon_cs8415_put(ice, CS8415_CTRL2, nval);
11721da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
11737cda8ba9STakashi Iwai spec->cs8415_mux = ucontrol->value.enumerated.item[0];
11741da177e4SLinus Torvalds return change;
11751da177e4SLinus Torvalds }
11761da177e4SLinus Torvalds
aureon_cs8415_rate_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1177ab0c7d72STakashi Iwai static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
11781da177e4SLinus Torvalds {
11791da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
11801da177e4SLinus Torvalds uinfo->count = 1;
11811da177e4SLinus Torvalds uinfo->value.integer.min = 0;
11821da177e4SLinus Torvalds uinfo->value.integer.max = 192000;
11831da177e4SLinus Torvalds return 0;
11841da177e4SLinus Torvalds }
11851da177e4SLinus Torvalds
aureon_cs8415_rate_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1186ab0c7d72STakashi Iwai static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11871da177e4SLinus Torvalds {
1188ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
11891da177e4SLinus Torvalds unsigned char ratio;
11901da177e4SLinus Torvalds ratio = aureon_cs8415_get(ice, CS8415_RATIO);
11911da177e4SLinus Torvalds ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
11921da177e4SLinus Torvalds return 0;
11931da177e4SLinus Torvalds }
11941da177e4SLinus Torvalds
11951da177e4SLinus Torvalds /*
11961da177e4SLinus Torvalds * CS8415A Mute
11971da177e4SLinus Torvalds */
1198a5ce8890STakashi Iwai #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
11991da177e4SLinus Torvalds
aureon_cs8415_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1200ab0c7d72STakashi Iwai static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12011da177e4SLinus Torvalds {
1202ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
12031da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
12041da177e4SLinus Torvalds ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
12051da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
12061da177e4SLinus Torvalds return 0;
12071da177e4SLinus Torvalds }
12081da177e4SLinus Torvalds
aureon_cs8415_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1209ab0c7d72STakashi Iwai static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12101da177e4SLinus Torvalds {
1211ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
12121da177e4SLinus Torvalds unsigned char oval, nval;
12131da177e4SLinus Torvalds int change;
12141da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
12151da177e4SLinus Torvalds oval = aureon_cs8415_get(ice, CS8415_CTRL1);
12161da177e4SLinus Torvalds if (ucontrol->value.integer.value[0])
12171da177e4SLinus Torvalds nval = oval & ~0x20;
12181da177e4SLinus Torvalds else
12191da177e4SLinus Torvalds nval = oval | 0x20;
12201ce211a9SAlexander Beregalov change = (oval != nval);
12211ce211a9SAlexander Beregalov if (change)
12221da177e4SLinus Torvalds aureon_cs8415_put(ice, CS8415_CTRL1, nval);
12231da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
12241da177e4SLinus Torvalds return change;
12251da177e4SLinus Torvalds }
12261da177e4SLinus Torvalds
12271da177e4SLinus Torvalds /*
12281da177e4SLinus Torvalds * CS8415A Q-Sub info
12291da177e4SLinus Torvalds */
aureon_cs8415_qsub_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)12301ce211a9SAlexander Beregalov static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
12311ce211a9SAlexander Beregalov {
12321da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
12331da177e4SLinus Torvalds uinfo->count = 10;
12341da177e4SLinus Torvalds return 0;
12351da177e4SLinus Torvalds }
12361da177e4SLinus Torvalds
aureon_cs8415_qsub_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)12371ce211a9SAlexander Beregalov static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12381ce211a9SAlexander Beregalov {
1239ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
12401da177e4SLinus Torvalds
12411da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
12421da177e4SLinus Torvalds aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
12431da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
12441da177e4SLinus Torvalds
12451da177e4SLinus Torvalds return 0;
12461da177e4SLinus Torvalds }
12471da177e4SLinus Torvalds
aureon_cs8415_spdif_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)12481ce211a9SAlexander Beregalov static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
12491ce211a9SAlexander Beregalov {
12501da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
12511da177e4SLinus Torvalds uinfo->count = 1;
12521da177e4SLinus Torvalds return 0;
12531da177e4SLinus Torvalds }
12541da177e4SLinus Torvalds
aureon_cs8415_mask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)12551ce211a9SAlexander Beregalov static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12561ce211a9SAlexander Beregalov {
12571da177e4SLinus Torvalds memset(ucontrol->value.iec958.status, 0xFF, 24);
12581da177e4SLinus Torvalds return 0;
12591da177e4SLinus Torvalds }
12601da177e4SLinus Torvalds
aureon_cs8415_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)12611ce211a9SAlexander Beregalov static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12621ce211a9SAlexander Beregalov {
1263ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
12641da177e4SLinus Torvalds
12651da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
12661da177e4SLinus Torvalds aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
12671da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
12681da177e4SLinus Torvalds return 0;
12691da177e4SLinus Torvalds }
12701da177e4SLinus Torvalds
12711da177e4SLinus Torvalds /*
12721da177e4SLinus Torvalds * Headphone Amplifier
12731da177e4SLinus Torvalds */
aureon_set_headphone_amp(struct snd_ice1712 * ice,int enable)1274ab0c7d72STakashi Iwai static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
12751da177e4SLinus Torvalds {
12761da177e4SLinus Torvalds unsigned int tmp, tmp2;
12771da177e4SLinus Torvalds
12781da177e4SLinus Torvalds tmp2 = tmp = snd_ice1712_gpio_read(ice);
12791da177e4SLinus Torvalds if (enable)
1280cdf88efaSToshimune Konno if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1281cdf88efaSToshimune Konno ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
12821da177e4SLinus Torvalds tmp |= AUREON_HP_SEL;
12831da177e4SLinus Torvalds else
1284c5130271STakashi Iwai tmp |= PRODIGY_HP_SEL;
1285c5130271STakashi Iwai else
1286cdf88efaSToshimune Konno if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1287cdf88efaSToshimune Konno ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
12881da177e4SLinus Torvalds tmp &= ~AUREON_HP_SEL;
1289c5130271STakashi Iwai else
1290c5130271STakashi Iwai tmp &= ~PRODIGY_HP_SEL;
12911da177e4SLinus Torvalds if (tmp != tmp2) {
12921da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
12931da177e4SLinus Torvalds return 1;
12941da177e4SLinus Torvalds }
12951da177e4SLinus Torvalds return 0;
12961da177e4SLinus Torvalds }
12971da177e4SLinus Torvalds
aureon_get_headphone_amp(struct snd_ice1712 * ice)1298ab0c7d72STakashi Iwai static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
12991da177e4SLinus Torvalds {
13001da177e4SLinus Torvalds unsigned int tmp = snd_ice1712_gpio_read(ice);
13011da177e4SLinus Torvalds
13021da177e4SLinus Torvalds return (tmp & AUREON_HP_SEL) != 0;
13031da177e4SLinus Torvalds }
13041da177e4SLinus Torvalds
1305a5ce8890STakashi Iwai #define aureon_hpamp_info snd_ctl_boolean_mono_info
13061da177e4SLinus Torvalds
aureon_hpamp_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1307ab0c7d72STakashi Iwai static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13081da177e4SLinus Torvalds {
1309ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13101da177e4SLinus Torvalds
13111da177e4SLinus Torvalds ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
13121da177e4SLinus Torvalds return 0;
13131da177e4SLinus Torvalds }
13141da177e4SLinus Torvalds
13151da177e4SLinus Torvalds
aureon_hpamp_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1316ab0c7d72STakashi Iwai static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13171da177e4SLinus Torvalds {
1318ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13191da177e4SLinus Torvalds
13201da177e4SLinus Torvalds return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
13211da177e4SLinus Torvalds }
13221da177e4SLinus Torvalds
13231da177e4SLinus Torvalds /*
13241da177e4SLinus Torvalds * Deemphasis
13251da177e4SLinus Torvalds */
13261da177e4SLinus Torvalds
1327a5ce8890STakashi Iwai #define aureon_deemp_info snd_ctl_boolean_mono_info
13281da177e4SLinus Torvalds
aureon_deemp_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1329ab0c7d72STakashi Iwai static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13301da177e4SLinus Torvalds {
1331ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13321da177e4SLinus Torvalds ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
13331da177e4SLinus Torvalds return 0;
13341da177e4SLinus Torvalds }
13351da177e4SLinus Torvalds
aureon_deemp_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1336ab0c7d72STakashi Iwai static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13371da177e4SLinus Torvalds {
1338ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13391da177e4SLinus Torvalds int temp, temp2;
13401da177e4SLinus Torvalds temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
13411da177e4SLinus Torvalds if (ucontrol->value.integer.value[0])
13421da177e4SLinus Torvalds temp |= 0xf;
13431da177e4SLinus Torvalds else
13441da177e4SLinus Torvalds temp &= ~0xf;
13451da177e4SLinus Torvalds if (temp != temp2) {
13461da177e4SLinus Torvalds wm_put(ice, WM_DAC_CTRL2, temp);
13471da177e4SLinus Torvalds return 1;
13481da177e4SLinus Torvalds }
13491da177e4SLinus Torvalds return 0;
13501da177e4SLinus Torvalds }
13511da177e4SLinus Torvalds
13521da177e4SLinus Torvalds /*
13531da177e4SLinus Torvalds * ADC Oversampling
13541da177e4SLinus Torvalds */
aureon_oversampling_info(struct snd_kcontrol * k,struct snd_ctl_elem_info * uinfo)1355ab0c7d72STakashi Iwai static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
13561da177e4SLinus Torvalds {
135732b47da0STakashi Iwai static const char * const texts[2] = { "128x", "64x" };
13581da177e4SLinus Torvalds
1359597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 2, texts);
13601da177e4SLinus Torvalds }
13611da177e4SLinus Torvalds
aureon_oversampling_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1362ab0c7d72STakashi Iwai static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13631da177e4SLinus Torvalds {
1364ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13651da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
13661da177e4SLinus Torvalds return 0;
13671da177e4SLinus Torvalds }
13681da177e4SLinus Torvalds
aureon_oversampling_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1369ab0c7d72STakashi Iwai static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13701da177e4SLinus Torvalds {
13711da177e4SLinus Torvalds int temp, temp2;
1372ab0c7d72STakashi Iwai struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
13731da177e4SLinus Torvalds
13741da177e4SLinus Torvalds temp2 = temp = wm_get(ice, WM_MASTER);
13751da177e4SLinus Torvalds
13761da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0])
13771da177e4SLinus Torvalds temp |= 0x8;
13781da177e4SLinus Torvalds else
13791da177e4SLinus Torvalds temp &= ~0x8;
13801da177e4SLinus Torvalds
13811da177e4SLinus Torvalds if (temp != temp2) {
13821da177e4SLinus Torvalds wm_put(ice, WM_MASTER, temp);
13831da177e4SLinus Torvalds return 1;
13841da177e4SLinus Torvalds }
13851da177e4SLinus Torvalds return 0;
13861da177e4SLinus Torvalds }
13871da177e4SLinus Torvalds
13881da177e4SLinus Torvalds /*
13891da177e4SLinus Torvalds * mixers
13901da177e4SLinus Torvalds */
13911da177e4SLinus Torvalds
1392b4e5e707STakashi Iwai static const struct snd_kcontrol_new aureon_dac_controls[] = {
13931da177e4SLinus Torvalds {
13941da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13951da177e4SLinus Torvalds .name = "Master Playback Switch",
13961da177e4SLinus Torvalds .info = wm_master_mute_info,
13971da177e4SLinus Torvalds .get = wm_master_mute_get,
13981da177e4SLinus Torvalds .put = wm_master_mute_put
13991da177e4SLinus Torvalds },
14001da177e4SLinus Torvalds {
14011da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1402f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1403f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14041da177e4SLinus Torvalds .name = "Master Playback Volume",
14051da177e4SLinus Torvalds .info = wm_master_vol_info,
14061da177e4SLinus Torvalds .get = wm_master_vol_get,
1407f640c320STakashi Iwai .put = wm_master_vol_put,
1408f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
14091da177e4SLinus Torvalds },
14101da177e4SLinus Torvalds {
14111da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14121da177e4SLinus Torvalds .name = "Front Playback Switch",
14131da177e4SLinus Torvalds .info = wm_mute_info,
14141da177e4SLinus Torvalds .get = wm_mute_get,
14151da177e4SLinus Torvalds .put = wm_mute_put,
14161da177e4SLinus Torvalds .private_value = (2 << 8) | 0
14171da177e4SLinus Torvalds },
14181da177e4SLinus Torvalds {
14191da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1421f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14221da177e4SLinus Torvalds .name = "Front Playback Volume",
14231da177e4SLinus Torvalds .info = wm_vol_info,
14241da177e4SLinus Torvalds .get = wm_vol_get,
14251da177e4SLinus Torvalds .put = wm_vol_put,
1426f640c320STakashi Iwai .private_value = (2 << 8) | 0,
1427f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
14281da177e4SLinus Torvalds },
14291da177e4SLinus Torvalds {
14301da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14311da177e4SLinus Torvalds .name = "Rear Playback Switch",
14321da177e4SLinus Torvalds .info = wm_mute_info,
14331da177e4SLinus Torvalds .get = wm_mute_get,
14341da177e4SLinus Torvalds .put = wm_mute_put,
14351da177e4SLinus Torvalds .private_value = (2 << 8) | 2
14361da177e4SLinus Torvalds },
14371da177e4SLinus Torvalds {
14381da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1440f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14411da177e4SLinus Torvalds .name = "Rear Playback Volume",
14421da177e4SLinus Torvalds .info = wm_vol_info,
14431da177e4SLinus Torvalds .get = wm_vol_get,
14441da177e4SLinus Torvalds .put = wm_vol_put,
1445f640c320STakashi Iwai .private_value = (2 << 8) | 2,
1446f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
14471da177e4SLinus Torvalds },
14481da177e4SLinus Torvalds {
14491da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14501da177e4SLinus Torvalds .name = "Center Playback Switch",
14511da177e4SLinus Torvalds .info = wm_mute_info,
14521da177e4SLinus Torvalds .get = wm_mute_get,
14531da177e4SLinus Torvalds .put = wm_mute_put,
14541da177e4SLinus Torvalds .private_value = (1 << 8) | 4
14551da177e4SLinus Torvalds },
14561da177e4SLinus Torvalds {
14571da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1458f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1459f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14601da177e4SLinus Torvalds .name = "Center Playback Volume",
14611da177e4SLinus Torvalds .info = wm_vol_info,
14621da177e4SLinus Torvalds .get = wm_vol_get,
14631da177e4SLinus Torvalds .put = wm_vol_put,
1464f640c320STakashi Iwai .private_value = (1 << 8) | 4,
1465f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
14661da177e4SLinus Torvalds },
14671da177e4SLinus Torvalds {
14681da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14691da177e4SLinus Torvalds .name = "LFE Playback Switch",
14701da177e4SLinus Torvalds .info = wm_mute_info,
14711da177e4SLinus Torvalds .get = wm_mute_get,
14721da177e4SLinus Torvalds .put = wm_mute_put,
14731da177e4SLinus Torvalds .private_value = (1 << 8) | 5
14741da177e4SLinus Torvalds },
14751da177e4SLinus Torvalds {
14761da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1477f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1478f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14791da177e4SLinus Torvalds .name = "LFE Playback Volume",
14801da177e4SLinus Torvalds .info = wm_vol_info,
14811da177e4SLinus Torvalds .get = wm_vol_get,
14821da177e4SLinus Torvalds .put = wm_vol_put,
1483f640c320STakashi Iwai .private_value = (1 << 8) | 5,
1484f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
14851da177e4SLinus Torvalds },
14861da177e4SLinus Torvalds {
14871da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14881da177e4SLinus Torvalds .name = "Side Playback Switch",
14891da177e4SLinus Torvalds .info = wm_mute_info,
14901da177e4SLinus Torvalds .get = wm_mute_get,
14911da177e4SLinus Torvalds .put = wm_mute_put,
14921da177e4SLinus Torvalds .private_value = (2 << 8) | 6
14931da177e4SLinus Torvalds },
14941da177e4SLinus Torvalds {
14951da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1496f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1497f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
14981da177e4SLinus Torvalds .name = "Side Playback Volume",
14991da177e4SLinus Torvalds .info = wm_vol_info,
15001da177e4SLinus Torvalds .get = wm_vol_get,
15011da177e4SLinus Torvalds .put = wm_vol_put,
1502f640c320STakashi Iwai .private_value = (2 << 8) | 6,
1503f640c320STakashi Iwai .tlv = { .p = db_scale_wm_dac }
15041da177e4SLinus Torvalds }
15051da177e4SLinus Torvalds };
15061da177e4SLinus Torvalds
1507b4e5e707STakashi Iwai static const struct snd_kcontrol_new wm_controls[] = {
15081da177e4SLinus Torvalds {
15091da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15101da177e4SLinus Torvalds .name = "PCM Playback Switch",
15111da177e4SLinus Torvalds .info = wm_pcm_mute_info,
15121da177e4SLinus Torvalds .get = wm_pcm_mute_get,
15131da177e4SLinus Torvalds .put = wm_pcm_mute_put
15141da177e4SLinus Torvalds },
15151da177e4SLinus Torvalds {
15161da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
15191da177e4SLinus Torvalds .name = "PCM Playback Volume",
15201da177e4SLinus Torvalds .info = wm_pcm_vol_info,
15211da177e4SLinus Torvalds .get = wm_pcm_vol_get,
1522f640c320STakashi Iwai .put = wm_pcm_vol_put,
1523f640c320STakashi Iwai .tlv = { .p = db_scale_wm_pcm }
15241da177e4SLinus Torvalds },
15251da177e4SLinus Torvalds {
15261da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15271da177e4SLinus Torvalds .name = "Capture Switch",
15281da177e4SLinus Torvalds .info = wm_adc_mute_info,
15291da177e4SLinus Torvalds .get = wm_adc_mute_get,
15301da177e4SLinus Torvalds .put = wm_adc_mute_put,
15311da177e4SLinus Torvalds },
15321da177e4SLinus Torvalds {
15331da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
15361da177e4SLinus Torvalds .name = "Capture Volume",
15371da177e4SLinus Torvalds .info = wm_adc_vol_info,
15381da177e4SLinus Torvalds .get = wm_adc_vol_get,
1539f640c320STakashi Iwai .put = wm_adc_vol_put,
1540f640c320STakashi Iwai .tlv = { .p = db_scale_wm_adc }
15411da177e4SLinus Torvalds },
15421da177e4SLinus Torvalds {
15431da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15441da177e4SLinus Torvalds .name = "Capture Source",
15451da177e4SLinus Torvalds .info = wm_adc_mux_info,
15461da177e4SLinus Torvalds .get = wm_adc_mux_get,
15471da177e4SLinus Torvalds .put = wm_adc_mux_put,
15481da177e4SLinus Torvalds .private_value = 5
15491da177e4SLinus Torvalds },
15501da177e4SLinus Torvalds {
15511da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15521da177e4SLinus Torvalds .name = "External Amplifier",
15531da177e4SLinus Torvalds .info = aureon_hpamp_info,
15541da177e4SLinus Torvalds .get = aureon_hpamp_get,
15551da177e4SLinus Torvalds .put = aureon_hpamp_put
15561da177e4SLinus Torvalds },
15571da177e4SLinus Torvalds {
15581da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15591da177e4SLinus Torvalds .name = "DAC Deemphasis Switch",
15601da177e4SLinus Torvalds .info = aureon_deemp_info,
15611da177e4SLinus Torvalds .get = aureon_deemp_get,
15621da177e4SLinus Torvalds .put = aureon_deemp_put
15631da177e4SLinus Torvalds },
15641da177e4SLinus Torvalds {
15651da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15661da177e4SLinus Torvalds .name = "ADC Oversampling",
15671da177e4SLinus Torvalds .info = aureon_oversampling_info,
15681da177e4SLinus Torvalds .get = aureon_oversampling_get,
15691da177e4SLinus Torvalds .put = aureon_oversampling_put
15701da177e4SLinus Torvalds }
15711da177e4SLinus Torvalds };
15721da177e4SLinus Torvalds
1573b4e5e707STakashi Iwai static const struct snd_kcontrol_new ac97_controls[] = {
15741da177e4SLinus Torvalds {
15751da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15761da177e4SLinus Torvalds .name = "AC97 Playback Switch",
15771da177e4SLinus Torvalds .info = aureon_ac97_mmute_info,
15781da177e4SLinus Torvalds .get = aureon_ac97_mmute_get,
15791da177e4SLinus Torvalds .put = aureon_ac97_mmute_put,
15801da177e4SLinus Torvalds .private_value = AC97_MASTER
15811da177e4SLinus Torvalds },
15821da177e4SLinus Torvalds {
15831da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1585f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
15861da177e4SLinus Torvalds .name = "AC97 Playback Volume",
15871da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
15881da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
15891da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1590f640c320STakashi Iwai .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1591f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_master }
15921da177e4SLinus Torvalds },
15931da177e4SLinus Torvalds {
15941da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15951da177e4SLinus Torvalds .name = "CD Playback Switch",
15961da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
15971da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
15981da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
15991da177e4SLinus Torvalds .private_value = AC97_CD
16001da177e4SLinus Torvalds },
16011da177e4SLinus Torvalds {
16021da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1604f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
16051da177e4SLinus Torvalds .name = "CD Playback Volume",
16061da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
16071da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
16081da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1609f640c320STakashi Iwai .private_value = AC97_CD|AUREON_AC97_STEREO,
1610f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
16111da177e4SLinus Torvalds },
16121da177e4SLinus Torvalds {
16131da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16141da177e4SLinus Torvalds .name = "Aux Playback Switch",
16151da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
16161da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
16171da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
16181da177e4SLinus Torvalds .private_value = AC97_AUX,
16191da177e4SLinus Torvalds },
16201da177e4SLinus Torvalds {
16211da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1623f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
16241da177e4SLinus Torvalds .name = "Aux Playback Volume",
16251da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
16261da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
16271da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1628f640c320STakashi Iwai .private_value = AC97_AUX|AUREON_AC97_STEREO,
1629f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
16301da177e4SLinus Torvalds },
16311da177e4SLinus Torvalds {
16321da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16331da177e4SLinus Torvalds .name = "Line Playback Switch",
16341da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
16351da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
16361da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
16371da177e4SLinus Torvalds .private_value = AC97_LINE
16381da177e4SLinus Torvalds },
16391da177e4SLinus Torvalds {
16401da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1641f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1642f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
16431da177e4SLinus Torvalds .name = "Line Playback Volume",
16441da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
16451da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
16461da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1647f640c320STakashi Iwai .private_value = AC97_LINE|AUREON_AC97_STEREO,
1648f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
16491da177e4SLinus Torvalds },
16501da177e4SLinus Torvalds {
16511da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16521da177e4SLinus Torvalds .name = "Mic Playback Switch",
16531da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
16541da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
16551da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
16561da177e4SLinus Torvalds .private_value = AC97_MIC
16571da177e4SLinus Torvalds },
16581da177e4SLinus Torvalds {
16591da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1661f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
16621da177e4SLinus Torvalds .name = "Mic Playback Volume",
16631da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
16641da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
16651da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1666f640c320STakashi Iwai .private_value = AC97_MIC,
1667f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
16681da177e4SLinus Torvalds },
16691da177e4SLinus Torvalds {
16701da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16711da177e4SLinus Torvalds .name = "Mic Boost (+20dB)",
16721da177e4SLinus Torvalds .info = aureon_ac97_micboost_info,
16731da177e4SLinus Torvalds .get = aureon_ac97_micboost_get,
16741da177e4SLinus Torvalds .put = aureon_ac97_micboost_put
16751da177e4SLinus Torvalds }
16761da177e4SLinus Torvalds };
16771da177e4SLinus Torvalds
1678b4e5e707STakashi Iwai static const struct snd_kcontrol_new universe_ac97_controls[] = {
16791da177e4SLinus Torvalds {
16801da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16811da177e4SLinus Torvalds .name = "AC97 Playback Switch",
16821da177e4SLinus Torvalds .info = aureon_ac97_mmute_info,
16831da177e4SLinus Torvalds .get = aureon_ac97_mmute_get,
16841da177e4SLinus Torvalds .put = aureon_ac97_mmute_put,
16851da177e4SLinus Torvalds .private_value = AC97_MASTER
16861da177e4SLinus Torvalds },
16871da177e4SLinus Torvalds {
16881da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1689f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1690f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
16911da177e4SLinus Torvalds .name = "AC97 Playback Volume",
16921da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
16931da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
16941da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1695f640c320STakashi Iwai .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1696f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_master }
16971da177e4SLinus Torvalds },
16981da177e4SLinus Torvalds {
16991da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17001da177e4SLinus Torvalds .name = "CD Playback Switch",
17011da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
17021da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
17031da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
17041da177e4SLinus Torvalds .private_value = AC97_AUX
17051da177e4SLinus Torvalds },
17061da177e4SLinus Torvalds {
17071da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1709f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
17101da177e4SLinus Torvalds .name = "CD Playback Volume",
17111da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
17121da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
17131da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1714f640c320STakashi Iwai .private_value = AC97_AUX|AUREON_AC97_STEREO,
1715f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
17161da177e4SLinus Torvalds },
17171da177e4SLinus Torvalds {
17181da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17191da177e4SLinus Torvalds .name = "Phono Playback Switch",
17201da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
17211da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
17221da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
1723f640c320STakashi Iwai .private_value = AC97_CD
17241da177e4SLinus Torvalds },
17251da177e4SLinus Torvalds {
17261da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1727f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1728f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
17291da177e4SLinus Torvalds .name = "Phono Playback Volume",
17301da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
17311da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
17321da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1733f640c320STakashi Iwai .private_value = AC97_CD|AUREON_AC97_STEREO,
1734f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
17351da177e4SLinus Torvalds },
17361da177e4SLinus Torvalds {
17371da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17381da177e4SLinus Torvalds .name = "Line Playback Switch",
17391da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
17401da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
17411da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
17421da177e4SLinus Torvalds .private_value = AC97_LINE
17431da177e4SLinus Torvalds },
17441da177e4SLinus Torvalds {
17451da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1747f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
17481da177e4SLinus Torvalds .name = "Line Playback Volume",
17491da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
17501da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
17511da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1752f640c320STakashi Iwai .private_value = AC97_LINE|AUREON_AC97_STEREO,
1753f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
17541da177e4SLinus Torvalds },
17551da177e4SLinus Torvalds {
17561da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17571da177e4SLinus Torvalds .name = "Mic Playback Switch",
17581da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
17591da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
17601da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
17611da177e4SLinus Torvalds .private_value = AC97_MIC
17621da177e4SLinus Torvalds },
17631da177e4SLinus Torvalds {
17641da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1766f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
17671da177e4SLinus Torvalds .name = "Mic Playback Volume",
17681da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
17691da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
17701da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1771f640c320STakashi Iwai .private_value = AC97_MIC,
1772f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
17731da177e4SLinus Torvalds },
17741da177e4SLinus Torvalds {
17751da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17761da177e4SLinus Torvalds .name = "Mic Boost (+20dB)",
17771da177e4SLinus Torvalds .info = aureon_ac97_micboost_info,
17781da177e4SLinus Torvalds .get = aureon_ac97_micboost_get,
17791da177e4SLinus Torvalds .put = aureon_ac97_micboost_put
17801da177e4SLinus Torvalds },
17811da177e4SLinus Torvalds {
17821da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17831da177e4SLinus Torvalds .name = "Aux Playback Switch",
17841da177e4SLinus Torvalds .info = aureon_ac97_mute_info,
17851da177e4SLinus Torvalds .get = aureon_ac97_mute_get,
17861da177e4SLinus Torvalds .put = aureon_ac97_mute_put,
17871da177e4SLinus Torvalds .private_value = AC97_VIDEO,
17881da177e4SLinus Torvalds },
17891da177e4SLinus Torvalds {
17901da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791f640c320STakashi Iwai .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1792f640c320STakashi Iwai SNDRV_CTL_ELEM_ACCESS_TLV_READ),
17931da177e4SLinus Torvalds .name = "Aux Playback Volume",
17941da177e4SLinus Torvalds .info = aureon_ac97_vol_info,
17951da177e4SLinus Torvalds .get = aureon_ac97_vol_get,
17961da177e4SLinus Torvalds .put = aureon_ac97_vol_put,
1797f640c320STakashi Iwai .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1798f640c320STakashi Iwai .tlv = { .p = db_scale_ac97_gain }
1799af9b70acSMaximilian Rehkopf },
1800af9b70acSMaximilian Rehkopf {
1801af9b70acSMaximilian Rehkopf .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1802af9b70acSMaximilian Rehkopf .name = "Aux Source",
1803af9b70acSMaximilian Rehkopf .info = aureon_universe_inmux_info,
1804af9b70acSMaximilian Rehkopf .get = aureon_universe_inmux_get,
1805af9b70acSMaximilian Rehkopf .put = aureon_universe_inmux_put
18061da177e4SLinus Torvalds }
1807af9b70acSMaximilian Rehkopf
18081da177e4SLinus Torvalds };
18091da177e4SLinus Torvalds
1810b4e5e707STakashi Iwai static const struct snd_kcontrol_new cs8415_controls[] = {
18111da177e4SLinus Torvalds {
18121da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
18131da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
18141da177e4SLinus Torvalds .info = aureon_cs8415_mute_info,
18151da177e4SLinus Torvalds .get = aureon_cs8415_mute_get,
18161da177e4SLinus Torvalds .put = aureon_cs8415_mute_put
18171da177e4SLinus Torvalds },
18181da177e4SLinus Torvalds {
18191da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
18201da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
18211da177e4SLinus Torvalds .info = aureon_cs8415_mux_info,
18221da177e4SLinus Torvalds .get = aureon_cs8415_mux_get,
18231da177e4SLinus Torvalds .put = aureon_cs8415_mux_put,
18241da177e4SLinus Torvalds },
18251da177e4SLinus Torvalds {
18261da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
18271da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
18281da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
18291da177e4SLinus Torvalds .info = aureon_cs8415_qsub_info,
18301da177e4SLinus Torvalds .get = aureon_cs8415_qsub_get,
18311da177e4SLinus Torvalds },
18321da177e4SLinus Torvalds {
18331da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
18341da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
18351da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ,
18361da177e4SLinus Torvalds .info = aureon_cs8415_spdif_info,
18371da177e4SLinus Torvalds .get = aureon_cs8415_mask_get
18381da177e4SLinus Torvalds },
18391da177e4SLinus Torvalds {
18401da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
18411da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
18421da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
18431da177e4SLinus Torvalds .info = aureon_cs8415_spdif_info,
18441da177e4SLinus Torvalds .get = aureon_cs8415_spdif_get
18451da177e4SLinus Torvalds },
18461da177e4SLinus Torvalds {
18471da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
18481da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
18491da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
18501da177e4SLinus Torvalds .info = aureon_cs8415_rate_info,
18511da177e4SLinus Torvalds .get = aureon_cs8415_rate_get
18521da177e4SLinus Torvalds }
18531da177e4SLinus Torvalds };
18541da177e4SLinus Torvalds
aureon_add_controls(struct snd_ice1712 * ice)1855e23e7a14SBill Pemberton static int aureon_add_controls(struct snd_ice1712 *ice)
18561da177e4SLinus Torvalds {
18571da177e4SLinus Torvalds unsigned int i, counts;
18581da177e4SLinus Torvalds int err;
18591da177e4SLinus Torvalds
18601da177e4SLinus Torvalds counts = ARRAY_SIZE(aureon_dac_controls);
18611da177e4SLinus Torvalds if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
18621da177e4SLinus Torvalds counts -= 2; /* no side */
18631da177e4SLinus Torvalds for (i = 0; i < counts; i++) {
18641da177e4SLinus Torvalds err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
18651da177e4SLinus Torvalds if (err < 0)
18661da177e4SLinus Torvalds return err;
18671da177e4SLinus Torvalds }
18681da177e4SLinus Torvalds
18691da177e4SLinus Torvalds for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
18701da177e4SLinus Torvalds err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
18711da177e4SLinus Torvalds if (err < 0)
18721da177e4SLinus Torvalds return err;
18731da177e4SLinus Torvalds }
18741da177e4SLinus Torvalds
18751da177e4SLinus Torvalds if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
18761da177e4SLinus Torvalds for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
18771da177e4SLinus Torvalds err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
18781da177e4SLinus Torvalds if (err < 0)
18791da177e4SLinus Torvalds return err;
18801da177e4SLinus Torvalds }
18811ce211a9SAlexander Beregalov } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1882cdf88efaSToshimune Konno ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
18831da177e4SLinus Torvalds for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
18841da177e4SLinus Torvalds err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
18851da177e4SLinus Torvalds if (err < 0)
18861da177e4SLinus Torvalds return err;
18871da177e4SLinus Torvalds }
18881da177e4SLinus Torvalds }
18891da177e4SLinus Torvalds
1890cdf88efaSToshimune Konno if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1891cdf88efaSToshimune Konno ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
18921da177e4SLinus Torvalds unsigned char id;
18931da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
18941da177e4SLinus Torvalds id = aureon_cs8415_get(ice, CS8415_ID);
1895951606a1SDmitry Fomin snd_ice1712_restore_gpio_status(ice);
18961da177e4SLinus Torvalds if (id != 0x41)
18976dfb5affSTakashi Iwai dev_info(ice->card->dev,
18986dfb5affSTakashi Iwai "No CS8415 chip. Skipping CS8415 controls.\n");
18991da177e4SLinus Torvalds else {
19001da177e4SLinus Torvalds for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1901ab0c7d72STakashi Iwai struct snd_kcontrol *kctl;
1902*b9a4efd6SJaroslav Kysela kctl = snd_ctl_new1(&cs8415_controls[i], ice);
19031da177e4SLinus Torvalds if (i > 1)
19041da177e4SLinus Torvalds kctl->id.device = ice->pcm->device;
1905*b9a4efd6SJaroslav Kysela err = snd_ctl_add(ice->card, kctl);
1906*b9a4efd6SJaroslav Kysela if (err < 0)
1907*b9a4efd6SJaroslav Kysela return err;
19081da177e4SLinus Torvalds }
19091da177e4SLinus Torvalds }
19101da177e4SLinus Torvalds }
19111da177e4SLinus Torvalds
19121da177e4SLinus Torvalds return 0;
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds
19151da177e4SLinus Torvalds /*
1916ae761481SBernhard Urban * reset the chip
19171da177e4SLinus Torvalds */
aureon_reset(struct snd_ice1712 * ice)1918ae761481SBernhard Urban static int aureon_reset(struct snd_ice1712 *ice)
19191da177e4SLinus Torvalds {
192032b47da0STakashi Iwai static const unsigned short wm_inits_aureon[] = {
19211da177e4SLinus Torvalds /* These come first to reduce init pop noise */
19221da177e4SLinus Torvalds 0x1b, 0x044, /* ADC Mux (AC'97 source) */
19231da177e4SLinus Torvalds 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
19241da177e4SLinus Torvalds 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
19251da177e4SLinus Torvalds
19261da177e4SLinus Torvalds 0x18, 0x000, /* All power-up */
19271da177e4SLinus Torvalds
19281da177e4SLinus Torvalds 0x16, 0x122, /* I2S, normal polarity, 24bit */
19291da177e4SLinus Torvalds 0x17, 0x022, /* 256fs, slave mode */
19301da177e4SLinus Torvalds 0x00, 0, /* DAC1 analog mute */
19311da177e4SLinus Torvalds 0x01, 0, /* DAC2 analog mute */
19321da177e4SLinus Torvalds 0x02, 0, /* DAC3 analog mute */
19331da177e4SLinus Torvalds 0x03, 0, /* DAC4 analog mute */
19341da177e4SLinus Torvalds 0x04, 0, /* DAC5 analog mute */
19351da177e4SLinus Torvalds 0x05, 0, /* DAC6 analog mute */
19361da177e4SLinus Torvalds 0x06, 0, /* DAC7 analog mute */
19371da177e4SLinus Torvalds 0x07, 0, /* DAC8 analog mute */
19381da177e4SLinus Torvalds 0x08, 0x100, /* master analog mute */
19391da177e4SLinus Torvalds 0x09, 0xff, /* DAC1 digital full */
19401da177e4SLinus Torvalds 0x0a, 0xff, /* DAC2 digital full */
19411da177e4SLinus Torvalds 0x0b, 0xff, /* DAC3 digital full */
19421da177e4SLinus Torvalds 0x0c, 0xff, /* DAC4 digital full */
19431da177e4SLinus Torvalds 0x0d, 0xff, /* DAC5 digital full */
19441da177e4SLinus Torvalds 0x0e, 0xff, /* DAC6 digital full */
19451da177e4SLinus Torvalds 0x0f, 0xff, /* DAC7 digital full */
19461da177e4SLinus Torvalds 0x10, 0xff, /* DAC8 digital full */
19471da177e4SLinus Torvalds 0x11, 0x1ff, /* master digital full */
19481da177e4SLinus Torvalds 0x12, 0x000, /* phase normal */
19491da177e4SLinus Torvalds 0x13, 0x090, /* unmute DAC L/R */
19501da177e4SLinus Torvalds 0x14, 0x000, /* all unmute */
19511da177e4SLinus Torvalds 0x15, 0x000, /* no deemphasis, no ZFLG */
19521da177e4SLinus Torvalds 0x19, 0x000, /* -12dB ADC/L */
19531da177e4SLinus Torvalds 0x1a, 0x000, /* -12dB ADC/R */
19541da177e4SLinus Torvalds (unsigned short)-1
19551da177e4SLinus Torvalds };
195632b47da0STakashi Iwai static const unsigned short wm_inits_prodigy[] = {
19571da177e4SLinus Torvalds
19581da177e4SLinus Torvalds /* These come first to reduce init pop noise */
19591da177e4SLinus Torvalds 0x1b, 0x000, /* ADC Mux */
19601da177e4SLinus Torvalds 0x1c, 0x009, /* Out Mux1 */
19611da177e4SLinus Torvalds 0x1d, 0x009, /* Out Mux2 */
19621da177e4SLinus Torvalds
19631da177e4SLinus Torvalds 0x18, 0x000, /* All power-up */
19641da177e4SLinus Torvalds
19651da177e4SLinus Torvalds 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
19661da177e4SLinus Torvalds 0x17, 0x006, /* 128fs, slave mode */
19671da177e4SLinus Torvalds
19681da177e4SLinus Torvalds 0x00, 0, /* DAC1 analog mute */
19691da177e4SLinus Torvalds 0x01, 0, /* DAC2 analog mute */
19701da177e4SLinus Torvalds 0x02, 0, /* DAC3 analog mute */
19711da177e4SLinus Torvalds 0x03, 0, /* DAC4 analog mute */
19721da177e4SLinus Torvalds 0x04, 0, /* DAC5 analog mute */
19731da177e4SLinus Torvalds 0x05, 0, /* DAC6 analog mute */
19741da177e4SLinus Torvalds 0x06, 0, /* DAC7 analog mute */
19751da177e4SLinus Torvalds 0x07, 0, /* DAC8 analog mute */
19761da177e4SLinus Torvalds 0x08, 0x100, /* master analog mute */
19771da177e4SLinus Torvalds
19781da177e4SLinus Torvalds 0x09, 0x7f, /* DAC1 digital full */
19791da177e4SLinus Torvalds 0x0a, 0x7f, /* DAC2 digital full */
19801da177e4SLinus Torvalds 0x0b, 0x7f, /* DAC3 digital full */
19811da177e4SLinus Torvalds 0x0c, 0x7f, /* DAC4 digital full */
19821da177e4SLinus Torvalds 0x0d, 0x7f, /* DAC5 digital full */
19831da177e4SLinus Torvalds 0x0e, 0x7f, /* DAC6 digital full */
19841da177e4SLinus Torvalds 0x0f, 0x7f, /* DAC7 digital full */
19851da177e4SLinus Torvalds 0x10, 0x7f, /* DAC8 digital full */
19861da177e4SLinus Torvalds 0x11, 0x1FF, /* master digital full */
19871da177e4SLinus Torvalds
19881da177e4SLinus Torvalds 0x12, 0x000, /* phase normal */
19891da177e4SLinus Torvalds 0x13, 0x090, /* unmute DAC L/R */
19901da177e4SLinus Torvalds 0x14, 0x000, /* all unmute */
19911da177e4SLinus Torvalds 0x15, 0x000, /* no deemphasis, no ZFLG */
19921da177e4SLinus Torvalds
19931da177e4SLinus Torvalds 0x19, 0x000, /* -12dB ADC/L */
19941da177e4SLinus Torvalds 0x1a, 0x000, /* -12dB ADC/R */
19951da177e4SLinus Torvalds (unsigned short)-1
19961da177e4SLinus Torvalds
19971da177e4SLinus Torvalds };
199832b47da0STakashi Iwai static const unsigned short cs_inits[] = {
19991da177e4SLinus Torvalds 0x0441, /* RUN */
20001da177e4SLinus Torvalds 0x0180, /* no mute, OMCK output on RMCK pin */
20011da177e4SLinus Torvalds 0x0201, /* S/PDIF source on RXP1 */
20021da177e4SLinus Torvalds 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
20031da177e4SLinus Torvalds (unsigned short)-1
20041da177e4SLinus Torvalds };
20051da177e4SLinus Torvalds unsigned int tmp;
200632b47da0STakashi Iwai const unsigned short *p;
2007ae761481SBernhard Urban int err;
2008ae761481SBernhard Urban struct aureon_spec *spec = ice->spec;
20091da177e4SLinus Torvalds
20101ce211a9SAlexander Beregalov err = aureon_ac97_init(ice);
20111ce211a9SAlexander Beregalov if (err != 0)
20121da177e4SLinus Torvalds return err;
20131da177e4SLinus Torvalds
20141da177e4SLinus Torvalds snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
20151da177e4SLinus Torvalds
20161da177e4SLinus Torvalds /* reset the wm codec as the SPI mode */
20171da177e4SLinus Torvalds snd_ice1712_save_gpio_status(ice);
20181da177e4SLinus Torvalds snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
20191da177e4SLinus Torvalds
20201da177e4SLinus Torvalds tmp = snd_ice1712_gpio_read(ice);
20211da177e4SLinus Torvalds tmp &= ~AUREON_WM_RESET;
20221da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
20231da177e4SLinus Torvalds udelay(1);
20241da177e4SLinus Torvalds tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
20251da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
20261da177e4SLinus Torvalds udelay(1);
20271da177e4SLinus Torvalds tmp |= AUREON_WM_RESET;
20281da177e4SLinus Torvalds snd_ice1712_gpio_write(ice, tmp);
20291da177e4SLinus Torvalds udelay(1);
20301da177e4SLinus Torvalds
20311da177e4SLinus Torvalds /* initialize WM8770 codec */
203245fe722bSTakashi Iwai if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2033cdf88efaSToshimune Konno ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2034cdf88efaSToshimune Konno ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
20351da177e4SLinus Torvalds p = wm_inits_prodigy;
20361da177e4SLinus Torvalds else
20371da177e4SLinus Torvalds p = wm_inits_aureon;
20381da177e4SLinus Torvalds for (; *p != (unsigned short)-1; p += 2)
20391da177e4SLinus Torvalds wm_put(ice, p[0], p[1]);
20401da177e4SLinus Torvalds
20411da177e4SLinus Torvalds /* initialize CS8415A codec */
2042cdf88efaSToshimune Konno if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2043cdf88efaSToshimune Konno ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
20441da177e4SLinus Torvalds for (p = cs_inits; *p != (unsigned short)-1; p++)
20451da177e4SLinus Torvalds aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
20467cda8ba9STakashi Iwai spec->cs8415_mux = 1;
20471da177e4SLinus Torvalds
20481da177e4SLinus Torvalds aureon_set_headphone_amp(ice, 1);
204945fe722bSTakashi Iwai }
20501da177e4SLinus Torvalds
20511da177e4SLinus Torvalds snd_ice1712_restore_gpio_status(ice);
20521da177e4SLinus Torvalds
2053af9b70acSMaximilian Rehkopf /* initialize PCA9554 pin directions & set default input */
2054af9b70acSMaximilian Rehkopf aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2055af9b70acSMaximilian Rehkopf aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2056ae761481SBernhard Urban return 0;
2057ae761481SBernhard Urban }
2058ae761481SBernhard Urban
2059ae761481SBernhard Urban /*
2060ae761481SBernhard Urban * suspend/resume
2061ae761481SBernhard Urban */
2062c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
aureon_resume(struct snd_ice1712 * ice)2063ae761481SBernhard Urban static int aureon_resume(struct snd_ice1712 *ice)
2064ae761481SBernhard Urban {
2065ae761481SBernhard Urban struct aureon_spec *spec = ice->spec;
2066ae761481SBernhard Urban int err, i;
2067ae761481SBernhard Urban
2068ae761481SBernhard Urban err = aureon_reset(ice);
2069ae761481SBernhard Urban if (err != 0)
2070ae761481SBernhard Urban return err;
2071ae761481SBernhard Urban
2072ae761481SBernhard Urban /* workaround for poking volume with alsamixer after resume:
2073ae761481SBernhard Urban * just set stored volume again */
2074ae761481SBernhard Urban for (i = 0; i < ice->num_total_dacs; i++)
2075ae761481SBernhard Urban wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2076ae761481SBernhard Urban return 0;
2077ae761481SBernhard Urban }
2078ae761481SBernhard Urban #endif
2079ae761481SBernhard Urban
2080ae761481SBernhard Urban /*
2081ae761481SBernhard Urban * initialize the chip
2082ae761481SBernhard Urban */
aureon_init(struct snd_ice1712 * ice)2083e23e7a14SBill Pemberton static int aureon_init(struct snd_ice1712 *ice)
2084ae761481SBernhard Urban {
2085ae761481SBernhard Urban struct aureon_spec *spec;
2086ae761481SBernhard Urban int i, err;
2087ae761481SBernhard Urban
2088ae761481SBernhard Urban spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2089ae761481SBernhard Urban if (!spec)
2090ae761481SBernhard Urban return -ENOMEM;
2091ae761481SBernhard Urban ice->spec = spec;
2092ae761481SBernhard Urban
2093ae761481SBernhard Urban if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2094ae761481SBernhard Urban ice->num_total_dacs = 6;
2095ae761481SBernhard Urban ice->num_total_adcs = 2;
2096ae761481SBernhard Urban } else {
2097ae761481SBernhard Urban /* aureon 7.1 and prodigy 7.1 */
2098ae761481SBernhard Urban ice->num_total_dacs = 8;
2099ae761481SBernhard Urban ice->num_total_adcs = 2;
2100ae761481SBernhard Urban }
2101ae761481SBernhard Urban
210225985edcSLucas De Marchi /* to remember the register values of CS8415 */
2103ae761481SBernhard Urban ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2104ae761481SBernhard Urban if (!ice->akm)
2105ae761481SBernhard Urban return -ENOMEM;
2106ae761481SBernhard Urban ice->akm_codecs = 1;
2107ae761481SBernhard Urban
2108ae761481SBernhard Urban err = aureon_reset(ice);
2109ae761481SBernhard Urban if (err != 0)
2110ae761481SBernhard Urban return err;
2111af9b70acSMaximilian Rehkopf
21127cda8ba9STakashi Iwai spec->master[0] = WM_VOL_MUTE;
21137cda8ba9STakashi Iwai spec->master[1] = WM_VOL_MUTE;
21141da177e4SLinus Torvalds for (i = 0; i < ice->num_total_dacs; i++) {
21157cda8ba9STakashi Iwai spec->vol[i] = WM_VOL_MUTE;
21167cda8ba9STakashi Iwai wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
21171da177e4SLinus Torvalds }
21181da177e4SLinus Torvalds
2119c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
2120ae761481SBernhard Urban ice->pm_resume = aureon_resume;
2121ae761481SBernhard Urban ice->pm_suspend_enabled = 1;
2122ae761481SBernhard Urban #endif
2123ae761481SBernhard Urban
21241da177e4SLinus Torvalds return 0;
21251da177e4SLinus Torvalds }
21261da177e4SLinus Torvalds
21271da177e4SLinus Torvalds
21281da177e4SLinus Torvalds /*
21291da177e4SLinus Torvalds * Aureon boards don't provide the EEPROM data except for the vendor IDs.
21301da177e4SLinus Torvalds * hence the driver needs to sets up it properly.
21311da177e4SLinus Torvalds */
21321da177e4SLinus Torvalds
2133f16a4e96STakashi Iwai static const unsigned char aureon51_eeprom[] = {
2134189bc171STakashi Iwai [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2135189bc171STakashi Iwai [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2136189bc171STakashi Iwai [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2137189bc171STakashi Iwai [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2138189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR] = 0xff,
2139189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR1] = 0xff,
2140189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR2] = 0x5f,
2141189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK] = 0x00,
2142189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK1] = 0x00,
2143189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK2] = 0x00,
2144189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE] = 0x00,
2145189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE1] = 0x00,
2146189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE2] = 0x00,
21471da177e4SLinus Torvalds };
21481da177e4SLinus Torvalds
2149f16a4e96STakashi Iwai static const unsigned char aureon71_eeprom[] = {
2150189bc171STakashi Iwai [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2151189bc171STakashi Iwai [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2152189bc171STakashi Iwai [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2153189bc171STakashi Iwai [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2154189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR] = 0xff,
2155189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR1] = 0xff,
2156189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR2] = 0x5f,
2157189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK] = 0x00,
2158189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK1] = 0x00,
2159189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK2] = 0x00,
2160189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE] = 0x00,
2161189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE1] = 0x00,
2162189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE2] = 0x00,
21631da177e4SLinus Torvalds };
2164189bc171STakashi Iwai #define prodigy71_eeprom aureon71_eeprom
21651da177e4SLinus Torvalds
2166f16a4e96STakashi Iwai static const unsigned char aureon71_universe_eeprom[] = {
2167c1805dddSMaximilian Rehkopf [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC,
2168c1805dddSMaximilian Rehkopf * 4DACs
2169c1805dddSMaximilian Rehkopf */
2170c1805dddSMaximilian Rehkopf [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2171c1805dddSMaximilian Rehkopf [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2172c1805dddSMaximilian Rehkopf [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2173c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_DIR] = 0xff,
2174c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_DIR1] = 0xff,
2175c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_DIR2] = 0x5f,
2176c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_MASK] = 0x00,
2177c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_MASK1] = 0x00,
2178c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_MASK2] = 0x00,
2179c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_STATE] = 0x00,
2180c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_STATE1] = 0x00,
2181c1805dddSMaximilian Rehkopf [ICE_EEP2_GPIO_STATE2] = 0x00,
2182c1805dddSMaximilian Rehkopf };
2183c1805dddSMaximilian Rehkopf
2184f16a4e96STakashi Iwai static const unsigned char prodigy71lt_eeprom[] = {
2185189bc171STakashi Iwai [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2186189bc171STakashi Iwai [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2187189bc171STakashi Iwai [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2188189bc171STakashi Iwai [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2189189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR] = 0xff,
2190189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR1] = 0xff,
2191189bc171STakashi Iwai [ICE_EEP2_GPIO_DIR2] = 0x5f,
2192189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK] = 0x00,
2193189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK1] = 0x00,
2194189bc171STakashi Iwai [ICE_EEP2_GPIO_MASK2] = 0x00,
2195189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE] = 0x00,
2196189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE1] = 0x00,
2197189bc171STakashi Iwai [ICE_EEP2_GPIO_STATE2] = 0x00,
219845fe722bSTakashi Iwai };
2199189bc171STakashi Iwai #define prodigy71xt_eeprom prodigy71lt_eeprom
220045fe722bSTakashi Iwai
22011da177e4SLinus Torvalds /* entry point */
2202e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
22031da177e4SLinus Torvalds {
22041da177e4SLinus Torvalds .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
22051da177e4SLinus Torvalds .name = "Terratec Aureon 5.1-Sky",
22061da177e4SLinus Torvalds .model = "aureon51",
22071da177e4SLinus Torvalds .chip_init = aureon_init,
22081da177e4SLinus Torvalds .build_controls = aureon_add_controls,
22091da177e4SLinus Torvalds .eeprom_size = sizeof(aureon51_eeprom),
22101da177e4SLinus Torvalds .eeprom_data = aureon51_eeprom,
22111da177e4SLinus Torvalds .driver = "Aureon51",
22121da177e4SLinus Torvalds },
22131da177e4SLinus Torvalds {
22141da177e4SLinus Torvalds .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
22151da177e4SLinus Torvalds .name = "Terratec Aureon 7.1-Space",
22161da177e4SLinus Torvalds .model = "aureon71",
22171da177e4SLinus Torvalds .chip_init = aureon_init,
22181da177e4SLinus Torvalds .build_controls = aureon_add_controls,
22191da177e4SLinus Torvalds .eeprom_size = sizeof(aureon71_eeprom),
22201da177e4SLinus Torvalds .eeprom_data = aureon71_eeprom,
22211da177e4SLinus Torvalds .driver = "Aureon71",
22221da177e4SLinus Torvalds },
22231da177e4SLinus Torvalds {
22241da177e4SLinus Torvalds .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
22251da177e4SLinus Torvalds .name = "Terratec Aureon 7.1-Universe",
22261da177e4SLinus Torvalds .model = "universe",
22271da177e4SLinus Torvalds .chip_init = aureon_init,
22281da177e4SLinus Torvalds .build_controls = aureon_add_controls,
2229c1805dddSMaximilian Rehkopf .eeprom_size = sizeof(aureon71_universe_eeprom),
2230c1805dddSMaximilian Rehkopf .eeprom_data = aureon71_universe_eeprom,
22319f37c5b3STakashi Iwai .driver = "Aureon71Univ", /* keep in 15 letters */
22321da177e4SLinus Torvalds },
22331da177e4SLinus Torvalds {
22341da177e4SLinus Torvalds .subvendor = VT1724_SUBDEVICE_PRODIGY71,
22351da177e4SLinus Torvalds .name = "Audiotrak Prodigy 7.1",
22361da177e4SLinus Torvalds .model = "prodigy71",
22371da177e4SLinus Torvalds .chip_init = aureon_init,
22381da177e4SLinus Torvalds .build_controls = aureon_add_controls,
22391da177e4SLinus Torvalds .eeprom_size = sizeof(prodigy71_eeprom),
22401da177e4SLinus Torvalds .eeprom_data = prodigy71_eeprom,
22411da177e4SLinus Torvalds .driver = "Prodigy71", /* should be identical with Aureon71 */
22421da177e4SLinus Torvalds },
224345fe722bSTakashi Iwai {
224445fe722bSTakashi Iwai .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
224545fe722bSTakashi Iwai .name = "Audiotrak Prodigy 7.1 LT",
224645fe722bSTakashi Iwai .model = "prodigy71lt",
224745fe722bSTakashi Iwai .chip_init = aureon_init,
224845fe722bSTakashi Iwai .build_controls = aureon_add_controls,
224945fe722bSTakashi Iwai .eeprom_size = sizeof(prodigy71lt_eeprom),
225045fe722bSTakashi Iwai .eeprom_data = prodigy71lt_eeprom,
225145fe722bSTakashi Iwai .driver = "Prodigy71LT",
225245fe722bSTakashi Iwai },
2253cdf88efaSToshimune Konno {
2254cdf88efaSToshimune Konno .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2255cdf88efaSToshimune Konno .name = "Audiotrak Prodigy 7.1 XT",
2256cdf88efaSToshimune Konno .model = "prodigy71xt",
2257cdf88efaSToshimune Konno .chip_init = aureon_init,
2258cdf88efaSToshimune Konno .build_controls = aureon_add_controls,
2259cdf88efaSToshimune Konno .eeprom_size = sizeof(prodigy71xt_eeprom),
2260cdf88efaSToshimune Konno .eeprom_data = prodigy71xt_eeprom,
2261cdf88efaSToshimune Konno .driver = "Prodigy71LT",
2262cdf88efaSToshimune Konno },
22631da177e4SLinus Torvalds { } /* terminator */
22641da177e4SLinus Torvalds };
2265