Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
0004  *
0005  *   Lowlevel functions for Terratec Aureon cards
0006  *
0007  *  Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
0008  *
0009  * NOTES:
0010  *
0011  * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
0012  *   both wm and akm codecs are pretty similar, so we can integrate
0013  *   both controls in the future, once if wm codecs are reused in
0014  *   many boards.
0015  *
0016  * - DAC digital volumes are not implemented in the mixer.
0017  *   if they show better response than DAC analog volumes, we can use them
0018  *   instead.
0019  *
0020  *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
0021  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
0022  *
0023  *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
0024  *       added 64x/128x oversampling switch (should be 64x only for 96khz)
0025  *       fixed some recording labels (still need to check the rest)
0026  *       recording is working probably thanks to correct wm8770 initialization
0027  *
0028  *   version 0.5: Initial release:
0029  *           working: analog output, mixer, headphone amplifier switch
0030  *       not working: prety much everything else, at least i could verify that
0031  *                    we have no digital output, no capture, pretty bad clicks and poops
0032  *                    on mixer switch and other coll stuff.
0033  */
0034 
0035 #include <linux/delay.h>
0036 #include <linux/interrupt.h>
0037 #include <linux/init.h>
0038 #include <linux/slab.h>
0039 #include <linux/mutex.h>
0040 
0041 #include <sound/core.h>
0042 
0043 #include "ice1712.h"
0044 #include "envy24ht.h"
0045 #include "aureon.h"
0046 #include <sound/tlv.h>
0047 
0048 /* AC97 register cache for Aureon */
0049 struct aureon_spec {
0050     unsigned short stac9744[64];
0051     unsigned int cs8415_mux;
0052     unsigned short master[2];
0053     unsigned short vol[8];
0054     unsigned char pca9554_out;
0055 };
0056 
0057 /* WM8770 registers */
0058 #define WM_DAC_ATTEN        0x00    /* DAC1-8 analog attenuation */
0059 #define WM_DAC_MASTER_ATTEN 0x08    /* DAC master analog attenuation */
0060 #define WM_DAC_DIG_ATTEN    0x09    /* DAC1-8 digital attenuation */
0061 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
0062 #define WM_PHASE_SWAP       0x12    /* DAC phase */
0063 #define WM_DAC_CTRL1        0x13    /* DAC control bits */
0064 #define WM_MUTE         0x14    /* mute controls */
0065 #define WM_DAC_CTRL2        0x15    /* de-emphasis and zefo-flag */
0066 #define WM_INT_CTRL     0x16    /* interface control */
0067 #define WM_MASTER       0x17    /* master clock and mode */
0068 #define WM_POWERDOWN        0x18    /* power-down controls */
0069 #define WM_ADC_GAIN     0x19    /* ADC gain L(19)/R(1a) */
0070 #define WM_ADC_MUX      0x1b    /* input MUX */
0071 #define WM_OUT_MUX1     0x1c    /* output MUX */
0072 #define WM_OUT_MUX2     0x1e    /* output MUX */
0073 #define WM_RESET        0x1f    /* software reset */
0074 
0075 /* CS8415A registers */
0076 #define CS8415_CTRL1    0x01
0077 #define CS8415_CTRL2    0x02
0078 #define CS8415_QSUB     0x14
0079 #define CS8415_RATIO    0x1E
0080 #define CS8415_C_BUFFER 0x20
0081 #define CS8415_ID       0x7F
0082 
0083 /* PCA9554 registers */
0084 #define PCA9554_DEV     0x40            /* I2C device address */
0085 #define PCA9554_IN      0x00            /* input port */
0086 #define PCA9554_OUT     0x01            /* output port */
0087 #define PCA9554_INVERT  0x02            /* input invert */
0088 #define PCA9554_DIR     0x03            /* port directions */
0089 
0090 /*
0091  * Aureon Universe additional controls using PCA9554
0092  */
0093 
0094 /*
0095  * Send data to pca9554
0096  */
0097 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
0098                  unsigned char data)
0099 {
0100     unsigned int tmp;
0101     int i, j;
0102     unsigned char dev = PCA9554_DEV;  /* ID 0100000, write */
0103     unsigned char val = 0;
0104 
0105     tmp = snd_ice1712_gpio_read(ice);
0106 
0107     snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
0108                      AUREON_WM_RW|AUREON_WM_CS|
0109                      AUREON_CS8415_CS));
0110     tmp |= AUREON_WM_RW;
0111     tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
0112 
0113     tmp &= ~AUREON_SPI_MOSI;
0114     tmp &= ~AUREON_SPI_CLK;
0115     snd_ice1712_gpio_write(ice, tmp);
0116     udelay(50);
0117 
0118     /*
0119      * send i2c stop condition and start condition
0120      * to obtain sane state
0121      */
0122     tmp |= AUREON_SPI_CLK;
0123     snd_ice1712_gpio_write(ice, tmp);
0124     udelay(50);
0125     tmp |= AUREON_SPI_MOSI;
0126     snd_ice1712_gpio_write(ice, tmp);
0127     udelay(100);
0128     tmp &= ~AUREON_SPI_MOSI;
0129     snd_ice1712_gpio_write(ice, tmp);
0130     udelay(50);
0131     tmp &= ~AUREON_SPI_CLK;
0132     snd_ice1712_gpio_write(ice, tmp);
0133     udelay(100);
0134     /*
0135      * send device address, command and value,
0136      * skipping ack cycles in between
0137      */
0138     for (j = 0; j < 3; j++) {
0139         switch (j) {
0140         case 0:
0141             val = dev;
0142             break;
0143         case 1:
0144             val = reg;
0145             break;
0146         case 2:
0147             val = data;
0148             break;
0149         }
0150         for (i = 7; i >= 0; i--) {
0151             tmp &= ~AUREON_SPI_CLK;
0152             snd_ice1712_gpio_write(ice, tmp);
0153             udelay(40);
0154             if (val & (1 << i))
0155                 tmp |= AUREON_SPI_MOSI;
0156             else
0157                 tmp &= ~AUREON_SPI_MOSI;
0158             snd_ice1712_gpio_write(ice, tmp);
0159             udelay(40);
0160             tmp |= AUREON_SPI_CLK;
0161             snd_ice1712_gpio_write(ice, tmp);
0162             udelay(40);
0163         }
0164         tmp &= ~AUREON_SPI_CLK;
0165         snd_ice1712_gpio_write(ice, tmp);
0166         udelay(40);
0167         tmp |= AUREON_SPI_CLK;
0168         snd_ice1712_gpio_write(ice, tmp);
0169         udelay(40);
0170         tmp &= ~AUREON_SPI_CLK;
0171         snd_ice1712_gpio_write(ice, tmp);
0172         udelay(40);
0173     }
0174     tmp &= ~AUREON_SPI_CLK;
0175     snd_ice1712_gpio_write(ice, tmp);
0176     udelay(40);
0177     tmp &= ~AUREON_SPI_MOSI;
0178     snd_ice1712_gpio_write(ice, tmp);
0179     udelay(40);
0180     tmp |= AUREON_SPI_CLK;
0181     snd_ice1712_gpio_write(ice, tmp);
0182     udelay(50);
0183     tmp |= AUREON_SPI_MOSI;
0184     snd_ice1712_gpio_write(ice, tmp);
0185     udelay(100);
0186 }
0187 
0188 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
0189                       struct snd_ctl_elem_info *uinfo)
0190 {
0191     static const char * const texts[3] =
0192         {"Internal Aux", "Wavetable", "Rear Line-In"};
0193 
0194     return snd_ctl_enum_info(uinfo, 1, 3, texts);
0195 }
0196 
0197 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
0198                      struct snd_ctl_elem_value *ucontrol)
0199 {
0200     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0201     struct aureon_spec *spec = ice->spec;
0202     ucontrol->value.enumerated.item[0] = spec->pca9554_out;
0203     return 0;
0204 }
0205 
0206 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
0207                      struct snd_ctl_elem_value *ucontrol)
0208 {
0209     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0210     struct aureon_spec *spec = ice->spec;
0211     unsigned char oval, nval;
0212     int change;
0213 
0214     nval = ucontrol->value.enumerated.item[0];
0215     if (nval >= 3)
0216         return -EINVAL;
0217     snd_ice1712_save_gpio_status(ice);
0218     oval = spec->pca9554_out;
0219     change = (oval != nval);
0220     if (change) {
0221         aureon_pca9554_write(ice, PCA9554_OUT, nval);
0222         spec->pca9554_out = nval;
0223     }
0224     snd_ice1712_restore_gpio_status(ice);
0225     return change;
0226 }
0227 
0228 
0229 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
0230                   unsigned short val)
0231 {
0232     struct aureon_spec *spec = ice->spec;
0233     unsigned int tmp;
0234 
0235     /* Send address to XILINX chip */
0236     tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
0237     snd_ice1712_gpio_write(ice, tmp);
0238     udelay(10);
0239     tmp |= AUREON_AC97_ADDR;
0240     snd_ice1712_gpio_write(ice, tmp);
0241     udelay(10);
0242     tmp &= ~AUREON_AC97_ADDR;
0243     snd_ice1712_gpio_write(ice, tmp);
0244     udelay(10);
0245 
0246     /* Send low-order byte to XILINX chip */
0247     tmp &= ~AUREON_AC97_DATA_MASK;
0248     tmp |= val & AUREON_AC97_DATA_MASK;
0249     snd_ice1712_gpio_write(ice, tmp);
0250     udelay(10);
0251     tmp |= AUREON_AC97_DATA_LOW;
0252     snd_ice1712_gpio_write(ice, tmp);
0253     udelay(10);
0254     tmp &= ~AUREON_AC97_DATA_LOW;
0255     snd_ice1712_gpio_write(ice, tmp);
0256     udelay(10);
0257 
0258     /* Send high-order byte to XILINX chip */
0259     tmp &= ~AUREON_AC97_DATA_MASK;
0260     tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
0261 
0262     snd_ice1712_gpio_write(ice, tmp);
0263     udelay(10);
0264     tmp |= AUREON_AC97_DATA_HIGH;
0265     snd_ice1712_gpio_write(ice, tmp);
0266     udelay(10);
0267     tmp &= ~AUREON_AC97_DATA_HIGH;
0268     snd_ice1712_gpio_write(ice, tmp);
0269     udelay(10);
0270 
0271     /* Instruct XILINX chip to parse the data to the STAC9744 chip */
0272     tmp |= AUREON_AC97_COMMIT;
0273     snd_ice1712_gpio_write(ice, tmp);
0274     udelay(10);
0275     tmp &= ~AUREON_AC97_COMMIT;
0276     snd_ice1712_gpio_write(ice, tmp);
0277     udelay(10);
0278 
0279     /* Store the data in out private buffer */
0280     spec->stac9744[(reg & 0x7F) >> 1] = val;
0281 }
0282 
0283 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
0284 {
0285     struct aureon_spec *spec = ice->spec;
0286     return spec->stac9744[(reg & 0x7F) >> 1];
0287 }
0288 
0289 /*
0290  * Initialize STAC9744 chip
0291  */
0292 static int aureon_ac97_init(struct snd_ice1712 *ice)
0293 {
0294     struct aureon_spec *spec = ice->spec;
0295     int i;
0296     static const unsigned short ac97_defaults[] = {
0297         0x00, 0x9640,
0298         0x02, 0x8000,
0299         0x04, 0x8000,
0300         0x06, 0x8000,
0301         0x0C, 0x8008,
0302         0x0E, 0x8008,
0303         0x10, 0x8808,
0304         0x12, 0x8808,
0305         0x14, 0x8808,
0306         0x16, 0x8808,
0307         0x18, 0x8808,
0308         0x1C, 0x8000,
0309         0x26, 0x000F,
0310         0x28, 0x0201,
0311         0x2C, 0xBB80,
0312         0x32, 0xBB80,
0313         0x7C, 0x8384,
0314         0x7E, 0x7644,
0315         (unsigned short)-1
0316     };
0317     unsigned int tmp;
0318 
0319     /* Cold reset */
0320     tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
0321     snd_ice1712_gpio_write(ice, tmp);
0322     udelay(3);
0323 
0324     tmp &= ~AUREON_AC97_RESET;
0325     snd_ice1712_gpio_write(ice, tmp);
0326     udelay(3);
0327 
0328     tmp |= AUREON_AC97_RESET;
0329     snd_ice1712_gpio_write(ice, tmp);
0330     udelay(3);
0331 
0332     memset(&spec->stac9744, 0, sizeof(spec->stac9744));
0333     for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2)
0334         spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
0335 
0336     /* Unmute AC'97 master volume permanently - muting is done by WM8770 */
0337     aureon_ac97_write(ice, AC97_MASTER, 0x0000);
0338 
0339     return 0;
0340 }
0341 
0342 #define AUREON_AC97_STEREO  0x80
0343 
0344 /*
0345  * AC'97 volume controls
0346  */
0347 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0348 {
0349     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0350     uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
0351     uinfo->value.integer.min = 0;
0352     uinfo->value.integer.max = 31;
0353     return 0;
0354 }
0355 
0356 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0357 {
0358     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0359     unsigned short vol;
0360 
0361     mutex_lock(&ice->gpio_mutex);
0362 
0363     vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0364     ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
0365     if (kcontrol->private_value & AUREON_AC97_STEREO)
0366         ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
0367 
0368     mutex_unlock(&ice->gpio_mutex);
0369     return 0;
0370 }
0371 
0372 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0373 {
0374     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0375     unsigned short ovol, nvol;
0376     int change;
0377 
0378     snd_ice1712_save_gpio_status(ice);
0379 
0380     ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0381     nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
0382     if (kcontrol->private_value & AUREON_AC97_STEREO)
0383         nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
0384     nvol |= ovol & ~0x1F1F;
0385 
0386     change = (ovol != nvol);
0387     if (change)
0388         aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
0389 
0390     snd_ice1712_restore_gpio_status(ice);
0391 
0392     return change;
0393 }
0394 
0395 /*
0396  * AC'97 mute controls
0397  */
0398 #define aureon_ac97_mute_info   snd_ctl_boolean_mono_info
0399 
0400 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0401 {
0402     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0403 
0404     mutex_lock(&ice->gpio_mutex);
0405 
0406     ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
0407             kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
0408 
0409     mutex_unlock(&ice->gpio_mutex);
0410     return 0;
0411 }
0412 
0413 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0414 {
0415     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0416     unsigned short ovol, nvol;
0417     int change;
0418 
0419     snd_ice1712_save_gpio_status(ice);
0420 
0421     ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0422     nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
0423 
0424     change = (ovol != nvol);
0425     if (change)
0426         aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
0427 
0428     snd_ice1712_restore_gpio_status(ice);
0429 
0430     return change;
0431 }
0432 
0433 /*
0434  * AC'97 mute controls
0435  */
0436 #define aureon_ac97_micboost_info   snd_ctl_boolean_mono_info
0437 
0438 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0439 {
0440     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0441 
0442     mutex_lock(&ice->gpio_mutex);
0443 
0444     ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
0445 
0446     mutex_unlock(&ice->gpio_mutex);
0447     return 0;
0448 }
0449 
0450 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0451 {
0452     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0453     unsigned short ovol, nvol;
0454     int change;
0455 
0456     snd_ice1712_save_gpio_status(ice);
0457 
0458     ovol = aureon_ac97_read(ice, AC97_MIC);
0459     nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
0460 
0461     change = (ovol != nvol);
0462     if (change)
0463         aureon_ac97_write(ice, AC97_MIC, nvol);
0464 
0465     snd_ice1712_restore_gpio_status(ice);
0466 
0467     return change;
0468 }
0469 
0470 /*
0471  * write data in the SPI mode
0472  */
0473 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
0474 {
0475     unsigned int tmp;
0476     int i;
0477     unsigned int mosi, clk;
0478 
0479     tmp = snd_ice1712_gpio_read(ice);
0480 
0481     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
0482         ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
0483         snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
0484         mosi = PRODIGY_SPI_MOSI;
0485         clk = PRODIGY_SPI_CLK;
0486     } else {
0487         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
0488                          AUREON_WM_CS|AUREON_CS8415_CS));
0489         mosi = AUREON_SPI_MOSI;
0490         clk = AUREON_SPI_CLK;
0491 
0492         tmp |= AUREON_WM_RW;
0493     }
0494 
0495     tmp &= ~cs;
0496     snd_ice1712_gpio_write(ice, tmp);
0497     udelay(1);
0498 
0499     for (i = bits - 1; i >= 0; i--) {
0500         tmp &= ~clk;
0501         snd_ice1712_gpio_write(ice, tmp);
0502         udelay(1);
0503         if (data & (1 << i))
0504             tmp |= mosi;
0505         else
0506             tmp &= ~mosi;
0507         snd_ice1712_gpio_write(ice, tmp);
0508         udelay(1);
0509         tmp |= clk;
0510         snd_ice1712_gpio_write(ice, tmp);
0511         udelay(1);
0512     }
0513 
0514     tmp &= ~clk;
0515     tmp |= cs;
0516     snd_ice1712_gpio_write(ice, tmp);
0517     udelay(1);
0518     tmp |= clk;
0519     snd_ice1712_gpio_write(ice, tmp);
0520     udelay(1);
0521 }
0522 
0523 /*
0524  * Read data in SPI mode
0525  */
0526 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
0527         unsigned int data, int bits, unsigned char *buffer, int size)
0528 {
0529     int i, j;
0530     unsigned int tmp;
0531 
0532     tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
0533     snd_ice1712_gpio_write(ice, tmp);
0534     tmp &= ~cs;
0535     snd_ice1712_gpio_write(ice, tmp);
0536     udelay(1);
0537 
0538     for (i = bits-1; i >= 0; i--) {
0539         if (data & (1 << i))
0540             tmp |= AUREON_SPI_MOSI;
0541         else
0542             tmp &= ~AUREON_SPI_MOSI;
0543         snd_ice1712_gpio_write(ice, tmp);
0544         udelay(1);
0545 
0546         tmp |= AUREON_SPI_CLK;
0547         snd_ice1712_gpio_write(ice, tmp);
0548         udelay(1);
0549 
0550         tmp &= ~AUREON_SPI_CLK;
0551         snd_ice1712_gpio_write(ice, tmp);
0552         udelay(1);
0553     }
0554 
0555     for (j = 0; j < size; j++) {
0556         unsigned char outdata = 0;
0557         for (i = 7; i >= 0; i--) {
0558             tmp = snd_ice1712_gpio_read(ice);
0559             outdata <<= 1;
0560             outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
0561             udelay(1);
0562 
0563             tmp |= AUREON_SPI_CLK;
0564             snd_ice1712_gpio_write(ice, tmp);
0565             udelay(1);
0566 
0567             tmp &= ~AUREON_SPI_CLK;
0568             snd_ice1712_gpio_write(ice, tmp);
0569             udelay(1);
0570         }
0571         buffer[j] = outdata;
0572     }
0573 
0574     tmp |= cs;
0575     snd_ice1712_gpio_write(ice, tmp);
0576 }
0577 
0578 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
0579 {
0580     unsigned char val;
0581     aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
0582     aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
0583     return val;
0584 }
0585 
0586 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
0587                 unsigned char *buffer, int size)
0588 {
0589     aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
0590     aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
0591 }
0592 
0593 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
0594                         unsigned char val)
0595 {
0596     aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
0597 }
0598 
0599 /*
0600  * get the current register value of WM codec
0601  */
0602 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
0603 {
0604     reg <<= 1;
0605     return ((unsigned short)ice->akm[0].images[reg] << 8) |
0606         ice->akm[0].images[reg + 1];
0607 }
0608 
0609 /*
0610  * set the register value of WM codec
0611  */
0612 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
0613 {
0614     aureon_spi_write(ice,
0615              ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
0616                ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
0617              PRODIGY_WM_CS : AUREON_WM_CS),
0618             (reg << 9) | (val & 0x1ff), 16);
0619 }
0620 
0621 /*
0622  * set the register value of WM codec and remember it
0623  */
0624 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
0625 {
0626     wm_put_nocache(ice, reg, val);
0627     reg <<= 1;
0628     ice->akm[0].images[reg] = val >> 8;
0629     ice->akm[0].images[reg + 1] = val;
0630 }
0631 
0632 /*
0633  */
0634 #define aureon_mono_bool_info       snd_ctl_boolean_mono_info
0635 
0636 /*
0637  * AC'97 master playback mute controls (Mute on WM8770 chip)
0638  */
0639 #define aureon_ac97_mmute_info      snd_ctl_boolean_mono_info
0640 
0641 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0642 {
0643     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0644 
0645     mutex_lock(&ice->gpio_mutex);
0646 
0647     ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
0648 
0649     mutex_unlock(&ice->gpio_mutex);
0650     return 0;
0651 }
0652 
0653 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0654 {
0655     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0656     unsigned short ovol, nvol;
0657     int change;
0658 
0659     snd_ice1712_save_gpio_status(ice);
0660 
0661     ovol = wm_get(ice, WM_OUT_MUX1);
0662     nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
0663     change = (ovol != nvol);
0664     if (change)
0665         wm_put(ice, WM_OUT_MUX1, nvol);
0666 
0667     snd_ice1712_restore_gpio_status(ice);
0668 
0669     return change;
0670 }
0671 
0672 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1);
0673 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
0674 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
0675 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
0676 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
0677 
0678 #define WM_VOL_MAX  100
0679 #define WM_VOL_CNT  101 /* 0dB .. -100dB */
0680 #define WM_VOL_MUTE 0x8000
0681 
0682 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
0683 {
0684     unsigned char nvol;
0685 
0686     if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
0687         nvol = 0;
0688     } else {
0689         nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
0690                                 WM_VOL_MAX;
0691         nvol += 0x1b;
0692     }
0693 
0694     wm_put(ice, index, nvol);
0695     wm_put_nocache(ice, index, 0x180 | nvol);
0696 }
0697 
0698 /*
0699  * DAC mute control
0700  */
0701 #define wm_pcm_mute_info    snd_ctl_boolean_mono_info
0702 
0703 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0704 {
0705     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0706 
0707     mutex_lock(&ice->gpio_mutex);
0708     ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
0709     mutex_unlock(&ice->gpio_mutex);
0710     return 0;
0711 }
0712 
0713 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0714 {
0715     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0716     unsigned short nval, oval;
0717     int change;
0718 
0719     snd_ice1712_save_gpio_status(ice);
0720     oval = wm_get(ice, WM_MUTE);
0721     nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
0722     change = (oval != nval);
0723     if (change)
0724         wm_put(ice, WM_MUTE, nval);
0725     snd_ice1712_restore_gpio_status(ice);
0726 
0727     return change;
0728 }
0729 
0730 /*
0731  * Master volume attenuation mixer control
0732  */
0733 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0734 {
0735     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0736     uinfo->count = 2;
0737     uinfo->value.integer.min = 0;
0738     uinfo->value.integer.max = WM_VOL_MAX;
0739     return 0;
0740 }
0741 
0742 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0743 {
0744     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0745     struct aureon_spec *spec = ice->spec;
0746     int i;
0747     for (i = 0; i < 2; i++)
0748         ucontrol->value.integer.value[i] =
0749             spec->master[i] & ~WM_VOL_MUTE;
0750     return 0;
0751 }
0752 
0753 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0754 {
0755     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0756     struct aureon_spec *spec = ice->spec;
0757     int ch, change = 0;
0758 
0759     snd_ice1712_save_gpio_status(ice);
0760     for (ch = 0; ch < 2; ch++) {
0761         unsigned int vol = ucontrol->value.integer.value[ch];
0762         if (vol > WM_VOL_MAX)
0763             vol = WM_VOL_MAX;
0764         vol |= spec->master[ch] & WM_VOL_MUTE;
0765         if (vol != spec->master[ch]) {
0766             int dac;
0767             spec->master[ch] = vol;
0768             for (dac = 0; dac < ice->num_total_dacs; dac += 2)
0769                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
0770                        spec->vol[dac + ch],
0771                        spec->master[ch]);
0772             change = 1;
0773         }
0774     }
0775     snd_ice1712_restore_gpio_status(ice);
0776     return change;
0777 }
0778 
0779 /*
0780  * DAC volume attenuation mixer control
0781  */
0782 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0783 {
0784     int voices = kcontrol->private_value >> 8;
0785     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0786     uinfo->count = voices;
0787     uinfo->value.integer.min = 0;       /* mute (-101dB) */
0788     uinfo->value.integer.max = WM_VOL_MAX;  /* 0dB */
0789     return 0;
0790 }
0791 
0792 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0793 {
0794     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0795     struct aureon_spec *spec = ice->spec;
0796     int i, ofs, voices;
0797 
0798     voices = kcontrol->private_value >> 8;
0799     ofs = kcontrol->private_value & 0xff;
0800     for (i = 0; i < voices; i++)
0801         ucontrol->value.integer.value[i] =
0802             spec->vol[ofs+i] & ~WM_VOL_MUTE;
0803     return 0;
0804 }
0805 
0806 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0807 {
0808     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0809     struct aureon_spec *spec = ice->spec;
0810     int i, idx, ofs, voices;
0811     int change = 0;
0812 
0813     voices = kcontrol->private_value >> 8;
0814     ofs = kcontrol->private_value & 0xff;
0815     snd_ice1712_save_gpio_status(ice);
0816     for (i = 0; i < voices; i++) {
0817         unsigned int vol = ucontrol->value.integer.value[i];
0818         if (vol > WM_VOL_MAX)
0819             vol = WM_VOL_MAX;
0820         vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
0821         if (vol != spec->vol[ofs+i]) {
0822             spec->vol[ofs+i] = vol;
0823             idx  = WM_DAC_ATTEN + ofs + i;
0824             wm_set_vol(ice, idx, spec->vol[ofs + i],
0825                    spec->master[i]);
0826             change = 1;
0827         }
0828     }
0829     snd_ice1712_restore_gpio_status(ice);
0830     return change;
0831 }
0832 
0833 /*
0834  * WM8770 mute control
0835  */
0836 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0837 {
0838     uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0839     uinfo->count = kcontrol->private_value >> 8;
0840     uinfo->value.integer.min = 0;
0841     uinfo->value.integer.max = 1;
0842     return 0;
0843 }
0844 
0845 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0846 {
0847     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0848     struct aureon_spec *spec = ice->spec;
0849     int voices, ofs, i;
0850 
0851     voices = kcontrol->private_value >> 8;
0852     ofs = kcontrol->private_value & 0xFF;
0853 
0854     for (i = 0; i < voices; i++)
0855         ucontrol->value.integer.value[i] =
0856             (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
0857     return 0;
0858 }
0859 
0860 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0861 {
0862     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0863     struct aureon_spec *spec = ice->spec;
0864     int change = 0, voices, ofs, i;
0865 
0866     voices = kcontrol->private_value >> 8;
0867     ofs = kcontrol->private_value & 0xFF;
0868 
0869     snd_ice1712_save_gpio_status(ice);
0870     for (i = 0; i < voices; i++) {
0871         int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
0872         if (ucontrol->value.integer.value[i] != val) {
0873             spec->vol[ofs + i] &= ~WM_VOL_MUTE;
0874             spec->vol[ofs + i] |=
0875                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
0876             wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
0877                    spec->master[i]);
0878             change = 1;
0879         }
0880     }
0881     snd_ice1712_restore_gpio_status(ice);
0882 
0883     return change;
0884 }
0885 
0886 /*
0887  * WM8770 master mute control
0888  */
0889 #define wm_master_mute_info     snd_ctl_boolean_stereo_info
0890 
0891 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0892 {
0893     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0894     struct aureon_spec *spec = ice->spec;
0895 
0896     ucontrol->value.integer.value[0] =
0897         (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
0898     ucontrol->value.integer.value[1] =
0899         (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
0900     return 0;
0901 }
0902 
0903 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0904 {
0905     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0906     struct aureon_spec *spec = ice->spec;
0907     int change = 0, i;
0908 
0909     snd_ice1712_save_gpio_status(ice);
0910     for (i = 0; i < 2; i++) {
0911         int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
0912         if (ucontrol->value.integer.value[i] != val) {
0913             int dac;
0914             spec->master[i] &= ~WM_VOL_MUTE;
0915             spec->master[i] |=
0916                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
0917             for (dac = 0; dac < ice->num_total_dacs; dac += 2)
0918                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
0919                        spec->vol[dac + i],
0920                        spec->master[i]);
0921             change = 1;
0922         }
0923     }
0924     snd_ice1712_restore_gpio_status(ice);
0925 
0926     return change;
0927 }
0928 
0929 /* digital master volume */
0930 #define PCM_0dB 0xff
0931 #define PCM_RES 128 /* -64dB */
0932 #define PCM_MIN (PCM_0dB - PCM_RES)
0933 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0934 {
0935     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0936     uinfo->count = 1;
0937     uinfo->value.integer.min = 0;       /* mute (-64dB) */
0938     uinfo->value.integer.max = PCM_RES; /* 0dB */
0939     return 0;
0940 }
0941 
0942 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0943 {
0944     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0945     unsigned short val;
0946 
0947     mutex_lock(&ice->gpio_mutex);
0948     val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
0949     val = val > PCM_MIN ? (val - PCM_MIN) : 0;
0950     ucontrol->value.integer.value[0] = val;
0951     mutex_unlock(&ice->gpio_mutex);
0952     return 0;
0953 }
0954 
0955 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0956 {
0957     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0958     unsigned short ovol, nvol;
0959     int change = 0;
0960 
0961     nvol = ucontrol->value.integer.value[0];
0962     if (nvol > PCM_RES)
0963         return -EINVAL;
0964     snd_ice1712_save_gpio_status(ice);
0965     nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
0966     ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
0967     if (ovol != nvol) {
0968         wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
0969         wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
0970         change = 1;
0971     }
0972     snd_ice1712_restore_gpio_status(ice);
0973     return change;
0974 }
0975 
0976 /*
0977  * ADC mute control
0978  */
0979 #define wm_adc_mute_info        snd_ctl_boolean_stereo_info
0980 
0981 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0982 {
0983     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0984     unsigned short val;
0985     int i;
0986 
0987     mutex_lock(&ice->gpio_mutex);
0988     for (i = 0; i < 2; i++) {
0989         val = wm_get(ice, WM_ADC_GAIN + i);
0990         ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
0991     }
0992     mutex_unlock(&ice->gpio_mutex);
0993     return 0;
0994 }
0995 
0996 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0997 {
0998     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0999     unsigned short new, old;
1000     int i, change = 0;
1001 
1002     snd_ice1712_save_gpio_status(ice);
1003     for (i = 0; i < 2; i++) {
1004         old = wm_get(ice, WM_ADC_GAIN + i);
1005         new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1006         if (new != old) {
1007             wm_put(ice, WM_ADC_GAIN + i, new);
1008             change = 1;
1009         }
1010     }
1011     snd_ice1712_restore_gpio_status(ice);
1012 
1013     return change;
1014 }
1015 
1016 /*
1017  * ADC gain mixer control
1018  */
1019 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1020 {
1021     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1022     uinfo->count = 2;
1023     uinfo->value.integer.min = 0;       /* -12dB */
1024     uinfo->value.integer.max = 0x1f;    /* 19dB */
1025     return 0;
1026 }
1027 
1028 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1029 {
1030     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031     int i, idx;
1032     unsigned short vol;
1033 
1034     mutex_lock(&ice->gpio_mutex);
1035     for (i = 0; i < 2; i++) {
1036         idx = WM_ADC_GAIN + i;
1037         vol = wm_get(ice, idx) & 0x1f;
1038         ucontrol->value.integer.value[i] = vol;
1039     }
1040     mutex_unlock(&ice->gpio_mutex);
1041     return 0;
1042 }
1043 
1044 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045 {
1046     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1047     int i, idx;
1048     unsigned short ovol, nvol;
1049     int change = 0;
1050 
1051     snd_ice1712_save_gpio_status(ice);
1052     for (i = 0; i < 2; i++) {
1053         idx  = WM_ADC_GAIN + i;
1054         nvol = ucontrol->value.integer.value[i] & 0x1f;
1055         ovol = wm_get(ice, idx);
1056         if ((ovol & 0x1f) != nvol) {
1057             wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058             change = 1;
1059         }
1060     }
1061     snd_ice1712_restore_gpio_status(ice);
1062     return change;
1063 }
1064 
1065 /*
1066  * ADC input mux mixer control
1067  */
1068 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1069 {
1070     static const char * const texts[] = {
1071         "CD",       /* AIN1 */
1072         "Aux",      /* AIN2 */
1073         "Line",     /* AIN3 */
1074         "Mic",      /* AIN4 */
1075         "AC97"      /* AIN5 */
1076     };
1077     static const char * const universe_texts[] = {
1078         "Aux1",     /* AIN1 */
1079         "CD",       /* AIN2 */
1080         "Phono",    /* AIN3 */
1081         "Line",     /* AIN4 */
1082         "Aux2",     /* AIN5 */
1083         "Mic",      /* AIN6 */
1084         "Aux3",     /* AIN7 */
1085         "AC97"      /* AIN8 */
1086     };
1087     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1088 
1089     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE)
1090         return snd_ctl_enum_info(uinfo, 2, 8, universe_texts);
1091     else
1092         return snd_ctl_enum_info(uinfo, 2, 5, texts);
1093 }
1094 
1095 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1096 {
1097     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1098     unsigned short val;
1099 
1100     mutex_lock(&ice->gpio_mutex);
1101     val = wm_get(ice, WM_ADC_MUX);
1102     ucontrol->value.enumerated.item[0] = val & 7;
1103     ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1104     mutex_unlock(&ice->gpio_mutex);
1105     return 0;
1106 }
1107 
1108 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1109 {
1110     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1111     unsigned short oval, nval;
1112     int change;
1113 
1114     snd_ice1712_save_gpio_status(ice);
1115     oval = wm_get(ice, WM_ADC_MUX);
1116     nval = oval & ~0x77;
1117     nval |= ucontrol->value.enumerated.item[0] & 7;
1118     nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1119     change = (oval != nval);
1120     if (change)
1121         wm_put(ice, WM_ADC_MUX, nval);
1122     snd_ice1712_restore_gpio_status(ice);
1123     return change;
1124 }
1125 
1126 /*
1127  * CS8415 Input mux
1128  */
1129 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130 {
1131     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1132     static const char * const aureon_texts[] = {
1133         "CD",       /* RXP0 */
1134         "Optical"   /* RXP1 */
1135     };
1136     static const char * const prodigy_texts[] = {
1137         "CD",
1138         "Coax"
1139     };
1140     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1141         return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts);
1142     else
1143         return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts);
1144 }
1145 
1146 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1147 {
1148     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1149     struct aureon_spec *spec = ice->spec;
1150 
1151     /* snd_ice1712_save_gpio_status(ice); */
1152     /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
1153     ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1154     /* snd_ice1712_restore_gpio_status(ice); */
1155     return 0;
1156 }
1157 
1158 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1159 {
1160     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1161     struct aureon_spec *spec = ice->spec;
1162     unsigned short oval, nval;
1163     int change;
1164 
1165     snd_ice1712_save_gpio_status(ice);
1166     oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1167     nval = oval & ~0x07;
1168     nval |= ucontrol->value.enumerated.item[0] & 7;
1169     change = (oval != nval);
1170     if (change)
1171         aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1172     snd_ice1712_restore_gpio_status(ice);
1173     spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1174     return change;
1175 }
1176 
1177 static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1178 {
1179     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1180     uinfo->count = 1;
1181     uinfo->value.integer.min = 0;
1182     uinfo->value.integer.max = 192000;
1183     return 0;
1184 }
1185 
1186 static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1187 {
1188     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1189     unsigned char ratio;
1190     ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1191     ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1192     return 0;
1193 }
1194 
1195 /*
1196  * CS8415A Mute
1197  */
1198 #define aureon_cs8415_mute_info     snd_ctl_boolean_mono_info
1199 
1200 static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1201 {
1202     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1203     snd_ice1712_save_gpio_status(ice);
1204     ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1205     snd_ice1712_restore_gpio_status(ice);
1206     return 0;
1207 }
1208 
1209 static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1210 {
1211     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212     unsigned char oval, nval;
1213     int change;
1214     snd_ice1712_save_gpio_status(ice);
1215     oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1216     if (ucontrol->value.integer.value[0])
1217         nval = oval & ~0x20;
1218     else
1219         nval = oval | 0x20;
1220     change = (oval != nval);
1221     if (change)
1222         aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1223     snd_ice1712_restore_gpio_status(ice);
1224     return change;
1225 }
1226 
1227 /*
1228  * CS8415A Q-Sub info
1229  */
1230 static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1231 {
1232     uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1233     uinfo->count = 10;
1234     return 0;
1235 }
1236 
1237 static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1238 {
1239     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240 
1241     snd_ice1712_save_gpio_status(ice);
1242     aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1243     snd_ice1712_restore_gpio_status(ice);
1244 
1245     return 0;
1246 }
1247 
1248 static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1249 {
1250     uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1251     uinfo->count = 1;
1252     return 0;
1253 }
1254 
1255 static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1256 {
1257     memset(ucontrol->value.iec958.status, 0xFF, 24);
1258     return 0;
1259 }
1260 
1261 static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1262 {
1263     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1264 
1265     snd_ice1712_save_gpio_status(ice);
1266     aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1267     snd_ice1712_restore_gpio_status(ice);
1268     return 0;
1269 }
1270 
1271 /*
1272  * Headphone Amplifier
1273  */
1274 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1275 {
1276     unsigned int tmp, tmp2;
1277 
1278     tmp2 = tmp = snd_ice1712_gpio_read(ice);
1279     if (enable)
1280         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1281             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1282             tmp |= AUREON_HP_SEL;
1283         else
1284             tmp |= PRODIGY_HP_SEL;
1285     else
1286         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1287             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1288             tmp &= ~AUREON_HP_SEL;
1289         else
1290             tmp &= ~PRODIGY_HP_SEL;
1291     if (tmp != tmp2) {
1292         snd_ice1712_gpio_write(ice, tmp);
1293         return 1;
1294     }
1295     return 0;
1296 }
1297 
1298 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1299 {
1300     unsigned int tmp = snd_ice1712_gpio_read(ice);
1301 
1302     return (tmp & AUREON_HP_SEL) != 0;
1303 }
1304 
1305 #define aureon_hpamp_info   snd_ctl_boolean_mono_info
1306 
1307 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1308 {
1309     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1310 
1311     ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1312     return 0;
1313 }
1314 
1315 
1316 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1317 {
1318     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1319 
1320     return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1321 }
1322 
1323 /*
1324  * Deemphasis
1325  */
1326 
1327 #define aureon_deemp_info   snd_ctl_boolean_mono_info
1328 
1329 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1330 {
1331     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1332     ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1333     return 0;
1334 }
1335 
1336 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1337 {
1338     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1339     int temp, temp2;
1340     temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1341     if (ucontrol->value.integer.value[0])
1342         temp |= 0xf;
1343     else
1344         temp &= ~0xf;
1345     if (temp != temp2) {
1346         wm_put(ice, WM_DAC_CTRL2, temp);
1347         return 1;
1348     }
1349     return 0;
1350 }
1351 
1352 /*
1353  * ADC Oversampling
1354  */
1355 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1356 {
1357     static const char * const texts[2] = { "128x", "64x"    };
1358 
1359     return snd_ctl_enum_info(uinfo, 1, 2, texts);
1360 }
1361 
1362 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363 {
1364     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1365     ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1366     return 0;
1367 }
1368 
1369 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1370 {
1371     int temp, temp2;
1372     struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1373 
1374     temp2 = temp = wm_get(ice, WM_MASTER);
1375 
1376     if (ucontrol->value.enumerated.item[0])
1377         temp |= 0x8;
1378     else
1379         temp &= ~0x8;
1380 
1381     if (temp != temp2) {
1382         wm_put(ice, WM_MASTER, temp);
1383         return 1;
1384     }
1385     return 0;
1386 }
1387 
1388 /*
1389  * mixers
1390  */
1391 
1392 static const struct snd_kcontrol_new aureon_dac_controls[] = {
1393     {
1394         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395         .name = "Master Playback Switch",
1396         .info = wm_master_mute_info,
1397         .get = wm_master_mute_get,
1398         .put = wm_master_mute_put
1399     },
1400     {
1401         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1402         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1403                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1404         .name = "Master Playback Volume",
1405         .info = wm_master_vol_info,
1406         .get = wm_master_vol_get,
1407         .put = wm_master_vol_put,
1408         .tlv = { .p = db_scale_wm_dac }
1409     },
1410     {
1411         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412         .name = "Front Playback Switch",
1413         .info = wm_mute_info,
1414         .get = wm_mute_get,
1415         .put = wm_mute_put,
1416         .private_value = (2 << 8) | 0
1417     },
1418     {
1419         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1421                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1422         .name = "Front Playback Volume",
1423         .info = wm_vol_info,
1424         .get = wm_vol_get,
1425         .put = wm_vol_put,
1426         .private_value = (2 << 8) | 0,
1427         .tlv = { .p = db_scale_wm_dac }
1428     },
1429     {
1430         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1431         .name = "Rear Playback Switch",
1432         .info = wm_mute_info,
1433         .get = wm_mute_get,
1434         .put = wm_mute_put,
1435         .private_value = (2 << 8) | 2
1436     },
1437     {
1438         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1440                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1441         .name = "Rear Playback Volume",
1442         .info = wm_vol_info,
1443         .get = wm_vol_get,
1444         .put = wm_vol_put,
1445         .private_value = (2 << 8) | 2,
1446         .tlv = { .p = db_scale_wm_dac }
1447     },
1448     {
1449         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1450         .name = "Center Playback Switch",
1451         .info = wm_mute_info,
1452         .get = wm_mute_get,
1453         .put = wm_mute_put,
1454         .private_value = (1 << 8) | 4
1455     },
1456     {
1457         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1458         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1459                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1460         .name = "Center Playback Volume",
1461         .info = wm_vol_info,
1462         .get = wm_vol_get,
1463         .put = wm_vol_put,
1464         .private_value = (1 << 8) | 4,
1465         .tlv = { .p = db_scale_wm_dac }
1466     },
1467     {
1468         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1469         .name = "LFE Playback Switch",
1470         .info = wm_mute_info,
1471         .get = wm_mute_get,
1472         .put = wm_mute_put,
1473         .private_value = (1 << 8) | 5
1474     },
1475     {
1476         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1477         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1478                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1479         .name = "LFE Playback Volume",
1480         .info = wm_vol_info,
1481         .get = wm_vol_get,
1482         .put = wm_vol_put,
1483         .private_value = (1 << 8) | 5,
1484         .tlv = { .p = db_scale_wm_dac }
1485     },
1486     {
1487         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1488         .name = "Side Playback Switch",
1489         .info = wm_mute_info,
1490         .get = wm_mute_get,
1491         .put = wm_mute_put,
1492         .private_value = (2 << 8) | 6
1493     },
1494     {
1495         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1496         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1497                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1498         .name = "Side Playback Volume",
1499         .info = wm_vol_info,
1500         .get = wm_vol_get,
1501         .put = wm_vol_put,
1502         .private_value = (2 << 8) | 6,
1503         .tlv = { .p = db_scale_wm_dac }
1504     }
1505 };
1506 
1507 static const struct snd_kcontrol_new wm_controls[] = {
1508     {
1509         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1510         .name = "PCM Playback Switch",
1511         .info = wm_pcm_mute_info,
1512         .get = wm_pcm_mute_get,
1513         .put = wm_pcm_mute_put
1514     },
1515     {
1516         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1519         .name = "PCM Playback Volume",
1520         .info = wm_pcm_vol_info,
1521         .get = wm_pcm_vol_get,
1522         .put = wm_pcm_vol_put,
1523         .tlv = { .p = db_scale_wm_pcm }
1524     },
1525     {
1526         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527         .name = "Capture Switch",
1528         .info = wm_adc_mute_info,
1529         .get = wm_adc_mute_get,
1530         .put = wm_adc_mute_put,
1531     },
1532     {
1533         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1536         .name = "Capture Volume",
1537         .info = wm_adc_vol_info,
1538         .get = wm_adc_vol_get,
1539         .put = wm_adc_vol_put,
1540         .tlv = { .p = db_scale_wm_adc }
1541     },
1542     {
1543         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544         .name = "Capture Source",
1545         .info = wm_adc_mux_info,
1546         .get = wm_adc_mux_get,
1547         .put = wm_adc_mux_put,
1548         .private_value = 5
1549     },
1550     {
1551         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1552         .name = "External Amplifier",
1553         .info = aureon_hpamp_info,
1554         .get = aureon_hpamp_get,
1555         .put = aureon_hpamp_put
1556     },
1557     {
1558         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1559         .name = "DAC Deemphasis Switch",
1560         .info = aureon_deemp_info,
1561         .get = aureon_deemp_get,
1562         .put = aureon_deemp_put
1563     },
1564     {
1565         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566         .name = "ADC Oversampling",
1567         .info = aureon_oversampling_info,
1568         .get = aureon_oversampling_get,
1569         .put = aureon_oversampling_put
1570     }
1571 };
1572 
1573 static const struct snd_kcontrol_new ac97_controls[] = {
1574     {
1575         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576         .name = "AC97 Playback Switch",
1577         .info = aureon_ac97_mmute_info,
1578         .get = aureon_ac97_mmute_get,
1579         .put = aureon_ac97_mmute_put,
1580         .private_value = AC97_MASTER
1581     },
1582     {
1583         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1585                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1586         .name = "AC97 Playback Volume",
1587         .info = aureon_ac97_vol_info,
1588         .get = aureon_ac97_vol_get,
1589         .put = aureon_ac97_vol_put,
1590         .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1591         .tlv = { .p = db_scale_ac97_master }
1592     },
1593     {
1594         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595         .name = "CD Playback Switch",
1596         .info = aureon_ac97_mute_info,
1597         .get = aureon_ac97_mute_get,
1598         .put = aureon_ac97_mute_put,
1599         .private_value = AC97_CD
1600     },
1601     {
1602         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1604                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1605         .name = "CD Playback Volume",
1606         .info = aureon_ac97_vol_info,
1607         .get = aureon_ac97_vol_get,
1608         .put = aureon_ac97_vol_put,
1609         .private_value = AC97_CD|AUREON_AC97_STEREO,
1610         .tlv = { .p = db_scale_ac97_gain }
1611     },
1612     {
1613         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1614         .name = "Aux Playback Switch",
1615         .info = aureon_ac97_mute_info,
1616         .get = aureon_ac97_mute_get,
1617         .put = aureon_ac97_mute_put,
1618         .private_value = AC97_AUX,
1619     },
1620     {
1621         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1623                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1624         .name = "Aux Playback Volume",
1625         .info = aureon_ac97_vol_info,
1626         .get = aureon_ac97_vol_get,
1627         .put = aureon_ac97_vol_put,
1628         .private_value = AC97_AUX|AUREON_AC97_STEREO,
1629         .tlv = { .p = db_scale_ac97_gain }
1630     },
1631     {
1632         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1633         .name = "Line Playback Switch",
1634         .info = aureon_ac97_mute_info,
1635         .get = aureon_ac97_mute_get,
1636         .put = aureon_ac97_mute_put,
1637         .private_value = AC97_LINE
1638     },
1639     {
1640         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1641         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1642                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1643         .name = "Line Playback Volume",
1644         .info = aureon_ac97_vol_info,
1645         .get = aureon_ac97_vol_get,
1646         .put = aureon_ac97_vol_put,
1647         .private_value = AC97_LINE|AUREON_AC97_STEREO,
1648         .tlv = { .p = db_scale_ac97_gain }
1649     },
1650     {
1651         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1652         .name = "Mic Playback Switch",
1653         .info = aureon_ac97_mute_info,
1654         .get = aureon_ac97_mute_get,
1655         .put = aureon_ac97_mute_put,
1656         .private_value = AC97_MIC
1657     },
1658     {
1659         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1661                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1662         .name = "Mic Playback Volume",
1663         .info = aureon_ac97_vol_info,
1664         .get = aureon_ac97_vol_get,
1665         .put = aureon_ac97_vol_put,
1666         .private_value = AC97_MIC,
1667         .tlv = { .p = db_scale_ac97_gain }
1668     },
1669     {
1670         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671         .name = "Mic Boost (+20dB)",
1672         .info = aureon_ac97_micboost_info,
1673         .get = aureon_ac97_micboost_get,
1674         .put = aureon_ac97_micboost_put
1675     }
1676 };
1677 
1678 static const struct snd_kcontrol_new universe_ac97_controls[] = {
1679     {
1680         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681         .name = "AC97 Playback Switch",
1682         .info = aureon_ac97_mmute_info,
1683         .get = aureon_ac97_mmute_get,
1684         .put = aureon_ac97_mmute_put,
1685         .private_value = AC97_MASTER
1686     },
1687     {
1688         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1689         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1690                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1691         .name = "AC97 Playback Volume",
1692         .info = aureon_ac97_vol_info,
1693         .get = aureon_ac97_vol_get,
1694         .put = aureon_ac97_vol_put,
1695         .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1696         .tlv = { .p = db_scale_ac97_master }
1697     },
1698     {
1699         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700         .name = "CD Playback Switch",
1701         .info = aureon_ac97_mute_info,
1702         .get = aureon_ac97_mute_get,
1703         .put = aureon_ac97_mute_put,
1704         .private_value = AC97_AUX
1705     },
1706     {
1707         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1709                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1710         .name = "CD Playback Volume",
1711         .info = aureon_ac97_vol_info,
1712         .get = aureon_ac97_vol_get,
1713         .put = aureon_ac97_vol_put,
1714         .private_value = AC97_AUX|AUREON_AC97_STEREO,
1715         .tlv = { .p = db_scale_ac97_gain }
1716     },
1717     {
1718         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719         .name = "Phono Playback Switch",
1720         .info = aureon_ac97_mute_info,
1721         .get = aureon_ac97_mute_get,
1722         .put = aureon_ac97_mute_put,
1723         .private_value = AC97_CD
1724     },
1725     {
1726         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1727         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1728                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1729         .name = "Phono Playback Volume",
1730         .info = aureon_ac97_vol_info,
1731         .get = aureon_ac97_vol_get,
1732         .put = aureon_ac97_vol_put,
1733         .private_value = AC97_CD|AUREON_AC97_STEREO,
1734         .tlv = { .p = db_scale_ac97_gain }
1735     },
1736     {
1737         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1738         .name = "Line Playback Switch",
1739         .info = aureon_ac97_mute_info,
1740         .get = aureon_ac97_mute_get,
1741         .put = aureon_ac97_mute_put,
1742         .private_value = AC97_LINE
1743     },
1744     {
1745         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1747                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1748         .name = "Line Playback Volume",
1749         .info = aureon_ac97_vol_info,
1750         .get = aureon_ac97_vol_get,
1751         .put = aureon_ac97_vol_put,
1752         .private_value = AC97_LINE|AUREON_AC97_STEREO,
1753         .tlv = { .p = db_scale_ac97_gain }
1754     },
1755     {
1756         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1757         .name = "Mic Playback Switch",
1758         .info = aureon_ac97_mute_info,
1759         .get = aureon_ac97_mute_get,
1760         .put = aureon_ac97_mute_put,
1761         .private_value = AC97_MIC
1762     },
1763     {
1764         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1766                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1767         .name = "Mic Playback Volume",
1768         .info = aureon_ac97_vol_info,
1769         .get = aureon_ac97_vol_get,
1770         .put = aureon_ac97_vol_put,
1771         .private_value = AC97_MIC,
1772         .tlv = { .p = db_scale_ac97_gain }
1773     },
1774     {
1775         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1776         .name = "Mic Boost (+20dB)",
1777         .info = aureon_ac97_micboost_info,
1778         .get = aureon_ac97_micboost_get,
1779         .put = aureon_ac97_micboost_put
1780     },
1781     {
1782         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1783         .name = "Aux Playback Switch",
1784         .info = aureon_ac97_mute_info,
1785         .get = aureon_ac97_mute_get,
1786         .put = aureon_ac97_mute_put,
1787         .private_value = AC97_VIDEO,
1788     },
1789     {
1790         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791         .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1792                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1793         .name = "Aux Playback Volume",
1794         .info = aureon_ac97_vol_info,
1795         .get = aureon_ac97_vol_get,
1796         .put = aureon_ac97_vol_put,
1797         .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1798         .tlv = { .p = db_scale_ac97_gain }
1799     },
1800     {
1801         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1802         .name = "Aux Source",
1803         .info = aureon_universe_inmux_info,
1804         .get = aureon_universe_inmux_get,
1805         .put = aureon_universe_inmux_put
1806     }
1807 
1808 };
1809 
1810 static const struct snd_kcontrol_new cs8415_controls[] = {
1811     {
1812         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1813         .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1814         .info = aureon_cs8415_mute_info,
1815         .get = aureon_cs8415_mute_get,
1816         .put = aureon_cs8415_mute_put
1817     },
1818     {
1819         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1820         .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1821         .info = aureon_cs8415_mux_info,
1822         .get = aureon_cs8415_mux_get,
1823         .put = aureon_cs8415_mux_put,
1824     },
1825     {
1826         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1827         .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1828         .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1829         .info = aureon_cs8415_qsub_info,
1830         .get = aureon_cs8415_qsub_get,
1831     },
1832     {
1833         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1834         .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1835         .access = SNDRV_CTL_ELEM_ACCESS_READ,
1836         .info = aureon_cs8415_spdif_info,
1837         .get = aureon_cs8415_mask_get
1838     },
1839     {
1840         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1841         .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1842         .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1843         .info = aureon_cs8415_spdif_info,
1844         .get = aureon_cs8415_spdif_get
1845     },
1846     {
1847         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1848         .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1849         .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1850         .info = aureon_cs8415_rate_info,
1851         .get = aureon_cs8415_rate_get
1852     }
1853 };
1854 
1855 static int aureon_add_controls(struct snd_ice1712 *ice)
1856 {
1857     unsigned int i, counts;
1858     int err;
1859 
1860     counts = ARRAY_SIZE(aureon_dac_controls);
1861     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1862         counts -= 2; /* no side */
1863     for (i = 0; i < counts; i++) {
1864         err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1865         if (err < 0)
1866             return err;
1867     }
1868 
1869     for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1870         err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1871         if (err < 0)
1872             return err;
1873     }
1874 
1875     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1876         for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1877             err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1878             if (err < 0)
1879                 return err;
1880         }
1881     } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1882          ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1883         for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1884             err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1885             if (err < 0)
1886                 return err;
1887         }
1888     }
1889 
1890     if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1891         ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1892         unsigned char id;
1893         snd_ice1712_save_gpio_status(ice);
1894         id = aureon_cs8415_get(ice, CS8415_ID);
1895         if (id != 0x41)
1896             dev_info(ice->card->dev,
1897                  "No CS8415 chip. Skipping CS8415 controls.\n");
1898         else if ((id & 0x0F) != 0x01)
1899             dev_info(ice->card->dev,
1900                  "Detected unsupported CS8415 rev. (%c)\n",
1901                  (char)((id & 0x0F) + 'A' - 1));
1902         else {
1903             for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1904                 struct snd_kcontrol *kctl;
1905                 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1906                 if (err < 0)
1907                     return err;
1908                 if (i > 1)
1909                     kctl->id.device = ice->pcm->device;
1910             }
1911         }
1912         snd_ice1712_restore_gpio_status(ice);
1913     }
1914 
1915     return 0;
1916 }
1917 
1918 /*
1919  * reset the chip
1920  */
1921 static int aureon_reset(struct snd_ice1712 *ice)
1922 {
1923     static const unsigned short wm_inits_aureon[] = {
1924         /* These come first to reduce init pop noise */
1925         0x1b, 0x044,        /* ADC Mux (AC'97 source) */
1926         0x1c, 0x00B,        /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1927         0x1d, 0x009,        /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1928 
1929         0x18, 0x000,        /* All power-up */
1930 
1931         0x16, 0x122,        /* I2S, normal polarity, 24bit */
1932         0x17, 0x022,        /* 256fs, slave mode */
1933         0x00, 0,        /* DAC1 analog mute */
1934         0x01, 0,        /* DAC2 analog mute */
1935         0x02, 0,        /* DAC3 analog mute */
1936         0x03, 0,        /* DAC4 analog mute */
1937         0x04, 0,        /* DAC5 analog mute */
1938         0x05, 0,        /* DAC6 analog mute */
1939         0x06, 0,        /* DAC7 analog mute */
1940         0x07, 0,        /* DAC8 analog mute */
1941         0x08, 0x100,        /* master analog mute */
1942         0x09, 0xff,     /* DAC1 digital full */
1943         0x0a, 0xff,     /* DAC2 digital full */
1944         0x0b, 0xff,     /* DAC3 digital full */
1945         0x0c, 0xff,     /* DAC4 digital full */
1946         0x0d, 0xff,     /* DAC5 digital full */
1947         0x0e, 0xff,     /* DAC6 digital full */
1948         0x0f, 0xff,     /* DAC7 digital full */
1949         0x10, 0xff,     /* DAC8 digital full */
1950         0x11, 0x1ff,        /* master digital full */
1951         0x12, 0x000,        /* phase normal */
1952         0x13, 0x090,        /* unmute DAC L/R */
1953         0x14, 0x000,        /* all unmute */
1954         0x15, 0x000,        /* no deemphasis, no ZFLG */
1955         0x19, 0x000,        /* -12dB ADC/L */
1956         0x1a, 0x000,        /* -12dB ADC/R */
1957         (unsigned short)-1
1958     };
1959     static const unsigned short wm_inits_prodigy[] = {
1960 
1961         /* These come first to reduce init pop noise */
1962         0x1b, 0x000,        /* ADC Mux */
1963         0x1c, 0x009,        /* Out Mux1 */
1964         0x1d, 0x009,        /* Out Mux2 */
1965 
1966         0x18, 0x000,        /* All power-up */
1967 
1968         0x16, 0x022,        /* I2S, normal polarity, 24bit, high-pass on */
1969         0x17, 0x006,        /* 128fs, slave mode */
1970 
1971         0x00, 0,        /* DAC1 analog mute */
1972         0x01, 0,        /* DAC2 analog mute */
1973         0x02, 0,        /* DAC3 analog mute */
1974         0x03, 0,        /* DAC4 analog mute */
1975         0x04, 0,        /* DAC5 analog mute */
1976         0x05, 0,        /* DAC6 analog mute */
1977         0x06, 0,        /* DAC7 analog mute */
1978         0x07, 0,        /* DAC8 analog mute */
1979         0x08, 0x100,        /* master analog mute */
1980 
1981         0x09, 0x7f,     /* DAC1 digital full */
1982         0x0a, 0x7f,     /* DAC2 digital full */
1983         0x0b, 0x7f,     /* DAC3 digital full */
1984         0x0c, 0x7f,     /* DAC4 digital full */
1985         0x0d, 0x7f,     /* DAC5 digital full */
1986         0x0e, 0x7f,     /* DAC6 digital full */
1987         0x0f, 0x7f,     /* DAC7 digital full */
1988         0x10, 0x7f,     /* DAC8 digital full */
1989         0x11, 0x1FF,        /* master digital full */
1990 
1991         0x12, 0x000,        /* phase normal */
1992         0x13, 0x090,        /* unmute DAC L/R */
1993         0x14, 0x000,        /* all unmute */
1994         0x15, 0x000,        /* no deemphasis, no ZFLG */
1995 
1996         0x19, 0x000,        /* -12dB ADC/L */
1997         0x1a, 0x000,        /* -12dB ADC/R */
1998         (unsigned short)-1
1999 
2000     };
2001     static const unsigned short cs_inits[] = {
2002         0x0441, /* RUN */
2003         0x0180, /* no mute, OMCK output on RMCK pin */
2004         0x0201, /* S/PDIF source on RXP1 */
2005         0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2006         (unsigned short)-1
2007     };
2008     unsigned int tmp;
2009     const unsigned short *p;
2010     int err;
2011     struct aureon_spec *spec = ice->spec;
2012 
2013     err = aureon_ac97_init(ice);
2014     if (err != 0)
2015         return err;
2016 
2017     snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2018 
2019     /* reset the wm codec as the SPI mode */
2020     snd_ice1712_save_gpio_status(ice);
2021     snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2022 
2023     tmp = snd_ice1712_gpio_read(ice);
2024     tmp &= ~AUREON_WM_RESET;
2025     snd_ice1712_gpio_write(ice, tmp);
2026     udelay(1);
2027     tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2028     snd_ice1712_gpio_write(ice, tmp);
2029     udelay(1);
2030     tmp |= AUREON_WM_RESET;
2031     snd_ice1712_gpio_write(ice, tmp);
2032     udelay(1);
2033 
2034     /* initialize WM8770 codec */
2035     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2036         ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2037         ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2038         p = wm_inits_prodigy;
2039     else
2040         p = wm_inits_aureon;
2041     for (; *p != (unsigned short)-1; p += 2)
2042         wm_put(ice, p[0], p[1]);
2043 
2044     /* initialize CS8415A codec */
2045     if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2046         ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2047         for (p = cs_inits; *p != (unsigned short)-1; p++)
2048             aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2049         spec->cs8415_mux = 1;
2050 
2051         aureon_set_headphone_amp(ice, 1);
2052     }
2053 
2054     snd_ice1712_restore_gpio_status(ice);
2055 
2056     /* initialize PCA9554 pin directions & set default input */
2057     aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2058     aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2059     return 0;
2060 }
2061 
2062 /*
2063  * suspend/resume
2064  */
2065 #ifdef CONFIG_PM_SLEEP
2066 static int aureon_resume(struct snd_ice1712 *ice)
2067 {
2068     struct aureon_spec *spec = ice->spec;
2069     int err, i;
2070 
2071     err = aureon_reset(ice);
2072     if (err != 0)
2073         return err;
2074 
2075     /* workaround for poking volume with alsamixer after resume:
2076      * just set stored volume again */
2077     for (i = 0; i < ice->num_total_dacs; i++)
2078         wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2079     return 0;
2080 }
2081 #endif
2082 
2083 /*
2084  * initialize the chip
2085  */
2086 static int aureon_init(struct snd_ice1712 *ice)
2087 {
2088     struct aureon_spec *spec;
2089     int i, err;
2090 
2091     spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2092     if (!spec)
2093         return -ENOMEM;
2094     ice->spec = spec;
2095 
2096     if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2097         ice->num_total_dacs = 6;
2098         ice->num_total_adcs = 2;
2099     } else {
2100         /* aureon 7.1 and prodigy 7.1 */
2101         ice->num_total_dacs = 8;
2102         ice->num_total_adcs = 2;
2103     }
2104 
2105     /* to remember the register values of CS8415 */
2106     ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2107     if (!ice->akm)
2108         return -ENOMEM;
2109     ice->akm_codecs = 1;
2110 
2111     err = aureon_reset(ice);
2112     if (err != 0)
2113         return err;
2114 
2115     spec->master[0] = WM_VOL_MUTE;
2116     spec->master[1] = WM_VOL_MUTE;
2117     for (i = 0; i < ice->num_total_dacs; i++) {
2118         spec->vol[i] = WM_VOL_MUTE;
2119         wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2120     }
2121 
2122 #ifdef CONFIG_PM_SLEEP
2123     ice->pm_resume = aureon_resume;
2124     ice->pm_suspend_enabled = 1;
2125 #endif
2126 
2127     return 0;
2128 }
2129 
2130 
2131 /*
2132  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2133  * hence the driver needs to sets up it properly.
2134  */
2135 
2136 static const unsigned char aureon51_eeprom[] = {
2137     [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
2138     [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2139     [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2140     [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2141     [ICE_EEP2_GPIO_DIR]    = 0xff,
2142     [ICE_EEP2_GPIO_DIR1]   = 0xff,
2143     [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2144     [ICE_EEP2_GPIO_MASK]   = 0x00,
2145     [ICE_EEP2_GPIO_MASK1]  = 0x00,
2146     [ICE_EEP2_GPIO_MASK2]  = 0x00,
2147     [ICE_EEP2_GPIO_STATE]  = 0x00,
2148     [ICE_EEP2_GPIO_STATE1] = 0x00,
2149     [ICE_EEP2_GPIO_STATE2] = 0x00,
2150 };
2151 
2152 static const unsigned char aureon71_eeprom[] = {
2153     [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
2154     [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2155     [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2156     [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2157     [ICE_EEP2_GPIO_DIR]    = 0xff,
2158     [ICE_EEP2_GPIO_DIR1]   = 0xff,
2159     [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2160     [ICE_EEP2_GPIO_MASK]   = 0x00,
2161     [ICE_EEP2_GPIO_MASK1]  = 0x00,
2162     [ICE_EEP2_GPIO_MASK2]  = 0x00,
2163     [ICE_EEP2_GPIO_STATE]  = 0x00,
2164     [ICE_EEP2_GPIO_STATE1] = 0x00,
2165     [ICE_EEP2_GPIO_STATE2] = 0x00,
2166 };
2167 #define prodigy71_eeprom aureon71_eeprom
2168 
2169 static const unsigned char aureon71_universe_eeprom[] = {
2170     [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, spdif-in/ADC,
2171                      * 4DACs
2172                      */
2173     [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2174     [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2175     [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2176     [ICE_EEP2_GPIO_DIR]    = 0xff,
2177     [ICE_EEP2_GPIO_DIR1]   = 0xff,
2178     [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2179     [ICE_EEP2_GPIO_MASK]   = 0x00,
2180     [ICE_EEP2_GPIO_MASK1]  = 0x00,
2181     [ICE_EEP2_GPIO_MASK2]  = 0x00,
2182     [ICE_EEP2_GPIO_STATE]  = 0x00,
2183     [ICE_EEP2_GPIO_STATE1] = 0x00,
2184     [ICE_EEP2_GPIO_STATE2] = 0x00,
2185 };
2186 
2187 static const unsigned char prodigy71lt_eeprom[] = {
2188     [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
2189     [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2190     [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2191     [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2192     [ICE_EEP2_GPIO_DIR]    = 0xff,
2193     [ICE_EEP2_GPIO_DIR1]   = 0xff,
2194     [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2195     [ICE_EEP2_GPIO_MASK]   = 0x00,
2196     [ICE_EEP2_GPIO_MASK1]  = 0x00,
2197     [ICE_EEP2_GPIO_MASK2]  = 0x00,
2198     [ICE_EEP2_GPIO_STATE]  = 0x00,
2199     [ICE_EEP2_GPIO_STATE1] = 0x00,
2200     [ICE_EEP2_GPIO_STATE2] = 0x00,
2201 };
2202 #define prodigy71xt_eeprom prodigy71lt_eeprom
2203 
2204 /* entry point */
2205 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
2206     {
2207         .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2208         .name = "Terratec Aureon 5.1-Sky",
2209         .model = "aureon51",
2210         .chip_init = aureon_init,
2211         .build_controls = aureon_add_controls,
2212         .eeprom_size = sizeof(aureon51_eeprom),
2213         .eeprom_data = aureon51_eeprom,
2214         .driver = "Aureon51",
2215     },
2216     {
2217         .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2218         .name = "Terratec Aureon 7.1-Space",
2219         .model = "aureon71",
2220         .chip_init = aureon_init,
2221         .build_controls = aureon_add_controls,
2222         .eeprom_size = sizeof(aureon71_eeprom),
2223         .eeprom_data = aureon71_eeprom,
2224         .driver = "Aureon71",
2225     },
2226     {
2227         .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2228         .name = "Terratec Aureon 7.1-Universe",
2229         .model = "universe",
2230         .chip_init = aureon_init,
2231         .build_controls = aureon_add_controls,
2232         .eeprom_size = sizeof(aureon71_universe_eeprom),
2233         .eeprom_data = aureon71_universe_eeprom,
2234         .driver = "Aureon71Univ", /* keep in 15 letters */
2235     },
2236     {
2237         .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2238         .name = "Audiotrak Prodigy 7.1",
2239         .model = "prodigy71",
2240         .chip_init = aureon_init,
2241         .build_controls = aureon_add_controls,
2242         .eeprom_size = sizeof(prodigy71_eeprom),
2243         .eeprom_data = prodigy71_eeprom,
2244         .driver = "Prodigy71", /* should be identical with Aureon71 */
2245     },
2246     {
2247         .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2248         .name = "Audiotrak Prodigy 7.1 LT",
2249         .model = "prodigy71lt",
2250         .chip_init = aureon_init,
2251         .build_controls = aureon_add_controls,
2252         .eeprom_size = sizeof(prodigy71lt_eeprom),
2253         .eeprom_data = prodigy71lt_eeprom,
2254         .driver = "Prodigy71LT",
2255     },
2256     {
2257         .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2258         .name = "Audiotrak Prodigy 7.1 XT",
2259         .model = "prodigy71xt",
2260         .chip_init = aureon_init,
2261         .build_controls = aureon_add_controls,
2262         .eeprom_size = sizeof(prodigy71xt_eeprom),
2263         .eeprom_data = prodigy71xt_eeprom,
2264         .driver = "Prodigy71LT",
2265     },
2266     { } /* terminator */
2267 };