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