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/delay.h>
  50#include <linux/interrupt.h>
  51#include <linux/init.h>
  52#include <linux/slab.h>
  53#include <linux/mutex.h>
  54
  55#include <sound/core.h>
  56
  57#include "ice1712.h"
  58#include "envy24ht.h"
  59#include "aureon.h"
  60#include <sound/tlv.h>
  61
  62/* AC97 register cache for Aureon */
  63struct aureon_spec {
  64        unsigned short stac9744[64];
  65        unsigned int cs8415_mux;
  66        unsigned short master[2];
  67        unsigned short vol[8];
  68        unsigned char pca9554_out;
  69};
  70
  71/* WM8770 registers */
  72#define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
  73#define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
  74#define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
  75#define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
  76#define WM_PHASE_SWAP           0x12    /* DAC phase */
  77#define WM_DAC_CTRL1            0x13    /* DAC control bits */
  78#define WM_MUTE                 0x14    /* mute controls */
  79#define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
  80#define WM_INT_CTRL             0x16    /* interface control */
  81#define WM_MASTER               0x17    /* master clock and mode */
  82#define WM_POWERDOWN            0x18    /* power-down controls */
  83#define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
  84#define WM_ADC_MUX              0x1b    /* input MUX */
  85#define WM_OUT_MUX1             0x1c    /* output MUX */
  86#define WM_OUT_MUX2             0x1e    /* output MUX */
  87#define WM_RESET                0x1f    /* software reset */
  88
  89/* CS8415A registers */
  90#define CS8415_CTRL1    0x01
  91#define CS8415_CTRL2    0x02
  92#define CS8415_QSUB             0x14
  93#define CS8415_RATIO    0x1E
  94#define CS8415_C_BUFFER 0x20
  95#define CS8415_ID               0x7F
  96
  97/* PCA9554 registers */
  98#define PCA9554_DEV     0x40            /* I2C device address */
  99#define PCA9554_IN      0x00            /* input port */
 100#define PCA9554_OUT     0x01            /* output port */
 101#define PCA9554_INVERT  0x02            /* input invert */
 102#define PCA9554_DIR     0x03            /* port directions */
 103
 104/*
 105 * Aureon Universe additional controls using PCA9554
 106 */
 107
 108/*
 109 * Send data to pca9554
 110 */
 111static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
 112                                 unsigned char data)
 113{
 114        unsigned int tmp;
 115        int i, j;
 116        unsigned char dev = PCA9554_DEV;  /* ID 0100000, write */
 117        unsigned char val = 0;
 118
 119        tmp = snd_ice1712_gpio_read(ice);
 120
 121        snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
 122                                         AUREON_WM_RW|AUREON_WM_CS|
 123                                         AUREON_CS8415_CS));
 124        tmp |= AUREON_WM_RW;
 125        tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
 126
 127        tmp &= ~AUREON_SPI_MOSI;
 128        tmp &= ~AUREON_SPI_CLK;
 129        snd_ice1712_gpio_write(ice, tmp);
 130        udelay(50);
 131
 132        /*
 133         * send i2c stop condition and start condition
 134         * to obtain sane state
 135         */
 136        tmp |= AUREON_SPI_CLK;
 137        snd_ice1712_gpio_write(ice, tmp);
 138        udelay(50);
 139        tmp |= AUREON_SPI_MOSI;
 140        snd_ice1712_gpio_write(ice, tmp);
 141        udelay(100);
 142        tmp &= ~AUREON_SPI_MOSI;
 143        snd_ice1712_gpio_write(ice, tmp);
 144        udelay(50);
 145        tmp &= ~AUREON_SPI_CLK;
 146        snd_ice1712_gpio_write(ice, tmp);
 147        udelay(100);
 148        /*
 149         * send device address, command and value,
 150         * skipping ack cycles in between
 151         */
 152        for (j = 0; j < 3; j++) {
 153                switch (j) {
 154                case 0:
 155                        val = dev;
 156                        break;
 157                case 1:
 158                        val = reg;
 159                        break;
 160                case 2:
 161                        val = data;
 162                        break;
 163                }
 164                for (i = 7; i >= 0; i--) {
 165                        tmp &= ~AUREON_SPI_CLK;
 166                        snd_ice1712_gpio_write(ice, tmp);
 167                        udelay(40);
 168                        if (val & (1 << i))
 169                                tmp |= AUREON_SPI_MOSI;
 170                        else
 171                                tmp &= ~AUREON_SPI_MOSI;
 172                        snd_ice1712_gpio_write(ice, tmp);
 173                        udelay(40);
 174                        tmp |= AUREON_SPI_CLK;
 175                        snd_ice1712_gpio_write(ice, tmp);
 176                        udelay(40);
 177                }
 178                tmp &= ~AUREON_SPI_CLK;
 179                snd_ice1712_gpio_write(ice, tmp);
 180                udelay(40);
 181                tmp |= AUREON_SPI_CLK;
 182                snd_ice1712_gpio_write(ice, tmp);
 183                udelay(40);
 184                tmp &= ~AUREON_SPI_CLK;
 185                snd_ice1712_gpio_write(ice, tmp);
 186                udelay(40);
 187        }
 188        tmp &= ~AUREON_SPI_CLK;
 189        snd_ice1712_gpio_write(ice, tmp);
 190        udelay(40);
 191        tmp &= ~AUREON_SPI_MOSI;
 192        snd_ice1712_gpio_write(ice, tmp);
 193        udelay(40);
 194        tmp |= AUREON_SPI_CLK;
 195        snd_ice1712_gpio_write(ice, tmp);
 196        udelay(50);
 197        tmp |= AUREON_SPI_MOSI;
 198        snd_ice1712_gpio_write(ice, tmp);
 199        udelay(100);
 200}
 201
 202static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
 203                                      struct snd_ctl_elem_info *uinfo)
 204{
 205        static const char * const texts[3] =
 206                {"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, -10000, 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#define WM_VOL_MAX      100
 699#define WM_VOL_CNT      101     /* 0dB .. -100dB */
 700#define WM_VOL_MUTE     0x8000
 701
 702static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
 703{
 704        unsigned char nvol;
 705
 706        if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
 707                nvol = 0;
 708        } else {
 709                nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
 710                                                                WM_VOL_MAX;
 711                nvol += 0x1b;
 712        }
 713
 714        wm_put(ice, index, nvol);
 715        wm_put_nocache(ice, index, 0x180 | nvol);
 716}
 717
 718/*
 719 * DAC mute control
 720 */
 721#define wm_pcm_mute_info        snd_ctl_boolean_mono_info
 722
 723static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 724{
 725        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 726
 727        mutex_lock(&ice->gpio_mutex);
 728        ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
 729        mutex_unlock(&ice->gpio_mutex);
 730        return 0;
 731}
 732
 733static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 734{
 735        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 736        unsigned short nval, oval;
 737        int change;
 738
 739        snd_ice1712_save_gpio_status(ice);
 740        oval = wm_get(ice, WM_MUTE);
 741        nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
 742        change = (oval != nval);
 743        if (change)
 744                wm_put(ice, WM_MUTE, nval);
 745        snd_ice1712_restore_gpio_status(ice);
 746
 747        return change;
 748}
 749
 750/*
 751 * Master volume attenuation mixer control
 752 */
 753static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 754{
 755        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 756        uinfo->count = 2;
 757        uinfo->value.integer.min = 0;
 758        uinfo->value.integer.max = WM_VOL_MAX;
 759        return 0;
 760}
 761
 762static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 763{
 764        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 765        struct aureon_spec *spec = ice->spec;
 766        int i;
 767        for (i = 0; i < 2; i++)
 768                ucontrol->value.integer.value[i] =
 769                        spec->master[i] & ~WM_VOL_MUTE;
 770        return 0;
 771}
 772
 773static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 774{
 775        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 776        struct aureon_spec *spec = ice->spec;
 777        int ch, change = 0;
 778
 779        snd_ice1712_save_gpio_status(ice);
 780        for (ch = 0; ch < 2; ch++) {
 781                unsigned int vol = ucontrol->value.integer.value[ch];
 782                if (vol > WM_VOL_MAX)
 783                        vol = WM_VOL_MAX;
 784                vol |= spec->master[ch] & WM_VOL_MUTE;
 785                if (vol != spec->master[ch]) {
 786                        int dac;
 787                        spec->master[ch] = vol;
 788                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 789                                wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
 790                                           spec->vol[dac + ch],
 791                                           spec->master[ch]);
 792                        change = 1;
 793                }
 794        }
 795        snd_ice1712_restore_gpio_status(ice);
 796        return change;
 797}
 798
 799/*
 800 * DAC volume attenuation mixer control
 801 */
 802static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 803{
 804        int voices = kcontrol->private_value >> 8;
 805        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 806        uinfo->count = voices;
 807        uinfo->value.integer.min = 0;           /* mute (-101dB) */
 808        uinfo->value.integer.max = WM_VOL_MAX;  /* 0dB */
 809        return 0;
 810}
 811
 812static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 813{
 814        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 815        struct aureon_spec *spec = ice->spec;
 816        int i, ofs, voices;
 817
 818        voices = kcontrol->private_value >> 8;
 819        ofs = kcontrol->private_value & 0xff;
 820        for (i = 0; i < voices; i++)
 821                ucontrol->value.integer.value[i] =
 822                        spec->vol[ofs+i] & ~WM_VOL_MUTE;
 823        return 0;
 824}
 825
 826static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 827{
 828        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 829        struct aureon_spec *spec = ice->spec;
 830        int i, idx, ofs, voices;
 831        int change = 0;
 832
 833        voices = kcontrol->private_value >> 8;
 834        ofs = kcontrol->private_value & 0xff;
 835        snd_ice1712_save_gpio_status(ice);
 836        for (i = 0; i < voices; i++) {
 837                unsigned int vol = ucontrol->value.integer.value[i];
 838                if (vol > WM_VOL_MAX)
 839                        vol = WM_VOL_MAX;
 840                vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
 841                if (vol != spec->vol[ofs+i]) {
 842                        spec->vol[ofs+i] = vol;
 843                        idx  = WM_DAC_ATTEN + ofs + i;
 844                        wm_set_vol(ice, idx, spec->vol[ofs + i],
 845                                   spec->master[i]);
 846                        change = 1;
 847                }
 848        }
 849        snd_ice1712_restore_gpio_status(ice);
 850        return change;
 851}
 852
 853/*
 854 * WM8770 mute control
 855 */
 856static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 857{
 858        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 859        uinfo->count = kcontrol->private_value >> 8;
 860        uinfo->value.integer.min = 0;
 861        uinfo->value.integer.max = 1;
 862        return 0;
 863}
 864
 865static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 866{
 867        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 868        struct aureon_spec *spec = ice->spec;
 869        int voices, ofs, i;
 870
 871        voices = kcontrol->private_value >> 8;
 872        ofs = kcontrol->private_value & 0xFF;
 873
 874        for (i = 0; i < voices; i++)
 875                ucontrol->value.integer.value[i] =
 876                        (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
 877        return 0;
 878}
 879
 880static int wm_mute_put(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 change = 0, voices, ofs, i;
 885
 886        voices = kcontrol->private_value >> 8;
 887        ofs = kcontrol->private_value & 0xFF;
 888
 889        snd_ice1712_save_gpio_status(ice);
 890        for (i = 0; i < voices; i++) {
 891                int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
 892                if (ucontrol->value.integer.value[i] != val) {
 893                        spec->vol[ofs + i] &= ~WM_VOL_MUTE;
 894                        spec->vol[ofs + i] |=
 895                                ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
 896                        wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
 897                                   spec->master[i]);
 898                        change = 1;
 899                }
 900        }
 901        snd_ice1712_restore_gpio_status(ice);
 902
 903        return change;
 904}
 905
 906/*
 907 * WM8770 master mute control
 908 */
 909#define wm_master_mute_info             snd_ctl_boolean_stereo_info
 910
 911static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 912{
 913        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 914        struct aureon_spec *spec = ice->spec;
 915
 916        ucontrol->value.integer.value[0] =
 917                (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
 918        ucontrol->value.integer.value[1] =
 919                (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
 920        return 0;
 921}
 922
 923static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 924{
 925        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 926        struct aureon_spec *spec = ice->spec;
 927        int change = 0, i;
 928
 929        snd_ice1712_save_gpio_status(ice);
 930        for (i = 0; i < 2; i++) {
 931                int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
 932                if (ucontrol->value.integer.value[i] != val) {
 933                        int dac;
 934                        spec->master[i] &= ~WM_VOL_MUTE;
 935                        spec->master[i] |=
 936                                ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
 937                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 938                                wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
 939                                           spec->vol[dac + i],
 940                                           spec->master[i]);
 941                        change = 1;
 942                }
 943        }
 944        snd_ice1712_restore_gpio_status(ice);
 945
 946        return change;
 947}
 948
 949/* digital master volume */
 950#define PCM_0dB 0xff
 951#define PCM_RES 128     /* -64dB */
 952#define PCM_MIN (PCM_0dB - PCM_RES)
 953static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 954{
 955        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 956        uinfo->count = 1;
 957        uinfo->value.integer.min = 0;           /* mute (-64dB) */
 958        uinfo->value.integer.max = PCM_RES;     /* 0dB */
 959        return 0;
 960}
 961
 962static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 963{
 964        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 965        unsigned short val;
 966
 967        mutex_lock(&ice->gpio_mutex);
 968        val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 969        val = val > PCM_MIN ? (val - PCM_MIN) : 0;
 970        ucontrol->value.integer.value[0] = val;
 971        mutex_unlock(&ice->gpio_mutex);
 972        return 0;
 973}
 974
 975static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 976{
 977        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 978        unsigned short ovol, nvol;
 979        int change = 0;
 980
 981        nvol = ucontrol->value.integer.value[0];
 982        if (nvol > PCM_RES)
 983                return -EINVAL;
 984        snd_ice1712_save_gpio_status(ice);
 985        nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
 986        ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 987        if (ovol != nvol) {
 988                wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
 989                wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
 990                change = 1;
 991        }
 992        snd_ice1712_restore_gpio_status(ice);
 993        return change;
 994}
 995
 996/*
 997 * ADC mute control
 998 */
 999#define wm_adc_mute_info                snd_ctl_boolean_stereo_info
1000
1001static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1002{
1003        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1004        unsigned short val;
1005        int i;
1006
1007        mutex_lock(&ice->gpio_mutex);
1008        for (i = 0; i < 2; i++) {
1009                val = wm_get(ice, WM_ADC_GAIN + i);
1010                ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1011        }
1012        mutex_unlock(&ice->gpio_mutex);
1013        return 0;
1014}
1015
1016static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1017{
1018        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1019        unsigned short new, old;
1020        int i, change = 0;
1021
1022        snd_ice1712_save_gpio_status(ice);
1023        for (i = 0; i < 2; i++) {
1024                old = wm_get(ice, WM_ADC_GAIN + i);
1025                new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1026                if (new != old) {
1027                        wm_put(ice, WM_ADC_GAIN + i, new);
1028                        change = 1;
1029                }
1030        }
1031        snd_ice1712_restore_gpio_status(ice);
1032
1033        return change;
1034}
1035
1036/*
1037 * ADC gain mixer control
1038 */
1039static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1040{
1041        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1042        uinfo->count = 2;
1043        uinfo->value.integer.min = 0;           /* -12dB */
1044        uinfo->value.integer.max = 0x1f;        /* 19dB */
1045        return 0;
1046}
1047
1048static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1049{
1050        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1051        int i, idx;
1052        unsigned short vol;
1053
1054        mutex_lock(&ice->gpio_mutex);
1055        for (i = 0; i < 2; i++) {
1056                idx = WM_ADC_GAIN + i;
1057                vol = wm_get(ice, idx) & 0x1f;
1058                ucontrol->value.integer.value[i] = vol;
1059        }
1060        mutex_unlock(&ice->gpio_mutex);
1061        return 0;
1062}
1063
1064static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1065{
1066        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1067        int i, idx;
1068        unsigned short ovol, nvol;
1069        int change = 0;
1070
1071        snd_ice1712_save_gpio_status(ice);
1072        for (i = 0; i < 2; i++) {
1073                idx  = WM_ADC_GAIN + i;
1074                nvol = ucontrol->value.integer.value[i] & 0x1f;
1075                ovol = wm_get(ice, idx);
1076                if ((ovol & 0x1f) != nvol) {
1077                        wm_put(ice, idx, nvol | (ovol & ~0x1f));
1078                        change = 1;
1079                }
1080        }
1081        snd_ice1712_restore_gpio_status(ice);
1082        return change;
1083}
1084
1085/*
1086 * ADC input mux mixer control
1087 */
1088static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1089{
1090        static const char * const texts[] = {
1091                "CD",           /* AIN1 */
1092                "Aux",          /* AIN2 */
1093                "Line",         /* AIN3 */
1094                "Mic",          /* AIN4 */
1095                "AC97"          /* AIN5 */
1096        };
1097        static const char * const universe_texts[] = {
1098                "Aux1",         /* AIN1 */
1099                "CD",           /* AIN2 */
1100                "Phono",        /* AIN3 */
1101                "Line",         /* AIN4 */
1102                "Aux2",         /* AIN5 */
1103                "Mic",          /* AIN6 */
1104                "Aux3",         /* AIN7 */
1105                "AC97"          /* AIN8 */
1106        };
1107        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1108
1109        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1110        uinfo->count = 2;
1111        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1112                uinfo->value.enumerated.items = 8;
1113                if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1114                        uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1115                strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1116        } else {
1117                uinfo->value.enumerated.items = 5;
1118                if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1119                        uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1120                strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1121        }
1122        return 0;
1123}
1124
1125static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1126{
1127        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1128        unsigned short val;
1129
1130        mutex_lock(&ice->gpio_mutex);
1131        val = wm_get(ice, WM_ADC_MUX);
1132        ucontrol->value.enumerated.item[0] = val & 7;
1133        ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1134        mutex_unlock(&ice->gpio_mutex);
1135        return 0;
1136}
1137
1138static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1139{
1140        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1141        unsigned short oval, nval;
1142        int change;
1143
1144        snd_ice1712_save_gpio_status(ice);
1145        oval = wm_get(ice, WM_ADC_MUX);
1146        nval = oval & ~0x77;
1147        nval |= ucontrol->value.enumerated.item[0] & 7;
1148        nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1149        change = (oval != nval);
1150        if (change)
1151                wm_put(ice, WM_ADC_MUX, nval);
1152        snd_ice1712_restore_gpio_status(ice);
1153        return change;
1154}
1155
1156/*
1157 * CS8415 Input mux
1158 */
1159static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1160{
1161        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1162        static const char * const aureon_texts[] = {
1163                "CD",           /* RXP0 */
1164                "Optical"       /* RXP1 */
1165        };
1166        static const char * const prodigy_texts[] = {
1167                "CD",
1168                "Coax"
1169        };
1170        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1171        uinfo->count = 1;
1172        uinfo->value.enumerated.items = 2;
1173        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1174                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1175        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1176                strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1177        else
1178                strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1179        return 0;
1180}
1181
1182static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1183{
1184        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1185        struct aureon_spec *spec = ice->spec;
1186
1187        /* snd_ice1712_save_gpio_status(ice); */
1188        /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
1189        ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1190        /* snd_ice1712_restore_gpio_status(ice); */
1191        return 0;
1192}
1193
1194static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1195{
1196        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1197        struct aureon_spec *spec = ice->spec;
1198        unsigned short oval, nval;
1199        int change;
1200
1201        snd_ice1712_save_gpio_status(ice);
1202        oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1203        nval = oval & ~0x07;
1204        nval |= ucontrol->value.enumerated.item[0] & 7;
1205        change = (oval != nval);
1206        if (change)
1207                aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1208        snd_ice1712_restore_gpio_status(ice);
1209        spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1210        return change;
1211}
1212
1213static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1214{
1215        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1216        uinfo->count = 1;
1217        uinfo->value.integer.min = 0;
1218        uinfo->value.integer.max = 192000;
1219        return 0;
1220}
1221
1222static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1223{
1224        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1225        unsigned char ratio;
1226        ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1227        ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1228        return 0;
1229}
1230
1231/*
1232 * CS8415A Mute
1233 */
1234#define aureon_cs8415_mute_info         snd_ctl_boolean_mono_info
1235
1236static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1237{
1238        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1239        snd_ice1712_save_gpio_status(ice);
1240        ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1241        snd_ice1712_restore_gpio_status(ice);
1242        return 0;
1243}
1244
1245static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1246{
1247        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1248        unsigned char oval, nval;
1249        int change;
1250        snd_ice1712_save_gpio_status(ice);
1251        oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1252        if (ucontrol->value.integer.value[0])
1253                nval = oval & ~0x20;
1254        else
1255                nval = oval | 0x20;
1256        change = (oval != nval);
1257        if (change)
1258                aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1259        snd_ice1712_restore_gpio_status(ice);
1260        return change;
1261}
1262
1263/*
1264 * CS8415A Q-Sub info
1265 */
1266static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1267{
1268        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1269        uinfo->count = 10;
1270        return 0;
1271}
1272
1273static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1274{
1275        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1276
1277        snd_ice1712_save_gpio_status(ice);
1278        aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1279        snd_ice1712_restore_gpio_status(ice);
1280
1281        return 0;
1282}
1283
1284static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1285{
1286        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1287        uinfo->count = 1;
1288        return 0;
1289}
1290
1291static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1292{
1293        memset(ucontrol->value.iec958.status, 0xFF, 24);
1294        return 0;
1295}
1296
1297static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1298{
1299        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1300
1301        snd_ice1712_save_gpio_status(ice);
1302        aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1303        snd_ice1712_restore_gpio_status(ice);
1304        return 0;
1305}
1306
1307/*
1308 * Headphone Amplifier
1309 */
1310static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1311{
1312        unsigned int tmp, tmp2;
1313
1314        tmp2 = tmp = snd_ice1712_gpio_read(ice);
1315        if (enable)
1316                if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1317                    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1318                        tmp |= AUREON_HP_SEL;
1319                else
1320                        tmp |= PRODIGY_HP_SEL;
1321        else
1322                if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1323                    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1324                        tmp &= ~AUREON_HP_SEL;
1325                else
1326                        tmp &= ~PRODIGY_HP_SEL;
1327        if (tmp != tmp2) {
1328                snd_ice1712_gpio_write(ice, tmp);
1329                return 1;
1330        }
1331        return 0;
1332}
1333
1334static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1335{
1336        unsigned int tmp = snd_ice1712_gpio_read(ice);
1337
1338        return (tmp & AUREON_HP_SEL) != 0;
1339}
1340
1341#define aureon_hpamp_info       snd_ctl_boolean_mono_info
1342
1343static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1344{
1345        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1346
1347        ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1348        return 0;
1349}
1350
1351
1352static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1353{
1354        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1355
1356        return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1357}
1358
1359/*
1360 * Deemphasis
1361 */
1362
1363#define aureon_deemp_info       snd_ctl_boolean_mono_info
1364
1365static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1366{
1367        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1368        ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1369        return 0;
1370}
1371
1372static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1373{
1374        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1375        int temp, temp2;
1376        temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1377        if (ucontrol->value.integer.value[0])
1378                temp |= 0xf;
1379        else
1380                temp &= ~0xf;
1381        if (temp != temp2) {
1382                wm_put(ice, WM_DAC_CTRL2, temp);
1383                return 1;
1384        }
1385        return 0;
1386}
1387
1388/*
1389 * ADC Oversampling
1390 */
1391static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1392{
1393        static const char * const texts[2] = { "128x", "64x"    };
1394
1395        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1396        uinfo->count = 1;
1397        uinfo->value.enumerated.items = 2;
1398
1399        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1400                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1401        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1402
1403        return 0;
1404}
1405
1406static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1407{
1408        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1409        ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1410        return 0;
1411}
1412
1413static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1414{
1415        int temp, temp2;
1416        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1417
1418        temp2 = temp = wm_get(ice, WM_MASTER);
1419
1420        if (ucontrol->value.enumerated.item[0])
1421                temp |= 0x8;
1422        else
1423                temp &= ~0x8;
1424
1425        if (temp != temp2) {
1426                wm_put(ice, WM_MASTER, temp);
1427                return 1;
1428        }
1429        return 0;
1430}
1431
1432/*
1433 * mixers
1434 */
1435
1436static struct snd_kcontrol_new aureon_dac_controls[] = {
1437        {
1438                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439                .name = "Master Playback Switch",
1440                .info = wm_master_mute_info,
1441                .get = wm_master_mute_get,
1442                .put = wm_master_mute_put
1443        },
1444        {
1445                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1446                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1447                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1448                .name = "Master Playback Volume",
1449                .info = wm_master_vol_info,
1450                .get = wm_master_vol_get,
1451                .put = wm_master_vol_put,
1452                .tlv = { .p = db_scale_wm_dac }
1453        },
1454        {
1455                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1456                .name = "Front Playback Switch",
1457                .info = wm_mute_info,
1458                .get = wm_mute_get,
1459                .put = wm_mute_put,
1460                .private_value = (2 << 8) | 0
1461        },
1462        {
1463                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1464                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1465                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1466                .name = "Front Playback Volume",
1467                .info = wm_vol_info,
1468                .get = wm_vol_get,
1469                .put = wm_vol_put,
1470                .private_value = (2 << 8) | 0,
1471                .tlv = { .p = db_scale_wm_dac }
1472        },
1473        {
1474                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475                .name = "Rear Playback Switch",
1476                .info = wm_mute_info,
1477                .get = wm_mute_get,
1478                .put = wm_mute_put,
1479                .private_value = (2 << 8) | 2
1480        },
1481        {
1482                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1483                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1484                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1485                .name = "Rear Playback Volume",
1486                .info = wm_vol_info,
1487                .get = wm_vol_get,
1488                .put = wm_vol_put,
1489                .private_value = (2 << 8) | 2,
1490                .tlv = { .p = db_scale_wm_dac }
1491        },
1492        {
1493                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1494                .name = "Center Playback Switch",
1495                .info = wm_mute_info,
1496                .get = wm_mute_get,
1497                .put = wm_mute_put,
1498                .private_value = (1 << 8) | 4
1499        },
1500        {
1501                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1502                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1503                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1504                .name = "Center Playback Volume",
1505                .info = wm_vol_info,
1506                .get = wm_vol_get,
1507                .put = wm_vol_put,
1508                .private_value = (1 << 8) | 4,
1509                .tlv = { .p = db_scale_wm_dac }
1510        },
1511        {
1512                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1513                .name = "LFE Playback Switch",
1514                .info = wm_mute_info,
1515                .get = wm_mute_get,
1516                .put = wm_mute_put,
1517                .private_value = (1 << 8) | 5
1518        },
1519        {
1520                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1521                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1522                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1523                .name = "LFE Playback Volume",
1524                .info = wm_vol_info,
1525                .get = wm_vol_get,
1526                .put = wm_vol_put,
1527                .private_value = (1 << 8) | 5,
1528                .tlv = { .p = db_scale_wm_dac }
1529        },
1530        {
1531                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1532                .name = "Side Playback Switch",
1533                .info = wm_mute_info,
1534                .get = wm_mute_get,
1535                .put = wm_mute_put,
1536                .private_value = (2 << 8) | 6
1537        },
1538        {
1539                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1540                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1541                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1542                .name = "Side Playback Volume",
1543                .info = wm_vol_info,
1544                .get = wm_vol_get,
1545                .put = wm_vol_put,
1546                .private_value = (2 << 8) | 6,
1547                .tlv = { .p = db_scale_wm_dac }
1548        }
1549};
1550
1551static struct snd_kcontrol_new wm_controls[] = {
1552        {
1553                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1554                .name = "PCM Playback Switch",
1555                .info = wm_pcm_mute_info,
1556                .get = wm_pcm_mute_get,
1557                .put = wm_pcm_mute_put
1558        },
1559        {
1560                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1561                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1562                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1563                .name = "PCM Playback Volume",
1564                .info = wm_pcm_vol_info,
1565                .get = wm_pcm_vol_get,
1566                .put = wm_pcm_vol_put,
1567                .tlv = { .p = db_scale_wm_pcm }
1568        },
1569        {
1570                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1571                .name = "Capture Switch",
1572                .info = wm_adc_mute_info,
1573                .get = wm_adc_mute_get,
1574                .put = wm_adc_mute_put,
1575        },
1576        {
1577                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1578                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1579                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1580                .name = "Capture Volume",
1581                .info = wm_adc_vol_info,
1582                .get = wm_adc_vol_get,
1583                .put = wm_adc_vol_put,
1584                .tlv = { .p = db_scale_wm_adc }
1585        },
1586        {
1587                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1588                .name = "Capture Source",
1589                .info = wm_adc_mux_info,
1590                .get = wm_adc_mux_get,
1591                .put = wm_adc_mux_put,
1592                .private_value = 5
1593        },
1594        {
1595                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1596                .name = "External Amplifier",
1597                .info = aureon_hpamp_info,
1598                .get = aureon_hpamp_get,
1599                .put = aureon_hpamp_put
1600        },
1601        {
1602                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603                .name = "DAC Deemphasis Switch",
1604                .info = aureon_deemp_info,
1605                .get = aureon_deemp_get,
1606                .put = aureon_deemp_put
1607        },
1608        {
1609                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1610                .name = "ADC Oversampling",
1611                .info = aureon_oversampling_info,
1612                .get = aureon_oversampling_get,
1613                .put = aureon_oversampling_put
1614        }
1615};
1616
1617static struct snd_kcontrol_new ac97_controls[] = {
1618        {
1619                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1620                .name = "AC97 Playback Switch",
1621                .info = aureon_ac97_mmute_info,
1622                .get = aureon_ac97_mmute_get,
1623                .put = aureon_ac97_mmute_put,
1624                .private_value = AC97_MASTER
1625        },
1626        {
1627                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1628                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1629                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1630                .name = "AC97 Playback Volume",
1631                .info = aureon_ac97_vol_info,
1632                .get = aureon_ac97_vol_get,
1633                .put = aureon_ac97_vol_put,
1634                .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1635                .tlv = { .p = db_scale_ac97_master }
1636        },
1637        {
1638                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1639                .name = "CD Playback Switch",
1640                .info = aureon_ac97_mute_info,
1641                .get = aureon_ac97_mute_get,
1642                .put = aureon_ac97_mute_put,
1643                .private_value = AC97_CD
1644        },
1645        {
1646                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1647                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1648                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1649                .name = "CD Playback Volume",
1650                .info = aureon_ac97_vol_info,
1651                .get = aureon_ac97_vol_get,
1652                .put = aureon_ac97_vol_put,
1653                .private_value = AC97_CD|AUREON_AC97_STEREO,
1654                .tlv = { .p = db_scale_ac97_gain }
1655        },
1656        {
1657                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1658                .name = "Aux Playback Switch",
1659                .info = aureon_ac97_mute_info,
1660                .get = aureon_ac97_mute_get,
1661                .put = aureon_ac97_mute_put,
1662                .private_value = AC97_AUX,
1663        },
1664        {
1665                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1666                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1667                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1668                .name = "Aux Playback Volume",
1669                .info = aureon_ac97_vol_info,
1670                .get = aureon_ac97_vol_get,
1671                .put = aureon_ac97_vol_put,
1672                .private_value = AC97_AUX|AUREON_AC97_STEREO,
1673                .tlv = { .p = db_scale_ac97_gain }
1674        },
1675        {
1676                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1677                .name = "Line Playback Switch",
1678                .info = aureon_ac97_mute_info,
1679                .get = aureon_ac97_mute_get,
1680                .put = aureon_ac97_mute_put,
1681                .private_value = AC97_LINE
1682        },
1683        {
1684                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1685                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1686                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1687                .name = "Line Playback Volume",
1688                .info = aureon_ac97_vol_info,
1689                .get = aureon_ac97_vol_get,
1690                .put = aureon_ac97_vol_put,
1691                .private_value = AC97_LINE|AUREON_AC97_STEREO,
1692                .tlv = { .p = db_scale_ac97_gain }
1693        },
1694        {
1695                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1696                .name = "Mic Playback Switch",
1697                .info = aureon_ac97_mute_info,
1698                .get = aureon_ac97_mute_get,
1699                .put = aureon_ac97_mute_put,
1700                .private_value = AC97_MIC
1701        },
1702        {
1703                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1704                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1705                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1706                .name = "Mic Playback Volume",
1707                .info = aureon_ac97_vol_info,
1708                .get = aureon_ac97_vol_get,
1709                .put = aureon_ac97_vol_put,
1710                .private_value = AC97_MIC,
1711                .tlv = { .p = db_scale_ac97_gain }
1712        },
1713        {
1714                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1715                .name = "Mic Boost (+20dB)",
1716                .info = aureon_ac97_micboost_info,
1717                .get = aureon_ac97_micboost_get,
1718                .put = aureon_ac97_micboost_put
1719        }
1720};
1721
1722static struct snd_kcontrol_new universe_ac97_controls[] = {
1723        {
1724                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1725                .name = "AC97 Playback Switch",
1726                .info = aureon_ac97_mmute_info,
1727                .get = aureon_ac97_mmute_get,
1728                .put = aureon_ac97_mmute_put,
1729                .private_value = AC97_MASTER
1730        },
1731        {
1732                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1733                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1734                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1735                .name = "AC97 Playback Volume",
1736                .info = aureon_ac97_vol_info,
1737                .get = aureon_ac97_vol_get,
1738                .put = aureon_ac97_vol_put,
1739                .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1740                .tlv = { .p = db_scale_ac97_master }
1741        },
1742        {
1743                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1744                .name = "CD Playback Switch",
1745                .info = aureon_ac97_mute_info,
1746                .get = aureon_ac97_mute_get,
1747                .put = aureon_ac97_mute_put,
1748                .private_value = AC97_AUX
1749        },
1750        {
1751                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1752                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1753                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1754                .name = "CD Playback Volume",
1755                .info = aureon_ac97_vol_info,
1756                .get = aureon_ac97_vol_get,
1757                .put = aureon_ac97_vol_put,
1758                .private_value = AC97_AUX|AUREON_AC97_STEREO,
1759                .tlv = { .p = db_scale_ac97_gain }
1760        },
1761        {
1762                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1763                .name = "Phono Playback Switch",
1764                .info = aureon_ac97_mute_info,
1765                .get = aureon_ac97_mute_get,
1766                .put = aureon_ac97_mute_put,
1767                .private_value = AC97_CD
1768        },
1769        {
1770                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1771                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1772                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1773                .name = "Phono Playback Volume",
1774                .info = aureon_ac97_vol_info,
1775                .get = aureon_ac97_vol_get,
1776                .put = aureon_ac97_vol_put,
1777                .private_value = AC97_CD|AUREON_AC97_STEREO,
1778                .tlv = { .p = db_scale_ac97_gain }
1779        },
1780        {
1781                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1782                .name = "Line Playback Switch",
1783                .info = aureon_ac97_mute_info,
1784                .get = aureon_ac97_mute_get,
1785                .put = aureon_ac97_mute_put,
1786                .private_value = AC97_LINE
1787        },
1788        {
1789                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1790                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1791                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1792                .name = "Line Playback Volume",
1793                .info = aureon_ac97_vol_info,
1794                .get = aureon_ac97_vol_get,
1795                .put = aureon_ac97_vol_put,
1796                .private_value = AC97_LINE|AUREON_AC97_STEREO,
1797                .tlv = { .p = db_scale_ac97_gain }
1798        },
1799        {
1800                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1801                .name = "Mic Playback Switch",
1802                .info = aureon_ac97_mute_info,
1803                .get = aureon_ac97_mute_get,
1804                .put = aureon_ac97_mute_put,
1805                .private_value = AC97_MIC
1806        },
1807        {
1808                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1809                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1810                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1811                .name = "Mic Playback Volume",
1812                .info = aureon_ac97_vol_info,
1813                .get = aureon_ac97_vol_get,
1814                .put = aureon_ac97_vol_put,
1815                .private_value = AC97_MIC,
1816                .tlv = { .p = db_scale_ac97_gain }
1817        },
1818        {
1819                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1820                .name = "Mic Boost (+20dB)",
1821                .info = aureon_ac97_micboost_info,
1822                .get = aureon_ac97_micboost_get,
1823                .put = aureon_ac97_micboost_put
1824        },
1825        {
1826                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1827                .name = "Aux Playback Switch",
1828                .info = aureon_ac97_mute_info,
1829                .get = aureon_ac97_mute_get,
1830                .put = aureon_ac97_mute_put,
1831                .private_value = AC97_VIDEO,
1832        },
1833        {
1834                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1835                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1836                                SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1837                .name = "Aux Playback Volume",
1838                .info = aureon_ac97_vol_info,
1839                .get = aureon_ac97_vol_get,
1840                .put = aureon_ac97_vol_put,
1841                .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1842                .tlv = { .p = db_scale_ac97_gain }
1843        },
1844        {
1845                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1846                .name = "Aux Source",
1847                .info = aureon_universe_inmux_info,
1848                .get = aureon_universe_inmux_get,
1849                .put = aureon_universe_inmux_put
1850        }
1851
1852};
1853
1854static struct snd_kcontrol_new cs8415_controls[] = {
1855        {
1856                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1857                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1858                .info = aureon_cs8415_mute_info,
1859                .get = aureon_cs8415_mute_get,
1860                .put = aureon_cs8415_mute_put
1861        },
1862        {
1863                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1864                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1865                .info = aureon_cs8415_mux_info,
1866                .get = aureon_cs8415_mux_get,
1867                .put = aureon_cs8415_mux_put,
1868        },
1869        {
1870                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1871                .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1872                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1873                .info = aureon_cs8415_qsub_info,
1874                .get = aureon_cs8415_qsub_get,
1875        },
1876        {
1877                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1878                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1879                .access = SNDRV_CTL_ELEM_ACCESS_READ,
1880                .info = aureon_cs8415_spdif_info,
1881                .get = aureon_cs8415_mask_get
1882        },
1883        {
1884                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1885                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1886                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1887                .info = aureon_cs8415_spdif_info,
1888                .get = aureon_cs8415_spdif_get
1889        },
1890        {
1891                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1892                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1893                .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1894                .info = aureon_cs8415_rate_info,
1895                .get = aureon_cs8415_rate_get
1896        }
1897};
1898
1899static int aureon_add_controls(struct snd_ice1712 *ice)
1900{
1901        unsigned int i, counts;
1902        int err;
1903
1904        counts = ARRAY_SIZE(aureon_dac_controls);
1905        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1906                counts -= 2; /* no side */
1907        for (i = 0; i < counts; i++) {
1908                err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1909                if (err < 0)
1910                        return err;
1911        }
1912
1913        for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1914                err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1915                if (err < 0)
1916                        return err;
1917        }
1918
1919        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1920                for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1921                        err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1922                        if (err < 0)
1923                                return err;
1924                }
1925        } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1926                 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1927                for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1928                        err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1929                        if (err < 0)
1930                                return err;
1931                }
1932        }
1933
1934        if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1935            ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1936                unsigned char id;
1937                snd_ice1712_save_gpio_status(ice);
1938                id = aureon_cs8415_get(ice, CS8415_ID);
1939                if (id != 0x41)
1940                        snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1941                else if ((id & 0x0F) != 0x01)
1942                        snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1943                else {
1944                        for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1945                                struct snd_kcontrol *kctl;
1946                                err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1947                                if (err < 0)
1948                                        return err;
1949                                if (i > 1)
1950                                        kctl->id.device = ice->pcm->device;
1951                        }
1952                }
1953                snd_ice1712_restore_gpio_status(ice);
1954        }
1955
1956        return 0;
1957}
1958
1959/*
1960 * reset the chip
1961 */
1962static int aureon_reset(struct snd_ice1712 *ice)
1963{
1964        static const unsigned short wm_inits_aureon[] = {
1965                /* These come first to reduce init pop noise */
1966                0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1967                0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1968                0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1969
1970                0x18, 0x000,            /* All power-up */
1971
1972                0x16, 0x122,            /* I2S, normal polarity, 24bit */
1973                0x17, 0x022,            /* 256fs, slave mode */
1974                0x00, 0,                /* DAC1 analog mute */
1975                0x01, 0,                /* DAC2 analog mute */
1976                0x02, 0,                /* DAC3 analog mute */
1977                0x03, 0,                /* DAC4 analog mute */
1978                0x04, 0,                /* DAC5 analog mute */
1979                0x05, 0,                /* DAC6 analog mute */
1980                0x06, 0,                /* DAC7 analog mute */
1981                0x07, 0,                /* DAC8 analog mute */
1982                0x08, 0x100,            /* master analog mute */
1983                0x09, 0xff,             /* DAC1 digital full */
1984                0x0a, 0xff,             /* DAC2 digital full */
1985                0x0b, 0xff,             /* DAC3 digital full */
1986                0x0c, 0xff,             /* DAC4 digital full */
1987                0x0d, 0xff,             /* DAC5 digital full */
1988                0x0e, 0xff,             /* DAC6 digital full */
1989                0x0f, 0xff,             /* DAC7 digital full */
1990                0x10, 0xff,             /* DAC8 digital full */
1991                0x11, 0x1ff,            /* master digital full */
1992                0x12, 0x000,            /* phase normal */
1993                0x13, 0x090,            /* unmute DAC L/R */
1994                0x14, 0x000,            /* all unmute */
1995                0x15, 0x000,            /* no deemphasis, no ZFLG */
1996                0x19, 0x000,            /* -12dB ADC/L */
1997                0x1a, 0x000,            /* -12dB ADC/R */
1998                (unsigned short)-1
1999        };
2000        static const unsigned short wm_inits_prodigy[] = {
2001
2002                /* These come first to reduce init pop noise */
2003                0x1b, 0x000,            /* ADC Mux */
2004                0x1c, 0x009,            /* Out Mux1 */
2005                0x1d, 0x009,            /* Out Mux2 */
2006
2007                0x18, 0x000,            /* All power-up */
2008
2009                0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
2010                0x17, 0x006,            /* 128fs, slave mode */
2011
2012                0x00, 0,                /* DAC1 analog mute */
2013                0x01, 0,                /* DAC2 analog mute */
2014                0x02, 0,                /* DAC3 analog mute */
2015                0x03, 0,                /* DAC4 analog mute */
2016                0x04, 0,                /* DAC5 analog mute */
2017                0x05, 0,                /* DAC6 analog mute */
2018                0x06, 0,                /* DAC7 analog mute */
2019                0x07, 0,                /* DAC8 analog mute */
2020                0x08, 0x100,            /* master analog mute */
2021
2022                0x09, 0x7f,             /* DAC1 digital full */
2023                0x0a, 0x7f,             /* DAC2 digital full */
2024                0x0b, 0x7f,             /* DAC3 digital full */
2025                0x0c, 0x7f,             /* DAC4 digital full */
2026                0x0d, 0x7f,             /* DAC5 digital full */
2027                0x0e, 0x7f,             /* DAC6 digital full */
2028                0x0f, 0x7f,             /* DAC7 digital full */
2029                0x10, 0x7f,             /* DAC8 digital full */
2030                0x11, 0x1FF,            /* master digital full */
2031
2032                0x12, 0x000,            /* phase normal */
2033                0x13, 0x090,            /* unmute DAC L/R */
2034                0x14, 0x000,            /* all unmute */
2035                0x15, 0x000,            /* no deemphasis, no ZFLG */
2036
2037                0x19, 0x000,            /* -12dB ADC/L */
2038                0x1a, 0x000,            /* -12dB ADC/R */
2039                (unsigned short)-1
2040
2041        };
2042        static const unsigned short cs_inits[] = {
2043                0x0441, /* RUN */
2044                0x0180, /* no mute, OMCK output on RMCK pin */
2045                0x0201, /* S/PDIF source on RXP1 */
2046                0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2047                (unsigned short)-1
2048        };
2049        unsigned int tmp;
2050        const unsigned short *p;
2051        int err;
2052        struct aureon_spec *spec = ice->spec;
2053
2054        err = aureon_ac97_init(ice);
2055        if (err != 0)
2056                return err;
2057
2058        snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2059
2060        /* reset the wm codec as the SPI mode */
2061        snd_ice1712_save_gpio_status(ice);
2062        snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2063
2064        tmp = snd_ice1712_gpio_read(ice);
2065        tmp &= ~AUREON_WM_RESET;
2066        snd_ice1712_gpio_write(ice, tmp);
2067        udelay(1);
2068        tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2069        snd_ice1712_gpio_write(ice, tmp);
2070        udelay(1);
2071        tmp |= AUREON_WM_RESET;
2072        snd_ice1712_gpio_write(ice, tmp);
2073        udelay(1);
2074
2075        /* initialize WM8770 codec */
2076        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2077                ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2078                ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2079                p = wm_inits_prodigy;
2080        else
2081                p = wm_inits_aureon;
2082        for (; *p != (unsigned short)-1; p += 2)
2083                wm_put(ice, p[0], p[1]);
2084
2085        /* initialize CS8415A codec */
2086        if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2087            ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2088                for (p = cs_inits; *p != (unsigned short)-1; p++)
2089                        aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2090                spec->cs8415_mux = 1;
2091
2092                aureon_set_headphone_amp(ice, 1);
2093        }
2094
2095        snd_ice1712_restore_gpio_status(ice);
2096
2097        /* initialize PCA9554 pin directions & set default input */
2098        aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2099        aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2100        return 0;
2101}
2102
2103/*
2104 * suspend/resume
2105 */
2106#ifdef CONFIG_PM_SLEEP
2107static int aureon_resume(struct snd_ice1712 *ice)
2108{
2109        struct aureon_spec *spec = ice->spec;
2110        int err, i;
2111
2112        err = aureon_reset(ice);
2113        if (err != 0)
2114                return err;
2115
2116        /* workaround for poking volume with alsamixer after resume:
2117         * just set stored volume again */
2118        for (i = 0; i < ice->num_total_dacs; i++)
2119                wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2120        return 0;
2121}
2122#endif
2123
2124/*
2125 * initialize the chip
2126 */
2127static int aureon_init(struct snd_ice1712 *ice)
2128{
2129        struct aureon_spec *spec;
2130        int i, err;
2131
2132        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2133        if (!spec)
2134                return -ENOMEM;
2135        ice->spec = spec;
2136
2137        if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2138                ice->num_total_dacs = 6;
2139                ice->num_total_adcs = 2;
2140        } else {
2141                /* aureon 7.1 and prodigy 7.1 */
2142                ice->num_total_dacs = 8;
2143                ice->num_total_adcs = 2;
2144        }
2145
2146        /* to remember the register values of CS8415 */
2147        ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2148        if (!ice->akm)
2149                return -ENOMEM;
2150        ice->akm_codecs = 1;
2151
2152        err = aureon_reset(ice);
2153        if (err != 0)
2154                return err;
2155
2156        spec->master[0] = WM_VOL_MUTE;
2157        spec->master[1] = WM_VOL_MUTE;
2158        for (i = 0; i < ice->num_total_dacs; i++) {
2159                spec->vol[i] = WM_VOL_MUTE;
2160                wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2161        }
2162
2163#ifdef CONFIG_PM_SLEEP
2164        ice->pm_resume = aureon_resume;
2165        ice->pm_suspend_enabled = 1;
2166#endif
2167
2168        return 0;
2169}
2170
2171
2172/*
2173 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2174 * hence the driver needs to sets up it properly.
2175 */
2176
2177static unsigned char aureon51_eeprom[] = {
2178        [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
2179        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2180        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2181        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2182        [ICE_EEP2_GPIO_DIR]    = 0xff,
2183        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2184        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2185        [ICE_EEP2_GPIO_MASK]   = 0x00,
2186        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2187        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2188        [ICE_EEP2_GPIO_STATE]  = 0x00,
2189        [ICE_EEP2_GPIO_STATE1] = 0x00,
2190        [ICE_EEP2_GPIO_STATE2] = 0x00,
2191};
2192
2193static unsigned char aureon71_eeprom[] = {
2194        [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
2195        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2196        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2197        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2198        [ICE_EEP2_GPIO_DIR]    = 0xff,
2199        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2200        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2201        [ICE_EEP2_GPIO_MASK]   = 0x00,
2202        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2203        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2204        [ICE_EEP2_GPIO_STATE]  = 0x00,
2205        [ICE_EEP2_GPIO_STATE1] = 0x00,
2206        [ICE_EEP2_GPIO_STATE2] = 0x00,
2207};
2208#define prodigy71_eeprom aureon71_eeprom
2209
2210static unsigned char aureon71_universe_eeprom[] = {
2211        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, spdif-in/ADC,
2212                                         * 4DACs
2213                                         */
2214        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2215        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2216        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2217        [ICE_EEP2_GPIO_DIR]    = 0xff,
2218        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2219        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2220        [ICE_EEP2_GPIO_MASK]   = 0x00,
2221        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2222        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2223        [ICE_EEP2_GPIO_STATE]  = 0x00,
2224        [ICE_EEP2_GPIO_STATE1] = 0x00,
2225        [ICE_EEP2_GPIO_STATE2] = 0x00,
2226};
2227
2228static unsigned char prodigy71lt_eeprom[] = {
2229        [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
2230        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2231        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2232        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2233        [ICE_EEP2_GPIO_DIR]    = 0xff,
2234        [ICE_EEP2_GPIO_DIR1]   = 0xff,
2235        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2236        [ICE_EEP2_GPIO_MASK]   = 0x00,
2237        [ICE_EEP2_GPIO_MASK1]  = 0x00,
2238        [ICE_EEP2_GPIO_MASK2]  = 0x00,
2239        [ICE_EEP2_GPIO_STATE]  = 0x00,
2240        [ICE_EEP2_GPIO_STATE1] = 0x00,
2241        [ICE_EEP2_GPIO_STATE2] = 0x00,
2242};
2243#define prodigy71xt_eeprom prodigy71lt_eeprom
2244
2245/* entry point */
2246struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
2247        {
2248                .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2249                .name = "Terratec Aureon 5.1-Sky",
2250                .model = "aureon51",
2251                .chip_init = aureon_init,
2252                .build_controls = aureon_add_controls,
2253                .eeprom_size = sizeof(aureon51_eeprom),
2254                .eeprom_data = aureon51_eeprom,
2255                .driver = "Aureon51",
2256        },
2257        {
2258                .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2259                .name = "Terratec Aureon 7.1-Space",
2260                .model = "aureon71",
2261                .chip_init = aureon_init,
2262                .build_controls = aureon_add_controls,
2263                .eeprom_size = sizeof(aureon71_eeprom),
2264                .eeprom_data = aureon71_eeprom,
2265                .driver = "Aureon71",
2266        },
2267        {
2268                .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2269                .name = "Terratec Aureon 7.1-Universe",
2270                .model = "universe",
2271                .chip_init = aureon_init,
2272                .build_controls = aureon_add_controls,
2273                .eeprom_size = sizeof(aureon71_universe_eeprom),
2274                .eeprom_data = aureon71_universe_eeprom,
2275                .driver = "Aureon71Univ", /* keep in 15 letters */
2276        },
2277        {
2278                .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2279                .name = "Audiotrak Prodigy 7.1",
2280                .model = "prodigy71",
2281                .chip_init = aureon_init,
2282                .build_controls = aureon_add_controls,
2283                .eeprom_size = sizeof(prodigy71_eeprom),
2284                .eeprom_data = prodigy71_eeprom,
2285                .driver = "Prodigy71", /* should be identical with Aureon71 */
2286        },
2287        {
2288                .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2289                .name = "Audiotrak Prodigy 7.1 LT",
2290                .model = "prodigy71lt",
2291                .chip_init = aureon_init,
2292                .build_controls = aureon_add_controls,
2293                .eeprom_size = sizeof(prodigy71lt_eeprom),
2294                .eeprom_data = prodigy71lt_eeprom,
2295                .driver = "Prodigy71LT",
2296        },
2297        {
2298                .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2299                .name = "Audiotrak Prodigy 7.1 XT",
2300                .model = "prodigy71xt",
2301                .chip_init = aureon_init,
2302                .build_controls = aureon_add_controls,
2303                .eeprom_size = sizeof(prodigy71xt_eeprom),
2304                .eeprom_data = prodigy71xt_eeprom,
2305                .driver = "Prodigy71LT",
2306        },
2307        { } /* terminator */
2308};
2309