linux/sound/pci/ice1712/aureon.c
<<
>>
Prefs
   1/*
   2 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
   3 *
   4 *   Lowlevel functions for Terratec Aureon cards
   5 *
   6 *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 *
  23 * NOTES:
  24 *
  25 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
  26 *   both wm and akm codecs are pretty similar, so we can integrate
  27 *   both controls in the future, once if wm codecs are reused in
  28 *   many boards.
  29 *
  30 * - DAC digital volumes are not implemented in the mixer.
  31 *   if they show better response than DAC analog volumes, we can use them
  32 *   instead.
  33 *
  34 *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
  35 *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
  36 *
  37 *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
  38 *       added 64x/128x oversampling switch (should be 64x only for 96khz)
  39 *       fixed some recording labels (still need to check the rest)
  40 *       recording is working probably thanks to correct wm8770 initialization
  41 *
  42 *   version 0.5: Initial release:
  43 *           working: analog output, mixer, headphone amplifier switch
  44 *       not working: prety much everything else, at least i could verify that
  45 *                    we have no digital output, no capture, pretty bad clicks and poops
  46 *                    on mixer switch and other coll stuff.
  47 */
  48
  49#include <linux/io.h>
  50#include <linux/delay.h>
  51#include <linux/interrupt.h>
  52#include <linux/init.h>
  53#include <linux/slab.h>
  54#include <linux/mutex.h>
  55
  56#include <sound/core.h>
  57
  58#include "ice1712.h"
  59#include "envy24ht.h"
  60#include "aureon.h"
  61#include <sound/tlv.h>
  62
  63/* AC97 register cache for Aureon */
  64struct aureon_spec {
  65        unsigned short stac9744[64];
  66        unsigned int cs8415_mux;
  67        unsigned short master[2];
  68        unsigned short vol[8];
  69        unsigned char pca9554_out;
  70};
  71
  72/* WM8770 registers */
  73#define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
  74#define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
  75#define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
  76#define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
  77#define WM_PHASE_SWAP           0x12    /* DAC phase */
  78#define WM_DAC_CTRL1            0x13    /* DAC control bits */
  79#define WM_MUTE                 0x14    /* mute controls */
  80#define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
  81#define WM_INT_CTRL             0x16    /* interface control */
  82#define WM_MASTER               0x17    /* master clock and mode */
  83#define WM_POWERDOWN            0x18    /* power-down controls */
  84#define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
  85#define WM_ADC_MUX              0x1b    /* input MUX */
  86#define WM_OUT_MUX1             0x1c    /* output MUX */
  87#define WM_OUT_MUX2             0x1e    /* output MUX */
  88#define WM_RESET                0x1f    /* software reset */
  89
  90/* CS8415A registers */
  91#define CS8415_CTRL1    0x01
  92#define CS8415_CTRL2    0x02
  93#define CS8415_QSUB             0x14
  94#define CS8415_RATIO    0x1E
  95#define CS8415_C_BUFFER 0x20
  96#define CS8415_ID               0x7F
  97
  98/* PCA9554 registers */
  99#define PCA9554_DEV     0x40            /* I2C device address */
 100#define PCA9554_IN      0x00            /* input port */
 101#define PCA9554_OUT     0x01            /* output port */
 102#define PCA9554_INVERT  0x02            /* input invert */
 103#define PCA9554_DIR     0x03            /* port directions */
 104
 105/*
 106 * Aureon Universe additional controls using PCA9554
 107 */
 108
 109/*
 110 * Send data to pca9554
 111 */
 112static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
 113                                 unsigned char data)
 114{
 115        unsigned int tmp;
 116        int i, j;
 117        unsigned char dev = PCA9554_DEV;  /* ID 0100000, write */
 118        unsigned char val = 0;
 119
 120        tmp = snd_ice1712_gpio_read(ice);
 121
 122        snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
 123                                         AUREON_WM_RW|AUREON_WM_CS|
 124                                         AUREON_CS8415_CS));
 125        tmp |= AUREON_WM_RW;
 126        tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
 127
 128        tmp &= ~AUREON_SPI_MOSI;
 129        tmp &= ~AUREON_SPI_CLK;
 130        snd_ice1712_gpio_write(ice, tmp);
 131        udelay(50);
 132
 133        /*
 134         * send i2c stop condition and start condition
 135         * to obtain sane state
 136         */
 137        tmp |= AUREON_SPI_CLK;
 138        snd_ice1712_gpio_write(ice, tmp);
 139        udelay(50);
 140        tmp |= AUREON_SPI_MOSI;
 141        snd_ice1712_gpio_write(ice, tmp);
 142        udelay(100);
 143        tmp &= ~AUREON_SPI_MOSI;
 144        snd_ice1712_gpio_write(ice, tmp);
 145        udelay(50);
 146        tmp &= ~AUREON_SPI_CLK;
 147        snd_ice1712_gpio_write(ice, tmp);
 148        udelay(100);
 149        /*
 150         * send device address, command and value,
 151         * skipping ack cycles inbetween
 152         */
 153        for (j = 0; j < 3; j++) {
 154                switch (j) {
 155                case 0:
 156                        val = dev;
 157                        break;
 158                case 1:
 159                        val = reg;
 160                        break;
 161                case 2:
 162                        val = data;
 163                        break;
 164                }
 165                for (i = 7; i >= 0; i--) {
 166                        tmp &= ~AUREON_SPI_CLK;
 167                        snd_ice1712_gpio_write(ice, tmp);
 168                        udelay(40);
 169                        if (val & (1 << i))
 170                                tmp |= AUREON_SPI_MOSI;
 171                        else
 172                                tmp &= ~AUREON_SPI_MOSI;
 173                        snd_ice1712_gpio_write(ice, tmp);
 174                        udelay(40);
 175                        tmp |= AUREON_SPI_CLK;
 176                        snd_ice1712_gpio_write(ice, tmp);
 177                        udelay(40);
 178                }
 179                tmp &= ~AUREON_SPI_CLK;
 180                snd_ice1712_gpio_write(ice, tmp);
 181                udelay(40);
 182                tmp |= AUREON_SPI_CLK;
 183                snd_ice1712_gpio_write(ice, tmp);
 184                udelay(40);
 185                tmp &= ~AUREON_SPI_CLK;
 186                snd_ice1712_gpio_write(ice, tmp);
 187                udelay(40);
 188        }
 189        tmp &= ~AUREON_SPI_CLK;
 190        snd_ice1712_gpio_write(ice, tmp);
 191        udelay(40);
 192        tmp &= ~AUREON_SPI_MOSI;
 193        snd_ice1712_gpio_write(ice, tmp);
 194        udelay(40);
 195        tmp |= AUREON_SPI_CLK;
 196        snd_ice1712_gpio_write(ice, tmp);
 197        udelay(50);
 198        tmp |= AUREON_SPI_MOSI;
 199        snd_ice1712_gpio_write(ice, tmp);
 200        udelay(100);
 201}
 202
 203static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
 204                                      struct snd_ctl_elem_info *uinfo)
 205{
 206        char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
 207
 208        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 209        uinfo->count = 1;
 210        uinfo->value.enumerated.items = 3;
 211        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 212                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
 213        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 214        return 0;
 215}
 216
 217static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
 218                                     struct snd_ctl_elem_value *ucontrol)
 219{
 220        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 221        struct aureon_spec *spec = ice->spec;
 222        ucontrol->value.enumerated.item[0] = spec->pca9554_out;
 223        return 0;
 224}
 225
 226static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
 227                                     struct snd_ctl_elem_value *ucontrol)
 228{
 229        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 230        struct aureon_spec *spec = ice->spec;
 231        unsigned char oval, nval;
 232        int change;
 233
 234        nval = ucontrol->value.enumerated.item[0];
 235        if (nval >= 3)
 236                return -EINVAL;
 237        snd_ice1712_save_gpio_status(ice);
 238        oval = spec->pca9554_out;
 239        change = (oval != nval);
 240        if (change) {
 241                aureon_pca9554_write(ice, PCA9554_OUT, nval);
 242                spec->pca9554_out = nval;
 243        }
 244        snd_ice1712_restore_gpio_status(ice);
 245        return change;
 246}
 247
 248
 249static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
 250                              unsigned short val)
 251{
 252        struct aureon_spec *spec = ice->spec;
 253        unsigned int tmp;
 254
 255        /* Send address to XILINX chip */
 256        tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
 257        snd_ice1712_gpio_write(ice, tmp);
 258        udelay(10);
 259        tmp |= AUREON_AC97_ADDR;
 260        snd_ice1712_gpio_write(ice, tmp);
 261        udelay(10);
 262        tmp &= ~AUREON_AC97_ADDR;
 263        snd_ice1712_gpio_write(ice, tmp);
 264        udelay(10);
 265
 266        /* Send low-order byte to XILINX chip */
 267        tmp &= ~AUREON_AC97_DATA_MASK;
 268        tmp |= val & AUREON_AC97_DATA_MASK;
 269        snd_ice1712_gpio_write(ice, tmp);
 270        udelay(10);
 271        tmp |= AUREON_AC97_DATA_LOW;
 272        snd_ice1712_gpio_write(ice, tmp);
 273        udelay(10);
 274        tmp &= ~AUREON_AC97_DATA_LOW;
 275        snd_ice1712_gpio_write(ice, tmp);
 276        udelay(10);
 277
 278        /* Send high-order byte to XILINX chip */
 279        tmp &= ~AUREON_AC97_DATA_MASK;
 280        tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
 281
 282        snd_ice1712_gpio_write(ice, tmp);
 283        udelay(10);
 284        tmp |= AUREON_AC97_DATA_HIGH;
 285        snd_ice1712_gpio_write(ice, tmp);
 286        udelay(10);
 287        tmp &= ~AUREON_AC97_DATA_HIGH;
 288        snd_ice1712_gpio_write(ice, tmp);
 289        udelay(10);
 290
 291        /* Instruct XILINX chip to parse the data to the STAC9744 chip */
 292        tmp |= AUREON_AC97_COMMIT;
 293        snd_ice1712_gpio_write(ice, tmp);
 294        udelay(10);
 295        tmp &= ~AUREON_AC97_COMMIT;
 296        snd_ice1712_gpio_write(ice, tmp);
 297        udelay(10);
 298
 299        /* Store the data in out private buffer */
 300        spec->stac9744[(reg & 0x7F) >> 1] = val;
 301}
 302
 303static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
 304{
 305        struct aureon_spec *spec = ice->spec;
 306        return spec->stac9744[(reg & 0x7F) >> 1];
 307}
 308
 309/*
 310 * Initialize STAC9744 chip
 311 */
 312static int aureon_ac97_init(struct snd_ice1712 *ice)
 313{
 314        struct aureon_spec *spec = ice->spec;
 315        int i;
 316        static const unsigned short ac97_defaults[] = {
 317                0x00, 0x9640,
 318                0x02, 0x8000,
 319                0x04, 0x8000,
 320                0x06, 0x8000,
 321                0x0C, 0x8008,
 322                0x0E, 0x8008,
 323                0x10, 0x8808,
 324                0x12, 0x8808,
 325                0x14, 0x8808,
 326                0x16, 0x8808,
 327                0x18, 0x8808,
 328                0x1C, 0x8000,
 329                0x26, 0x000F,
 330                0x28, 0x0201,
 331                0x2C, 0xBB80,
 332                0x32, 0xBB80,
 333                0x7C, 0x8384,
 334                0x7E, 0x7644,
 335                (unsigned short)-1
 336        };
 337        unsigned int tmp;
 338
 339        /* Cold reset */
 340        tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
 341        snd_ice1712_gpio_write(ice, tmp);
 342        udelay(3);
 343
 344        tmp &= ~AUREON_AC97_RESET;
 345        snd_ice1712_gpio_write(ice, tmp);
 346        udelay(3);
 347
 348        tmp |= AUREON_AC97_RESET;
 349        snd_ice1712_gpio_write(ice, tmp);
 350        udelay(3);
 351
 352        memset(&spec->stac9744, 0, sizeof(spec->stac9744));
 353        for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2)
 354                spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
 355
 356        /* Unmute AC'97 master volume permanently - muting is done by WM8770 */
 357        aureon_ac97_write(ice, AC97_MASTER, 0x0000);
 358
 359        return 0;
 360}
 361
 362#define AUREON_AC97_STEREO      0x80
 363
 364/*
 365 * AC'97 volume controls
 366 */
 367static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 368{
 369        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 370        uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
 371        uinfo->value.integer.min = 0;
 372        uinfo->value.integer.max = 31;
 373        return 0;
 374}
 375
 376static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 377{
 378        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 379        unsigned short vol;
 380
 381        mutex_lock(&ice->gpio_mutex);
 382
 383        vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
 384        ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
 385        if (kcontrol->private_value & AUREON_AC97_STEREO)
 386                ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
 387
 388        mutex_unlock(&ice->gpio_mutex);
 389        return 0;
 390}
 391
 392static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 393{
 394        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 395        unsigned short ovol, nvol;
 396        int change;
 397
 398        snd_ice1712_save_gpio_status(ice);
 399
 400        ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
 401        nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
 402        if (kcontrol->private_value & AUREON_AC97_STEREO)
 403                nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
 404        nvol |= ovol & ~0x1F1F;
 405
 406        change = (ovol != nvol);
 407        if (change)
 408                aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
 409
 410        snd_ice1712_restore_gpio_status(ice);
 411
 412        return change;
 413}
 414
 415/*
 416 * AC'97 mute controls
 417 */
 418#define aureon_ac97_mute_info   snd_ctl_boolean_mono_info
 419
 420static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 421{
 422        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 423
 424        mutex_lock(&ice->gpio_mutex);
 425
 426        ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
 427                        kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
 428
 429        mutex_unlock(&ice->gpio_mutex);
 430        return 0;
 431}
 432
 433static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 434{
 435        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 436        unsigned short ovol, nvol;
 437        int change;
 438
 439        snd_ice1712_save_gpio_status(ice);
 440
 441        ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
 442        nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
 443
 444        change = (ovol != nvol);
 445        if (change)
 446                aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
 447
 448        snd_ice1712_restore_gpio_status(ice);
 449
 450        return change;
 451}
 452
 453/*
 454 * AC'97 mute controls
 455 */
 456#define aureon_ac97_micboost_info       snd_ctl_boolean_mono_info
 457
 458static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 459{
 460        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 461
 462        mutex_lock(&ice->gpio_mutex);
 463
 464        ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
 465
 466        mutex_unlock(&ice->gpio_mutex);
 467        return 0;
 468}
 469
 470static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 471{
 472        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 473        unsigned short ovol, nvol;
 474        int change;
 475
 476        snd_ice1712_save_gpio_status(ice);
 477
 478        ovol = aureon_ac97_read(ice, AC97_MIC);
 479        nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
 480
 481        change = (ovol != nvol);
 482        if (change)
 483                aureon_ac97_write(ice, AC97_MIC, nvol);
 484
 485        snd_ice1712_restore_gpio_status(ice);
 486
 487        return change;
 488}
 489
 490/*
 491 * write data in the SPI mode
 492 */
 493static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
 494{
 495        unsigned int tmp;
 496        int i;
 497        unsigned int mosi, clk;
 498
 499        tmp = snd_ice1712_gpio_read(ice);
 500
 501        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
 502            ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
 503                snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
 504                mosi = PRODIGY_SPI_MOSI;
 505                clk = PRODIGY_SPI_CLK;
 506        } else {
 507                snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
 508                                                 AUREON_WM_CS|AUREON_CS8415_CS));
 509                mosi = AUREON_SPI_MOSI;
 510                clk = AUREON_SPI_CLK;
 511
 512                tmp |= AUREON_WM_RW;
 513        }
 514
 515        tmp &= ~cs;
 516        snd_ice1712_gpio_write(ice, tmp);
 517        udelay(1);
 518
 519        for (i = bits - 1; i >= 0; i--) {
 520                tmp &= ~clk;
 521                snd_ice1712_gpio_write(ice, tmp);
 522                udelay(1);
 523                if (data & (1 << i))
 524                        tmp |= mosi;
 525                else
 526                        tmp &= ~mosi;
 527                snd_ice1712_gpio_write(ice, tmp);
 528                udelay(1);
 529                tmp |= clk;
 530                snd_ice1712_gpio_write(ice, tmp);
 531                udelay(1);
 532        }
 533
 534        tmp &= ~clk;
 535        tmp |= cs;
 536        snd_ice1712_gpio_write(ice, tmp);
 537        udelay(1);
 538        tmp |= clk;
 539        snd_ice1712_gpio_write(ice, tmp);
 540        udelay(1);
 541}
 542
 543/*
 544 * Read data in SPI mode
 545 */
 546static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
 547                unsigned int data, int bits, unsigned char *buffer, int size)
 548{
 549        int i, j;
 550        unsigned int tmp;
 551
 552        tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
 553        snd_ice1712_gpio_write(ice, tmp);
 554        tmp &= ~cs;
 555        snd_ice1712_gpio_write(ice, tmp);
 556        udelay(1);
 557
 558        for (i = bits-1; i >= 0; i--) {
 559                if (data & (1 << i))
 560                        tmp |= AUREON_SPI_MOSI;
 561                else
 562                        tmp &= ~AUREON_SPI_MOSI;
 563                snd_ice1712_gpio_write(ice, tmp);
 564                udelay(1);
 565
 566                tmp |= AUREON_SPI_CLK;
 567                snd_ice1712_gpio_write(ice, tmp);
 568                udelay(1);
 569
 570                tmp &= ~AUREON_SPI_CLK;
 571                snd_ice1712_gpio_write(ice, tmp);
 572                udelay(1);
 573        }
 574
 575        for (j = 0; j < size; j++) {
 576                unsigned char outdata = 0;
 577                for (i = 7; i >= 0; i--) {
 578                        tmp = snd_ice1712_gpio_read(ice);
 579                        outdata <<= 1;
 580                        outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
 581                        udelay(1);
 582
 583                        tmp |= AUREON_SPI_CLK;
 584                        snd_ice1712_gpio_write(ice, tmp);
 585                        udelay(1);
 586
 587                        tmp &= ~AUREON_SPI_CLK;
 588                        snd_ice1712_gpio_write(ice, tmp);
 589                        udelay(1);
 590                }
 591                buffer[j] = outdata;
 592        }
 593
 594        tmp |= cs;
 595        snd_ice1712_gpio_write(ice, tmp);
 596}
 597
 598static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
 599{
 600        unsigned char val;
 601        aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
 602        aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
 603        return val;
 604}
 605
 606static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
 607                                unsigned char *buffer, int size)
 608{
 609        aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
 610        aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
 611}
 612
 613static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
 614                                                unsigned char val)
 615{
 616        aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
 617}
 618
 619/*
 620 * get the current register value of WM codec
 621 */
 622static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
 623{
 624        reg <<= 1;
 625        return ((unsigned short)ice->akm[0].images[reg] << 8) |
 626                ice->akm[0].images[reg + 1];
 627}
 628
 629/*
 630 * set the register value of WM codec
 631 */
 632static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
 633{
 634        aureon_spi_write(ice,
 635                         ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
 636                           ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
 637                         PRODIGY_WM_CS : AUREON_WM_CS),
 638                        (reg << 9) | (val & 0x1ff), 16);
 639}
 640
 641/*
 642 * set the register value of WM codec and remember it
 643 */
 644static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
 645{
 646        wm_put_nocache(ice, reg, val);
 647        reg <<= 1;
 648        ice->akm[0].images[reg] = val >> 8;
 649        ice->akm[0].images[reg + 1] = val;
 650}
 651
 652/*
 653 */
 654#define aureon_mono_bool_info           snd_ctl_boolean_mono_info
 655
 656/*
 657 * AC'97 master playback mute controls (Mute on WM8770 chip)
 658 */
 659#define aureon_ac97_mmute_info          snd_ctl_boolean_mono_info
 660
 661static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 662{
 663        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 664
 665        mutex_lock(&ice->gpio_mutex);
 666
 667        ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
 668
 669        mutex_unlock(&ice->gpio_mutex);
 670        return 0;
 671}
 672
 673static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 674{
 675        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 676        unsigned short ovol, nvol;
 677        int change;
 678
 679        snd_ice1712_save_gpio_status(ice);
 680
 681        ovol = wm_get(ice, WM_OUT_MUX1);
 682        nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
 683        change = (ovol != nvol);
 684        if (change)
 685                wm_put(ice, WM_OUT_MUX1, nvol);
 686
 687        snd_ice1712_restore_gpio_status(ice);
 688
 689        return change;
 690}
 691
 692static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 693static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 694static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
 695static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
 696static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
 697
 698/*
 699 * Logarithmic volume values for WM8770
 700 * Computed as 20 * Log10(255 / x)
 701 */
 702static const unsigned char wm_vol[256] = {
 703        127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
 704        23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
 705        17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
 706        13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
 707        11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
 708        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
 709        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 710        5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
 711        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 712        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 713        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 714        0, 0
 715};
 716
 717#define WM_VOL_MAX      (sizeof(wm_vol) - 1)
 718#define WM_VOL_MUTE     0x8000
 719
 720static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
 721{
 722        unsigned char nvol;
 723
 724        if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
 725                nvol = 0;
 726        else
 727                nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
 728
 729        wm_put(ice, index, nvol);
 730        wm_put_nocache(ice, index, 0x180 | nvol);
 731}
 732
 733/*
 734 * DAC mute control
 735 */
 736#define wm_pcm_mute_info        snd_ctl_boolean_mono_info
 737
 738static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 739{
 740        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 741
 742        mutex_lock(&ice->gpio_mutex);
 743        ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
 744        mutex_unlock(&ice->gpio_mutex);
 745        return 0;
 746}
 747
 748static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 749{
 750        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 751        unsigned short nval, oval;
 752        int change;
 753
 754        snd_ice1712_save_gpio_status(ice);
 755        oval = wm_get(ice, WM_MUTE);
 756        nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
 757        change = (oval != nval);
 758        if (change)
 759                wm_put(ice, WM_MUTE, nval);
 760        snd_ice1712_restore_gpio_status(ice);
 761
 762        return change;
 763}
 764
 765/*
 766 * Master volume attenuation mixer control
 767 */
 768static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 769{
 770        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 771        uinfo->count = 2;
 772        uinfo->value.integer.min = 0;
 773        uinfo->value.integer.max = WM_VOL_MAX;
 774        return 0;
 775}
 776
 777static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 778{
 779        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 780        struct aureon_spec *spec = ice->spec;
 781        int i;
 782        for (i = 0; i < 2; i++)
 783                ucontrol->value.integer.value[i] =
 784                        spec->master[i] & ~WM_VOL_MUTE;
 785        return 0;
 786}
 787
 788static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 789{
 790        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 791        struct aureon_spec *spec = ice->spec;
 792        int ch, change = 0;
 793
 794        snd_ice1712_save_gpio_status(ice);
 795        for (ch = 0; ch < 2; ch++) {
 796                unsigned int vol = ucontrol->value.integer.value[ch];
 797                if (vol > WM_VOL_MAX)
 798                        continue;
 799                vol |= spec->master[ch] & WM_VOL_MUTE;
 800                if (vol != spec->master[ch]) {
 801                        int dac;
 802                        spec->master[ch] = vol;
 803                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 804                                wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
 805                                           spec->vol[dac + ch],
 806                                           spec->master[ch]);
 807                        change = 1;
 808                }
 809        }
 810        snd_ice1712_restore_gpio_status(ice);
 811        return change;
 812}
 813
 814/*
 815 * DAC volume attenuation mixer control
 816 */
 817static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 818{
 819        int voices = kcontrol->private_value >> 8;
 820        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 821        uinfo->count = voices;
 822        uinfo->value.integer.min = 0;           /* mute (-101dB) */
 823        uinfo->value.integer.max = 0x7F;        /* 0dB */
 824        return 0;
 825}
 826
 827static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 828{
 829        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 830        struct aureon_spec *spec = ice->spec;
 831        int i, ofs, voices;
 832
 833        voices = kcontrol->private_value >> 8;
 834        ofs = kcontrol->private_value & 0xff;
 835        for (i = 0; i < voices; i++)
 836                ucontrol->value.integer.value[i] =
 837                        spec->vol[ofs+i] & ~WM_VOL_MUTE;
 838        return 0;
 839}
 840
 841static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 842{
 843        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 844        struct aureon_spec *spec = ice->spec;
 845        int i, idx, ofs, voices;
 846        int change = 0;
 847
 848        voices = kcontrol->private_value >> 8;
 849        ofs = kcontrol->private_value & 0xff;
 850        snd_ice1712_save_gpio_status(ice);
 851        for (i = 0; i < voices; i++) {
 852                unsigned int vol = ucontrol->value.integer.value[i];
 853                if (vol > 0x7f)
 854                        continue;
 855                vol |= spec->vol[ofs+i];
 856                if (vol != spec->vol[ofs+i]) {
 857                        spec->vol[ofs+i] = vol;
 858                        idx  = WM_DAC_ATTEN + ofs + i;
 859                        wm_set_vol(ice, idx, spec->vol[ofs + i],
 860                                   spec->master[i]);
 861                        change = 1;
 862                }
 863        }
 864        snd_ice1712_restore_gpio_status(ice);
 865        return change;
 866}
 867
 868/*
 869 * WM8770 mute control
 870 */
 871static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 872{
 873        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 874        uinfo->count = kcontrol->private_value >> 8;
 875        uinfo->value.integer.min = 0;
 876        uinfo->value.integer.max = 1;
 877        return 0;
 878}
 879
 880static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 881{
 882        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 883        struct aureon_spec *spec = ice->spec;
 884        int voices, ofs, i;
 885
 886        voices = kcontrol->private_value >> 8;
 887        ofs = kcontrol->private_value & 0xFF;
 888
 889        for (i = 0; i < voices; i++)
 890                ucontrol->value.integer.value[i] =
 891                        (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
 892        return 0;
 893}
 894
 895static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 896{
 897        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 898        struct aureon_spec *spec = ice->spec;
 899        int change = 0, voices, ofs, i;
 900
 901        voices = kcontrol->private_value >> 8;
 902        ofs = kcontrol->private_value & 0xFF;
 903
 904        snd_ice1712_save_gpio_status(ice);
 905        for (i = 0; i < voices; i++) {
 906                int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
 907                if (ucontrol->value.integer.value[i] != val) {
 908                        spec->vol[ofs + i] &= ~WM_VOL_MUTE;
 909                        spec->vol[ofs + i] |=
 910                                ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
 911                        wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
 912                                   spec->master[i]);
 913                        change = 1;
 914                }
 915        }
 916        snd_ice1712_restore_gpio_status(ice);
 917
 918        return change;
 919}
 920
 921/*
 922 * WM8770 master mute control
 923 */
 924#define wm_master_mute_info             snd_ctl_boolean_stereo_info
 925
 926static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 927{
 928        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 929        struct aureon_spec *spec = ice->spec;
 930
 931        ucontrol->value.integer.value[0] =
 932                (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
 933        ucontrol->value.integer.value[1] =
 934                (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
 935        return 0;
 936}
 937
 938static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 939{
 940        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 941        struct aureon_spec *spec = ice->spec;
 942        int change = 0, i;
 943
 944        snd_ice1712_save_gpio_status(ice);
 945        for (i = 0; i < 2; i++) {
 946                int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
 947                if (ucontrol->value.integer.value[i] != val) {
 948                        int dac;
 949                        spec->master[i] &= ~WM_VOL_MUTE;
 950                        spec->master[i] |=
 951                                ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
 952                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 953                                wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
 954                                           spec->vol[dac + i],
 955                                           spec->master[i]);
 956                        change = 1;
 957                }
 958        }
 959        snd_ice1712_restore_gpio_status(ice);
 960
 961        return change;
 962}
 963
 964/* digital master volume */
 965#define PCM_0dB 0xff
 966#define PCM_RES 128     /* -64dB */
 967#define PCM_MIN (PCM_0dB - PCM_RES)
 968static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 969{
 970        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 971        uinfo->count = 1;
 972        uinfo->value.integer.min = 0;           /* mute (-64dB) */
 973        uinfo->value.integer.max = PCM_RES;     /* 0dB */
 974        return 0;
 975}
 976
 977static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 978{
 979        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 980        unsigned short val;
 981
 982        mutex_lock(&ice->gpio_mutex);
 983        val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 984        val = val > PCM_MIN ? (val - PCM_MIN) : 0;
 985        ucontrol->value.integer.value[0] = val;
 986        mutex_unlock(&ice->gpio_mutex);
 987        return 0;
 988}
 989
 990static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 991{
 992        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 993        unsigned short ovol, nvol;
 994        int change = 0;
 995
 996        nvol = ucontrol->value.integer.value[0];
 997        if (nvol > PCM_RES)
 998                return -EINVAL;
 999        snd_ice1712_save_gpio_status(ice);
1000        nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
1001        ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
1002        if (ovol != nvol) {
1003                wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
1004                wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
1005                change = 1;
1006        }
1007        snd_ice1712_restore_gpio_status(ice);
1008        return change;
1009}
1010
1011/*
1012 * ADC mute control
1013 */
1014#define wm_adc_mute_info                snd_ctl_boolean_stereo_info
1015
1016static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1017{
1018        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1019        unsigned short val;
1020        int i;
1021
1022        mutex_lock(&ice->gpio_mutex);
1023        for (i = 0; i < 2; i++) {
1024                val = wm_get(ice, WM_ADC_GAIN + i);
1025                ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1026        }
1027        mutex_unlock(&ice->gpio_mutex);
1028        return 0;
1029}
1030
1031static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1032{
1033        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1034        unsigned short new, old;
1035        int i, change = 0;
1036
1037        snd_ice1712_save_gpio_status(ice);
1038        for (i = 0; i < 2; i++) {
1039                old = wm_get(ice, WM_ADC_GAIN + i);
1040                new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1041                if (new != old) {
1042                        wm_put(ice, WM_ADC_GAIN + i, new);
1043                        change = 1;
1044                }
1045        }
1046        snd_ice1712_restore_gpio_status(ice);
1047
1048        return change;
1049}
1050
1051/*
1052 * ADC gain mixer control
1053 */
1054static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1055{
1056        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1057        uinfo->count = 2;
1058        uinfo->value.integer.min = 0;           /* -12dB */
1059        uinfo->value.integer.max = 0x1f;        /* 19dB */
1060        return 0;
1061}
1062
1063static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1064{
1065        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1066        int i, idx;
1067        unsigned short vol;
1068
1069        mutex_lock(&ice->gpio_mutex);
1070        for (i = 0; i < 2; i++) {
1071                idx = WM_ADC_GAIN + i;
1072                vol = wm_get(ice, idx) & 0x1f;
1073                ucontrol->value.integer.value[i] = vol;
1074        }
1075        mutex_unlock(&ice->gpio_mutex);
1076        return 0;
1077}
1078
1079static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1080{
1081        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1082        int i, idx;
1083        unsigned short ovol, nvol;
1084        int change = 0;
1085
1086        snd_ice1712_save_gpio_status(ice);
1087        for (i = 0; i < 2; i++) {
1088                idx  = WM_ADC_GAIN + i;
1089                nvol = ucontrol->value.integer.value[i] & 0x1f;
1090                ovol = wm_get(ice, idx);
1091                if ((ovol & 0x1f) != nvol) {
1092                        wm_put(ice, idx, nvol | (ovol & ~0x1f));
1093                        change = 1;
1094                }
1095        }
1096        snd_ice1712_restore_gpio_status(ice);
1097        return change;
1098}
1099
1100/*
1101 * ADC input mux mixer control
1102 */
1103static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1104{
1105        static const char * const texts[] = {
1106                "CD",           /* AIN1 */
1107                "Aux",          /* AIN2 */
1108                "Line",         /* AIN3 */
1109                "Mic",          /* AIN4 */
1110                "AC97"          /* AIN5 */
1111        };
1112        static const char * const universe_texts[] = {
1113                "Aux1",         /* AIN1 */
1114                "CD",           /* AIN2 */
1115                "Phono",        /* AIN3 */
1116                "Line",         /* AIN4 */
1117                "Aux2",         /* AIN5 */
1118                "Mic",          /* AIN6 */
1119                "Aux3",         /* AIN7 */
1120                "AC97"          /* AIN8 */
1121        };
1122        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1123
1124        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1125        uinfo->count = 2;
1126        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1127                uinfo->value.enumerated.items = 8;
1128                if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1129                        uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1130                strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1131        } else {
1132                uinfo->value.enumerated.items = 5;
1133                if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1134                        uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1135                strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1136        }
1137        return 0;
1138}
1139
1140static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1141{
1142        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1143        unsigned short val;
1144
1145        mutex_lock(&ice->gpio_mutex);
1146        val = wm_get(ice, WM_ADC_MUX);
1147        ucontrol->value.enumerated.item[0] = val & 7;
1148        ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1149        mutex_unlock(&ice->gpio_mutex);
1150        return 0;
1151}
1152
1153static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1154{
1155        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1156        unsigned short oval, nval;
1157        int change;
1158
1159        snd_ice1712_save_gpio_status(ice);
1160        oval = wm_get(ice, WM_ADC_MUX);
1161        nval = oval & ~0x77;
1162        nval |= ucontrol->value.enumerated.item[0] & 7;
1163        nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1164        change = (oval != nval);
1165        if (change)
1166                wm_put(ice, WM_ADC_MUX, nval);
1167        snd_ice1712_restore_gpio_status(ice);
1168        return change;
1169}
1170
1171/*
1172 * CS8415 Input mux
1173 */
1174static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1175{
1176        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1177        static const char * const aureon_texts[] = {
1178                "CD",           /* RXP0 */
1179                "Optical"       /* RXP1 */
1180        };
1181        static const char * const prodigy_texts[] = {
1182                "CD",
1183                "Coax"
1184        };
1185        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1186        uinfo->count = 1;
1187        uinfo->value.enumerated.items = 2;
1188        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1189                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1190        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1191                strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1192        else
1193                strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1194        return 0;
1195}
1196
1197static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1198{
1199        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1200        struct aureon_spec *spec = ice->spec;
1201
1202        /* snd_ice1712_save_gpio_status(ice); */
1203        /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
1204        ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1205        /* snd_ice1712_restore_gpio_status(ice); */
1206        return 0;
1207}
1208
1209static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1210{
1211        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212        struct aureon_spec *spec = ice->spec;
1213        unsigned short oval, nval;
1214        int change;
1215
1216        snd_ice1712_save_gpio_status(ice);
1217        oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1218        nval = oval & ~0x07;
1219        nval |= ucontrol->value.enumerated.item[0] & 7;
1220        change = (oval != nval);
1221        if (change)
1222                aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1223        snd_ice1712_restore_gpio_status(ice);
1224        spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1225        return change;
1226}
1227
1228static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1229{
1230        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1231        uinfo->count = 1;
1232        uinfo->value.integer.min = 0;
1233        uinfo->value.integer.max = 192000;
1234        return 0;
1235}
1236
1237static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1238{
1239        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240        unsigned char ratio;
1241        ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1242        ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1243        return 0;
1244}
1245
1246/*
1247 * CS8415A Mute
1248 */
1249#define aureon_cs8415_mute_info         snd_ctl_boolean_mono_info
1250
1251static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1252{
1253        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1254        snd_ice1712_save_gpio_status(ice);
1255        ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1256        snd_ice1712_restore_gpio_status(ice);
1257        return 0;
1258}
1259
1260static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1261{
1262        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1263        unsigned char oval, nval;
1264        int change;
1265        snd_ice1712_save_gpio_status(ice);
1266        oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1267        if (ucontrol->value.integer.value[0])
1268                nval = oval & ~0x20;
1269        else
1270                nval = oval | 0x20;
1271        change = (oval != nval);
1272        if (change)
1273                aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1274        snd_ice1712_restore_gpio_status(ice);
1275        return change;
1276}
1277
1278/*
1279 * CS8415A Q-Sub info
1280 */
1281static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1282{
1283        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1284        uinfo->count = 10;
1285        return 0;
1286}
1287
1288static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1289{
1290        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1291
1292        snd_ice1712_save_gpio_status(ice);
1293        aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1294        snd_ice1712_restore_gpio_status(ice);
1295
1296        return 0;
1297}
1298
1299static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1300{
1301        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1302        uinfo->count = 1;
1303        return 0;
1304}
1305
1306static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1307{
1308        memset(ucontrol->value.iec958.status, 0xFF, 24);
1309        return 0;
1310}
1311
1312static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1313{
1314        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1315
1316        snd_ice1712_save_gpio_status(ice);
1317        aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1318        snd_ice1712_restore_gpio_status(ice);
1319        return 0;
1320}
1321
1322/*
1323 * Headphone Amplifier
1324 */
1325static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1326{
1327        unsigned int tmp, tmp2;
1328
1329        tmp2 = tmp = snd_ice1712_gpio_read(ice);
1330        if (enable)
1331                if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1332                    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1333                        tmp |= AUREON_HP_SEL;
1334                else
1335                        tmp |= PRODIGY_HP_SEL;
1336        else
1337                if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1338                    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1339                        tmp &= ~AUREON_HP_SEL;
1340                else
1341                        tmp &= ~PRODIGY_HP_SEL;
1342        if (tmp != tmp2) {
1343                snd_ice1712_gpio_write(ice, tmp);
1344                return 1;
1345        }
1346        return 0;
1347}
1348
1349static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1350{
1351        unsigned int tmp = snd_ice1712_gpio_read(ice);
1352
1353        return (tmp & AUREON_HP_SEL) != 0;
1354}
1355
1356#define aureon_hpamp_info       snd_ctl_boolean_mono_info
1357
1358static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1359{
1360        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1361
1362        ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1363        return 0;
1364}
1365
1366
1367static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1368{
1369        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1370
1371        return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1372}
1373
1374/*
1375 * Deemphasis
1376 */
1377
1378#define aureon_deemp_info       snd_ctl_boolean_mono_info
1379
1380static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1381{
1382        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1383        ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1384        return 0;
1385}
1386
1387static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1388{
1389        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1390        int temp, temp2;
1391        temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1392        if (ucontrol->value.integer.value[0])
1393                temp |= 0xf;
1394        else
1395                temp &= ~0xf;
1396        if (temp != temp2) {
1397                wm_put(ice, WM_DAC_CTRL2, temp);
1398                return 1;
1399        }
1400        return 0;
1401}
1402
1403/*
1404 * ADC Oversampling
1405 */
1406static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1407{
1408        static const char * const texts[2] = { "128x", "64x"    };
1409
1410        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1411        uinfo->count = 1;
1412        uinfo->value.enumerated.items = 2;
1413
1414        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1415                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1416        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1417
1418        return 0;
1419}
1420
1421static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1422{
1423        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1424        ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1425        return 0;
1426}
1427
1428static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1429{
1430        int temp, temp2;
1431        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1432
1433        temp2 = temp = wm_get(ice, WM_MASTER);
1434
1435        if (ucontrol->value.enumerated.item[0])
1436                temp |= 0x8;
1437        else
1438                temp &= ~0x8;
1439
1440        if (temp != temp2) {
1441                wm_put(ice, WM_MASTER, temp);
1442                return 1;
1443        }
1444        return 0;
1445}
1446
1447/*
1448 * mixers
1449 */
1450
1451static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1452        {
1453                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454                .name = "Master Playback Switch",
1455                .info = wm_master_mute_info,
1456                .get = wm_master_mute_get,
1457                .put = wm_master_mute_put
1458        },
1459        {
1460                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1461                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1462                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1463                .name = "Master Playback Volume",
1464                .info = wm_master_vol_info,
1465                .get = wm_master_vol_get,
1466                .put = wm_master_vol_put,
1467                .tlv = { .p = db_scale_wm_dac }
1468        },
1469        {
1470                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1471                .name = "Front Playback Switch",
1472                .info = wm_mute_info,
1473                .get = wm_mute_get,
1474                .put = wm_mute_put,
1475                .private_value = (2 << 8) | 0
1476        },
1477        {
1478                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1479                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1480                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1481                .name = "Front Playback Volume",
1482                .info = wm_vol_info,
1483                .get = wm_vol_get,
1484                .put = wm_vol_put,
1485                .private_value = (2 << 8) | 0,
1486                .tlv = { .p = db_scale_wm_dac }
1487        },
1488        {
1489                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1490                .name = "Rear Playback Switch",
1491                .info = wm_mute_info,
1492                .get = wm_mute_get,
1493                .put = wm_mute_put,
1494                .private_value = (2 << 8) | 2
1495        },
1496        {
1497                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1498                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1499                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1500                .name = "Rear Playback Volume",
1501                .info = wm_vol_info,
1502                .get = wm_vol_get,
1503                .put = wm_vol_put,
1504                .private_value = (2 << 8) | 2,
1505                .tlv = { .p = db_scale_wm_dac }
1506        },
1507        {
1508                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509                .name = "Center Playback Switch",
1510                .info = wm_mute_info,
1511                .get = wm_mute_get,
1512                .put = wm_mute_put,
1513                .private_value = (1 << 8) | 4
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 = "Center Playback Volume",
1520                .info = wm_vol_info,
1521                .get = wm_vol_get,
1522                .put = wm_vol_put,
1523                .private_value = (1 << 8) | 4,
1524                .tlv = { .p = db_scale_wm_dac }
1525        },
1526        {
1527                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1528                .name = "LFE Playback Switch",
1529                .info = wm_mute_info,
1530                .get = wm_mute_get,
1531                .put = wm_mute_put,
1532                .private_value = (1 << 8) | 5
1533        },
1534        {
1535                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1536                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1537                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1538                .name = "LFE Playback Volume",
1539                .info = wm_vol_info,
1540                .get = wm_vol_get,
1541                .put = wm_vol_put,
1542                .private_value = (1 << 8) | 5,
1543                .tlv = { .p = db_scale_wm_dac }
1544        },
1545        {
1546                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1547                .name = "Side Playback Switch",
1548                .info = wm_mute_info,
1549                .get = wm_mute_get,
1550                .put = wm_mute_put,
1551                .private_value = (2 << 8) | 6
1552        },
1553        {
1554                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1555                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1556                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1557                .name = "Side Playback Volume",
1558                .info = wm_vol_info,
1559                .get = wm_vol_get,
1560                .put = wm_vol_put,
1561                .private_value = (2 << 8) | 6,
1562                .tlv = { .p = db_scale_wm_dac }
1563        }
1564};
1565
1566static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1567        {
1568                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1569                .name = "PCM Playback Switch",
1570                .info = wm_pcm_mute_info,
1571                .get = wm_pcm_mute_get,
1572                .put = wm_pcm_mute_put
1573        },
1574        {
1575                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1577                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1578                .name = "PCM Playback Volume",
1579                .info = wm_pcm_vol_info,
1580                .get = wm_pcm_vol_get,
1581                .put = wm_pcm_vol_put,
1582                .tlv = { .p = db_scale_wm_pcm }
1583        },
1584        {
1585                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586                .name = "Capture Switch",
1587                .info = wm_adc_mute_info,
1588                .get = wm_adc_mute_get,
1589                .put = wm_adc_mute_put,
1590        },
1591        {
1592                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1594                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1595                .name = "Capture Volume",
1596                .info = wm_adc_vol_info,
1597                .get = wm_adc_vol_get,
1598                .put = wm_adc_vol_put,
1599                .tlv = { .p = db_scale_wm_adc }
1600        },
1601        {
1602                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603                .name = "Capture Source",
1604                .info = wm_adc_mux_info,
1605                .get = wm_adc_mux_get,
1606                .put = wm_adc_mux_put,
1607                .private_value = 5
1608        },
1609        {
1610                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1611                .name = "External Amplifier",
1612                .info = aureon_hpamp_info,
1613                .get = aureon_hpamp_get,
1614                .put = aureon_hpamp_put
1615        },
1616        {
1617                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618                .name = "DAC Deemphasis Switch",
1619                .info = aureon_deemp_info,
1620                .get = aureon_deemp_get,
1621                .put = aureon_deemp_put
1622        },
1623        {
1624                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1625                .name = "ADC Oversampling",
1626                .info = aureon_oversampling_info,
1627                .get = aureon_oversampling_get,
1628                .put = aureon_oversampling_put
1629        }
1630};
1631
1632static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1633        {
1634                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1635                .name = "AC97 Playback Switch",
1636                .info = aureon_ac97_mmute_info,
1637                .get = aureon_ac97_mmute_get,
1638                .put = aureon_ac97_mmute_put,
1639                .private_value = AC97_MASTER
1640        },
1641        {
1642                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1643                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1644                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1645                .name = "AC97 Playback Volume",
1646                .info = aureon_ac97_vol_info,
1647                .get = aureon_ac97_vol_get,
1648                .put = aureon_ac97_vol_put,
1649                .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1650                .tlv = { .p = db_scale_ac97_master }
1651        },
1652        {
1653                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1654                .name = "CD Playback Switch",
1655                .info = aureon_ac97_mute_info,
1656                .get = aureon_ac97_mute_get,
1657                .put = aureon_ac97_mute_put,
1658                .private_value = AC97_CD
1659        },
1660        {
1661                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1662                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1663                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1664                .name = "CD Playback Volume",
1665                .info = aureon_ac97_vol_info,
1666                .get = aureon_ac97_vol_get,
1667                .put = aureon_ac97_vol_put,
1668                .private_value = AC97_CD|AUREON_AC97_STEREO,
1669                .tlv = { .p = db_scale_ac97_gain }
1670        },
1671        {
1672                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1673                .name = "Aux Playback Switch",
1674                .info = aureon_ac97_mute_info,
1675                .get = aureon_ac97_mute_get,
1676                .put = aureon_ac97_mute_put,
1677                .private_value = AC97_AUX,
1678        },
1679        {
1680                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1682                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1683                .name = "Aux Playback Volume",
1684                .info = aureon_ac97_vol_info,
1685                .get = aureon_ac97_vol_get,
1686                .put = aureon_ac97_vol_put,
1687                .private_value = AC97_AUX|AUREON_AC97_STEREO,
1688                .tlv = { .p = db_scale_ac97_gain }
1689        },
1690        {
1691                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1692                .name = "Line Playback Switch",
1693                .info = aureon_ac97_mute_info,
1694                .get = aureon_ac97_mute_get,
1695                .put = aureon_ac97_mute_put,
1696                .private_value = AC97_LINE
1697        },
1698        {
1699                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1701                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1702                .name = "Line Playback Volume",
1703                .info = aureon_ac97_vol_info,
1704                .get = aureon_ac97_vol_get,
1705                .put = aureon_ac97_vol_put,
1706                .private_value = AC97_LINE|AUREON_AC97_STEREO,
1707                .tlv = { .p = db_scale_ac97_gain }
1708        },
1709        {
1710                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1711                .name = "Mic Playback Switch",
1712                .info = aureon_ac97_mute_info,
1713                .get = aureon_ac97_mute_get,
1714                .put = aureon_ac97_mute_put,
1715                .private_value = AC97_MIC
1716        },
1717        {
1718                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1720                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1721                .name = "Mic Playback Volume",
1722                .info = aureon_ac97_vol_info,
1723                .get = aureon_ac97_vol_get,
1724                .put = aureon_ac97_vol_put,
1725                .private_value = AC97_MIC,
1726                .tlv = { .p = db_scale_ac97_gain }
1727        },
1728        {
1729                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730                .name = "Mic Boost (+20dB)",
1731                .info = aureon_ac97_micboost_info,
1732                .get = aureon_ac97_micboost_get,
1733                .put = aureon_ac97_micboost_put
1734        }
1735};
1736
1737static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1738        {
1739                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1740                .name = "AC97 Playback Switch",
1741                .info = aureon_ac97_mmute_info,
1742                .get = aureon_ac97_mmute_get,
1743                .put = aureon_ac97_mmute_put,
1744                .private_value = AC97_MASTER
1745        },
1746        {
1747                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1748                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1749                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1750                .name = "AC97 Playback Volume",
1751                .info = aureon_ac97_vol_info,
1752                .get = aureon_ac97_vol_get,
1753                .put = aureon_ac97_vol_put,
1754                .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1755                .tlv = { .p = db_scale_ac97_master }
1756        },
1757        {
1758                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1759                .name = "CD Playback Switch",
1760                .info = aureon_ac97_mute_info,
1761                .get = aureon_ac97_mute_get,
1762                .put = aureon_ac97_mute_put,
1763                .private_value = AC97_AUX
1764        },
1765        {
1766                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1767                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1768                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1769                .name = "CD Playback Volume",
1770                .info = aureon_ac97_vol_info,
1771                .get = aureon_ac97_vol_get,
1772                .put = aureon_ac97_vol_put,
1773                .private_value = AC97_AUX|AUREON_AC97_STEREO,
1774                .tlv = { .p = db_scale_ac97_gain }
1775        },
1776        {
1777                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1778                .name = "Phono Playback Switch",
1779                .info = aureon_ac97_mute_info,
1780                .get = aureon_ac97_mute_get,
1781                .put = aureon_ac97_mute_put,
1782                .private_value = AC97_CD
1783        },
1784        {
1785                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1786                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1787                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1788                .name = "Phono Playback Volume",
1789                .info = aureon_ac97_vol_info,
1790                .get = aureon_ac97_vol_get,
1791                .put = aureon_ac97_vol_put,
1792                .private_value = AC97_CD|AUREON_AC97_STEREO,
1793                .tlv = { .p = db_scale_ac97_gain }
1794        },
1795        {
1796                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1797                .name = "Line Playback Switch",
1798                .info = aureon_ac97_mute_info,
1799                .get = aureon_ac97_mute_get,
1800                .put = aureon_ac97_mute_put,
1801                .private_value = AC97_LINE
1802        },
1803        {
1804                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1805                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1806                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1807                .name = "Line Playback Volume",
1808                .info = aureon_ac97_vol_info,
1809                .get = aureon_ac97_vol_get,
1810                .put = aureon_ac97_vol_put,
1811                .private_value = AC97_LINE|AUREON_AC97_STEREO,
1812                .tlv = { .p = db_scale_ac97_gain }
1813        },
1814        {
1815                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1816                .name = "Mic Playback Switch",
1817                .info = aureon_ac97_mute_info,
1818                .get = aureon_ac97_mute_get,
1819                .put = aureon_ac97_mute_put,
1820                .private_value = AC97_MIC
1821        },
1822        {
1823                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1824                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1825                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1826                .name = "Mic Playback Volume",
1827                .info = aureon_ac97_vol_info,
1828                .get = aureon_ac97_vol_get,
1829                .put = aureon_ac97_vol_put,
1830                .private_value = AC97_MIC,
1831                .tlv = { .p = db_scale_ac97_gain }
1832        },
1833        {
1834                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1835                .name = "Mic Boost (+20dB)",
1836                .info = aureon_ac97_micboost_info,
1837                .get = aureon_ac97_micboost_get,
1838                .put = aureon_ac97_micboost_put
1839        },
1840        {
1841                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1842                .name = "Aux Playback Switch",
1843                .info = aureon_ac97_mute_info,
1844                .get = aureon_ac97_mute_get,
1845                .put = aureon_ac97_mute_put,
1846                .private_value = AC97_VIDEO,
1847        },
1848        {
1849                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1850                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1851                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1852                .name = "Aux Playback Volume",
1853                .info = aureon_ac97_vol_info,
1854                .get = aureon_ac97_vol_get,
1855                .put = aureon_ac97_vol_put,
1856                .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1857                .tlv = { .p = db_scale_ac97_gain }
1858        },
1859        {
1860                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1861                .name = "Aux Source",
1862                .info = aureon_universe_inmux_info,
1863                .get = aureon_universe_inmux_get,
1864                .put = aureon_universe_inmux_put
1865        }
1866
1867};
1868
1869static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1870        {
1871                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1872                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1873                .info = aureon_cs8415_mute_info,
1874                .get = aureon_cs8415_mute_get,
1875                .put = aureon_cs8415_mute_put
1876        },
1877        {
1878                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1879                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1880                .info = aureon_cs8415_mux_info,
1881                .get = aureon_cs8415_mux_get,
1882                .put = aureon_cs8415_mux_put,
1883        },
1884        {
1885                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1886                .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1887                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1888                .info = aureon_cs8415_qsub_info,
1889                .get = aureon_cs8415_qsub_get,
1890        },
1891        {
1892                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1893                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1894                .access = SNDRV_CTL_ELEM_ACCESS_READ,
1895                .info = aureon_cs8415_spdif_info,
1896                .get = aureon_cs8415_mask_get
1897        },
1898        {
1899                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1900                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1901                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1902                .info = aureon_cs8415_spdif_info,
1903                .get = aureon_cs8415_spdif_get
1904        },
1905        {
1906                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1907                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1908                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1909                .info = aureon_cs8415_rate_info,
1910                .get = aureon_cs8415_rate_get
1911        }
1912};
1913
1914static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1915{
1916        unsigned int i, counts;
1917        int err;
1918
1919        counts = ARRAY_SIZE(aureon_dac_controls);
1920        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1921                counts -= 2; /* no side */
1922        for (i = 0; i < counts; i++) {
1923                err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1924                if (err < 0)
1925                        return err;
1926        }
1927
1928        for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1929                err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1930                if (err < 0)
1931                        return err;
1932        }
1933
1934        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1935                for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1936                        err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1937                        if (err < 0)
1938                                return err;
1939                }
1940        } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1941                 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1942                for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1943                        err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1944                        if (err < 0)
1945                                return err;
1946                }
1947        }
1948
1949        if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1950            ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1951                unsigned char id;
1952                snd_ice1712_save_gpio_status(ice);
1953                id = aureon_cs8415_get(ice, CS8415_ID);
1954                if (id != 0x41)
1955                        snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1956                else if ((id & 0x0F) != 0x01)
1957                        snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1958                else {
1959                        for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1960                                struct snd_kcontrol *kctl;
1961                                err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1962                                if (err < 0)
1963                                        return err;
1964                                if (i > 1)
1965                                        kctl->id.device = ice->pcm->device;
1966                        }
1967                }
1968                snd_ice1712_restore_gpio_status(ice);
1969        }
1970
1971        return 0;
1972}
1973
1974
1975/*
1976 * initialize the chip
1977 */
1978static int __devinit aureon_init(struct snd_ice1712 *ice)
1979{
1980        static const unsigned short wm_inits_aureon[] = {
1981                /* These come first to reduce init pop noise */
1982                0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1983                0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1984                0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1985
1986                0x18, 0x000,            /* All power-up */
1987
1988                0x16, 0x122,            /* I2S, normal polarity, 24bit */
1989                0x17, 0x022,            /* 256fs, slave mode */
1990                0x00, 0,                /* DAC1 analog mute */
1991                0x01, 0,                /* DAC2 analog mute */
1992                0x02, 0,                /* DAC3 analog mute */
1993                0x03, 0,                /* DAC4 analog mute */
1994                0x04, 0,                /* DAC5 analog mute */
1995                0x05, 0,                /* DAC6 analog mute */
1996                0x06, 0,                /* DAC7 analog mute */
1997                0x07, 0,                /* DAC8 analog mute */
1998                0x08, 0x100,            /* master analog mute */
1999                0x09, 0xff,             /* DAC1 digital full */
2000                0x0a, 0xff,             /* DAC2 digital full */
2001                0x0b, 0xff,             /* DAC3 digital full */
2002                0x0c, 0xff,             /* DAC4 digital full */
2003                0x0d, 0xff,             /* DAC5 digital full */
2004                0x0e, 0xff,             /* DAC6 digital full */
2005                0x0f, 0xff,             /* DAC7 digital full */
2006                0x10, 0xff,             /* DAC8 digital full */
2007                0x11, 0x1ff,            /* master digital full */
2008                0x12, 0x000,            /* phase normal */
2009                0x13, 0x090,            /* unmute DAC L/R */
2010                0x14, 0x000,            /* all unmute */
2011                0x15, 0x000,            /* no deemphasis, no ZFLG */
2012                0x19, 0x000,            /* -12dB ADC/L */
2013                0x1a, 0x000,            /* -12dB ADC/R */
2014                (unsigned short)-1
2015        };
2016        static const unsigned short wm_inits_prodigy[] = {
2017
2018                /* These come first to reduce init pop noise */
2019                0x1b, 0x000,            /* ADC Mux */
2020                0x1c, 0x009,            /* Out Mux1 */
2021                0x1d, 0x009,            /* Out Mux2 */
2022
2023                0x18, 0x000,            /* All power-up */
2024
2025                0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
2026                0x17, 0x006,            /* 128fs, slave mode */
2027
2028                0x00, 0,                /* DAC1 analog mute */
2029                0x01, 0,                /* DAC2 analog mute */
2030                0x02, 0,                /* DAC3 analog mute */
2031                0x03, 0,                /* DAC4 analog mute */
2032                0x04, 0,                /* DAC5 analog mute */
2033                0x05, 0,                /* DAC6 analog mute */
2034                0x06, 0,                /* DAC7 analog mute */
2035                0x07, 0,                /* DAC8 analog mute */
2036                0x08, 0x100,            /* master analog mute */
2037
2038                0x09, 0x7f,             /* DAC1 digital full */
2039                0x0a, 0x7f,             /* DAC2 digital full */
2040                0x0b, 0x7f,             /* DAC3 digital full */
2041                0x0c, 0x7f,             /* DAC4 digital full */
2042                0x0d, 0x7f,             /* DAC5 digital full */
2043                0x0e, 0x7f,             /* DAC6 digital full */
2044                0x0f, 0x7f,             /* DAC7 digital full */
2045                0x10, 0x7f,             /* DAC8 digital full */
2046                0x11, 0x1FF,            /* master digital full */
2047
2048                0x12, 0x000,            /* phase normal */
2049                0x13, 0x090,            /* unmute DAC L/R */
2050                0x14, 0x000,            /* all unmute */
2051                0x15, 0x000,            /* no deemphasis, no ZFLG */
2052
2053                0x19, 0x000,            /* -12dB ADC/L */
2054                0x1a, 0x000,            /* -12dB ADC/R */
2055                (unsigned short)-1
2056
2057        };
2058        static const unsigned short cs_inits[] = {
2059                0x0441, /* RUN */
2060                0x0180, /* no mute, OMCK output on RMCK pin */
2061                0x0201, /* S/PDIF source on RXP1 */
2062                0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2063                (unsigned short)-1
2064        };
2065        struct aureon_spec *spec;
2066        unsigned int tmp;
2067        const unsigned short *p;
2068        int err, i;
2069
2070        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2071        if (!spec)
2072                return -ENOMEM;
2073        ice->spec = spec;
2074
2075        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2076                ice->num_total_dacs = 6;
2077                ice->num_total_adcs = 2;
2078        } else {
2079                /* aureon 7.1 and prodigy 7.1 */
2080                ice->num_total_dacs = 8;
2081                ice->num_total_adcs = 2;
2082        }
2083
2084        /* to remeber the register values of CS8415 */
2085        ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2086        if (!ice->akm)
2087                return -ENOMEM;
2088        ice->akm_codecs = 1;
2089
2090        err = aureon_ac97_init(ice);
2091        if (err != 0)
2092                return err;
2093
2094        snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2095
2096        /* reset the wm codec as the SPI mode */
2097        snd_ice1712_save_gpio_status(ice);
2098        snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2099
2100        tmp = snd_ice1712_gpio_read(ice);
2101        tmp &= ~AUREON_WM_RESET;
2102        snd_ice1712_gpio_write(ice, tmp);
2103        udelay(1);
2104        tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2105        snd_ice1712_gpio_write(ice, tmp);
2106        udelay(1);
2107        tmp |= AUREON_WM_RESET;
2108        snd_ice1712_gpio_write(ice, tmp);
2109        udelay(1);
2110
2111        /* initialize WM8770 codec */
2112        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2113                ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2114                ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2115                p = wm_inits_prodigy;
2116        else
2117                p = wm_inits_aureon;
2118        for (; *p != (unsigned short)-1; p += 2)
2119                wm_put(ice, p[0], p[1]);
2120
2121        /* initialize CS8415A codec */
2122        if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2123            ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2124                for (p = cs_inits; *p != (unsigned short)-1; p++)
2125                        aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2126                spec->cs8415_mux = 1;
2127
2128                aureon_set_headphone_amp(ice, 1);
2129        }
2130
2131        snd_ice1712_restore_gpio_status(ice);
2132
2133        /* initialize PCA9554 pin directions & set default input */
2134        aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2135        aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2136
2137        spec->master[0] = WM_VOL_MUTE;
2138        spec->master[1] = WM_VOL_MUTE;
2139        for (i = 0; i < ice->num_total_dacs; i++) {
2140                spec->vol[i] = WM_VOL_MUTE;
2141                wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2142        }
2143
2144        return 0;
2145}
2146
2147
2148/*
2149 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2150 * hence the driver needs to sets up it properly.
2151 */
2152
2153static unsigned char aureon51_eeprom[] __devinitdata = {
2154        [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
2155        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2156        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2157        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2158        [ICE_EEP2_GPIO_DIR]    = 0xff,
2159        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2160        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2161        [ICE_EEP2_GPIO_MASK]   = 0x00,
2162        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2163        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2164        [ICE_EEP2_GPIO_STATE]  = 0x00,
2165        [ICE_EEP2_GPIO_STATE1] = 0x00,
2166        [ICE_EEP2_GPIO_STATE2] = 0x00,
2167};
2168
2169static unsigned char aureon71_eeprom[] __devinitdata = {
2170        [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
2171        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2172        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2173        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2174        [ICE_EEP2_GPIO_DIR]    = 0xff,
2175        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2176        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2177        [ICE_EEP2_GPIO_MASK]   = 0x00,
2178        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2179        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2180        [ICE_EEP2_GPIO_STATE]  = 0x00,
2181        [ICE_EEP2_GPIO_STATE1] = 0x00,
2182        [ICE_EEP2_GPIO_STATE2] = 0x00,
2183};
2184#define prodigy71_eeprom aureon71_eeprom
2185
2186static unsigned char aureon71_universe_eeprom[] __devinitdata = {
2187        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, spdif-in/ADC,
2188                                         * 4DACs
2189                                         */
2190        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2191        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2192        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2193        [ICE_EEP2_GPIO_DIR]    = 0xff,
2194        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2195        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2196        [ICE_EEP2_GPIO_MASK]   = 0x00,
2197        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2198        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2199        [ICE_EEP2_GPIO_STATE]  = 0x00,
2200        [ICE_EEP2_GPIO_STATE1] = 0x00,
2201        [ICE_EEP2_GPIO_STATE2] = 0x00,
2202};
2203
2204static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2205        [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
2206        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2207        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2208        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2209        [ICE_EEP2_GPIO_DIR]    = 0xff,
2210        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2211        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2212        [ICE_EEP2_GPIO_MASK]   = 0x00,
2213        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2214        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2215        [ICE_EEP2_GPIO_STATE]  = 0x00,
2216        [ICE_EEP2_GPIO_STATE1] = 0x00,
2217        [ICE_EEP2_GPIO_STATE2] = 0x00,
2218};
2219#define prodigy71xt_eeprom prodigy71lt_eeprom
2220
2221/* entry point */
2222struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2223        {
2224                .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2225                .name = "Terratec Aureon 5.1-Sky",
2226                .model = "aureon51",
2227                .chip_init = aureon_init,
2228                .build_controls = aureon_add_controls,
2229                .eeprom_size = sizeof(aureon51_eeprom),
2230                .eeprom_data = aureon51_eeprom,
2231                .driver = "Aureon51",
2232        },
2233        {
2234                .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2235                .name = "Terratec Aureon 7.1-Space",
2236                .model = "aureon71",
2237                .chip_init = aureon_init,
2238                .build_controls = aureon_add_controls,
2239                .eeprom_size = sizeof(aureon71_eeprom),
2240                .eeprom_data = aureon71_eeprom,
2241                .driver = "Aureon71",
2242        },
2243        {
2244                .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2245                .name = "Terratec Aureon 7.1-Universe",
2246                .model = "universe",
2247                .chip_init = aureon_init,
2248                .build_controls = aureon_add_controls,
2249                .eeprom_size = sizeof(aureon71_universe_eeprom),
2250                .eeprom_data = aureon71_universe_eeprom,
2251                .driver = "Aureon71Univ", /* keep in 15 letters */
2252        },
2253        {
2254                .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2255                .name = "Audiotrak Prodigy 7.1",
2256                .model = "prodigy71",
2257                .chip_init = aureon_init,
2258                .build_controls = aureon_add_controls,
2259                .eeprom_size = sizeof(prodigy71_eeprom),
2260                .eeprom_data = prodigy71_eeprom,
2261                .driver = "Prodigy71", /* should be identical with Aureon71 */
2262        },
2263        {
2264                .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2265                .name = "Audiotrak Prodigy 7.1 LT",
2266                .model = "prodigy71lt",
2267                .chip_init = aureon_init,
2268                .build_controls = aureon_add_controls,
2269                .eeprom_size = sizeof(prodigy71lt_eeprom),
2270                .eeprom_data = prodigy71lt_eeprom,
2271                .driver = "Prodigy71LT",
2272        },
2273        {
2274                .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2275                .name = "Audiotrak Prodigy 7.1 XT",
2276                .model = "prodigy71xt",
2277                .chip_init = aureon_init,
2278                .build_controls = aureon_add_controls,
2279                .eeprom_size = sizeof(prodigy71xt_eeprom),
2280                .eeprom_data = prodigy71xt_eeprom,
2281                .driver = "Prodigy71LT",
2282        },
2283        { } /* terminator */
2284};
2285