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