This source file includes following definitions.
- aureon_pca9554_write
- aureon_universe_inmux_info
- aureon_universe_inmux_get
- aureon_universe_inmux_put
- aureon_ac97_write
- aureon_ac97_read
- aureon_ac97_init
- aureon_ac97_vol_info
- aureon_ac97_vol_get
- aureon_ac97_vol_put
- aureon_ac97_mute_get
- aureon_ac97_mute_put
- aureon_ac97_micboost_get
- aureon_ac97_micboost_put
- aureon_spi_write
- aureon_spi_read
- aureon_cs8415_get
- aureon_cs8415_read
- aureon_cs8415_put
- wm_get
- wm_put_nocache
- wm_put
- aureon_ac97_mmute_get
- aureon_ac97_mmute_put
- wm_set_vol
- wm_pcm_mute_get
- wm_pcm_mute_put
- wm_master_vol_info
- wm_master_vol_get
- wm_master_vol_put
- wm_vol_info
- wm_vol_get
- wm_vol_put
- wm_mute_info
- wm_mute_get
- wm_mute_put
- wm_master_mute_get
- wm_master_mute_put
- wm_pcm_vol_info
- wm_pcm_vol_get
- wm_pcm_vol_put
- wm_adc_mute_get
- wm_adc_mute_put
- wm_adc_vol_info
- wm_adc_vol_get
- wm_adc_vol_put
- wm_adc_mux_info
- wm_adc_mux_get
- wm_adc_mux_put
- aureon_cs8415_mux_info
- aureon_cs8415_mux_get
- aureon_cs8415_mux_put
- aureon_cs8415_rate_info
- aureon_cs8415_rate_get
- aureon_cs8415_mute_get
- aureon_cs8415_mute_put
- aureon_cs8415_qsub_info
- aureon_cs8415_qsub_get
- aureon_cs8415_spdif_info
- aureon_cs8415_mask_get
- aureon_cs8415_spdif_get
- aureon_set_headphone_amp
- aureon_get_headphone_amp
- aureon_hpamp_get
- aureon_hpamp_put
- aureon_deemp_get
- aureon_deemp_put
- aureon_oversampling_info
- aureon_oversampling_get
- aureon_oversampling_put
- aureon_add_controls
- aureon_reset
- aureon_resume
- aureon_init
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  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 
  49 struct 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 
  58 #define WM_DAC_ATTEN            0x00    
  59 #define WM_DAC_MASTER_ATTEN     0x08    
  60 #define WM_DAC_DIG_ATTEN        0x09    
  61 #define WM_DAC_DIG_MASTER_ATTEN 0x11    
  62 #define WM_PHASE_SWAP           0x12    
  63 #define WM_DAC_CTRL1            0x13    
  64 #define WM_MUTE                 0x14    
  65 #define WM_DAC_CTRL2            0x15    
  66 #define WM_INT_CTRL             0x16    
  67 #define WM_MASTER               0x17    
  68 #define WM_POWERDOWN            0x18    
  69 #define WM_ADC_GAIN             0x19    
  70 #define WM_ADC_MUX              0x1b    
  71 #define WM_OUT_MUX1             0x1c    
  72 #define WM_OUT_MUX2             0x1e    
  73 #define WM_RESET                0x1f    
  74 
  75 
  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 
  84 #define PCA9554_DEV     0x40            
  85 #define PCA9554_IN      0x00            
  86 #define PCA9554_OUT     0x01            
  87 #define PCA9554_INVERT  0x02            
  88 #define PCA9554_DIR     0x03            
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 static 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;  
 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; 
 112 
 113         tmp &= ~AUREON_SPI_MOSI;
 114         tmp &= ~AUREON_SPI_CLK;
 115         snd_ice1712_gpio_write(ice, tmp);
 116         udelay(50);
 117 
 118         
 119 
 120 
 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 
 136 
 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 
 188 static 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 
 197 static 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 
 206 static 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 
 229 static 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         
 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         
 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         
 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         
 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         
 280         spec->stac9744[(reg & 0x7F) >> 1] = val;
 281 }
 282 
 283 static 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 
 291 
 292 static 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         
 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         
 337         aureon_ac97_write(ice, AC97_MASTER, 0x0000);
 338 
 339         return 0;
 340 }
 341 
 342 #define AUREON_AC97_STEREO      0x80
 343 
 344 
 345 
 346 
 347 static 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 
 356 static 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 
 372 static 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 
 397 
 398 #define aureon_ac97_mute_info   snd_ctl_boolean_mono_info
 399 
 400 static 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 
 413 static 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 
 435 
 436 #define aureon_ac97_micboost_info       snd_ctl_boolean_mono_info
 437 
 438 static 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 
 450 static 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 
 472 
 473 static 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 
 525 
 526 static 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 
 578 static 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 
 586 static 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 
 593 static 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 
 601 
 602 static 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 
 611 
 612 static 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 
 623 
 624 static 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 
 638 
 639 #define aureon_ac97_mmute_info          snd_ctl_boolean_mono_info
 640 
 641 static 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 
 653 static 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 
 672 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1);
 673 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 674 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
 675 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
 676 static 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     
 680 #define WM_VOL_MUTE     0x8000
 681 
 682 static 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 
 700 
 701 #define wm_pcm_mute_info        snd_ctl_boolean_mono_info
 702 
 703 static 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 
 713 static 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 
 732 
 733 static 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 
 742 static 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 
 753 static 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 
 781 
 782 static 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;           
 788         uinfo->value.integer.max = WM_VOL_MAX;  
 789         return 0;
 790 }
 791 
 792 static 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 
 806 static 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 
 835 
 836 static 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 
 845 static 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 
 860 static 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 
 888 
 889 #define wm_master_mute_info             snd_ctl_boolean_stereo_info
 890 
 891 static 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 
 903 static 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 
 930 #define PCM_0dB 0xff
 931 #define PCM_RES 128     
 932 #define PCM_MIN (PCM_0dB - PCM_RES)
 933 static 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;           
 938         uinfo->value.integer.max = PCM_RES;     
 939         return 0;
 940 }
 941 
 942 static 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 
 955 static 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); 
 969                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); 
 970                 change = 1;
 971         }
 972         snd_ice1712_restore_gpio_status(ice);
 973         return change;
 974 }
 975 
 976 
 977 
 978 
 979 #define wm_adc_mute_info                snd_ctl_boolean_stereo_info
 980 
 981 static 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 
 996 static 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 
1018 
1019 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1020 {
1021         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1022         uinfo->count = 2;
1023         uinfo->value.integer.min = 0;           
1024         uinfo->value.integer.max = 0x1f;        
1025         return 0;
1026 }
1027 
1028 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1029 {
1030         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031         int i, idx;
1032         unsigned short vol;
1033 
1034         mutex_lock(&ice->gpio_mutex);
1035         for (i = 0; i < 2; i++) {
1036                 idx = WM_ADC_GAIN + i;
1037                 vol = wm_get(ice, idx) & 0x1f;
1038                 ucontrol->value.integer.value[i] = vol;
1039         }
1040         mutex_unlock(&ice->gpio_mutex);
1041         return 0;
1042 }
1043 
1044 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045 {
1046         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1047         int i, idx;
1048         unsigned short ovol, nvol;
1049         int change = 0;
1050 
1051         snd_ice1712_save_gpio_status(ice);
1052         for (i = 0; i < 2; i++) {
1053                 idx  = WM_ADC_GAIN + i;
1054                 nvol = ucontrol->value.integer.value[i] & 0x1f;
1055                 ovol = wm_get(ice, idx);
1056                 if ((ovol & 0x1f) != nvol) {
1057                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058                         change = 1;
1059                 }
1060         }
1061         snd_ice1712_restore_gpio_status(ice);
1062         return change;
1063 }
1064 
1065 
1066 
1067 
1068 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1069 {
1070         static const char * const texts[] = {
1071                 "CD",           
1072                 "Aux",          
1073                 "Line",         
1074                 "Mic",          
1075                 "AC97"          
1076         };
1077         static const char * const universe_texts[] = {
1078                 "Aux1",         
1079                 "CD",           
1080                 "Phono",        
1081                 "Line",         
1082                 "Aux2",         
1083                 "Mic",          
1084                 "Aux3",         
1085                 "AC97"          
1086         };
1087         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1088 
1089         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE)
1090                 return snd_ctl_enum_info(uinfo, 2, 8, universe_texts);
1091         else
1092                 return snd_ctl_enum_info(uinfo, 2, 5, texts);
1093 }
1094 
1095 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1096 {
1097         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1098         unsigned short val;
1099 
1100         mutex_lock(&ice->gpio_mutex);
1101         val = wm_get(ice, WM_ADC_MUX);
1102         ucontrol->value.enumerated.item[0] = val & 7;
1103         ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1104         mutex_unlock(&ice->gpio_mutex);
1105         return 0;
1106 }
1107 
1108 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1109 {
1110         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1111         unsigned short oval, nval;
1112         int change;
1113 
1114         snd_ice1712_save_gpio_status(ice);
1115         oval = wm_get(ice, WM_ADC_MUX);
1116         nval = oval & ~0x77;
1117         nval |= ucontrol->value.enumerated.item[0] & 7;
1118         nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1119         change = (oval != nval);
1120         if (change)
1121                 wm_put(ice, WM_ADC_MUX, nval);
1122         snd_ice1712_restore_gpio_status(ice);
1123         return change;
1124 }
1125 
1126 
1127 
1128 
1129 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130 {
1131         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1132         static const char * const aureon_texts[] = {
1133                 "CD",           
1134                 "Optical"       
1135         };
1136         static const char * const prodigy_texts[] = {
1137                 "CD",
1138                 "Coax"
1139         };
1140         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1141                 return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts);
1142         else
1143                 return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts);
1144 }
1145 
1146 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1147 {
1148         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1149         struct aureon_spec *spec = ice->spec;
1150 
1151         
1152         
1153         ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1154         
1155         return 0;
1156 }
1157 
1158 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1159 {
1160         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1161         struct aureon_spec *spec = ice->spec;
1162         unsigned short oval, nval;
1163         int change;
1164 
1165         snd_ice1712_save_gpio_status(ice);
1166         oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1167         nval = oval & ~0x07;
1168         nval |= ucontrol->value.enumerated.item[0] & 7;
1169         change = (oval != nval);
1170         if (change)
1171                 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1172         snd_ice1712_restore_gpio_status(ice);
1173         spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1174         return change;
1175 }
1176 
1177 static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1178 {
1179         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1180         uinfo->count = 1;
1181         uinfo->value.integer.min = 0;
1182         uinfo->value.integer.max = 192000;
1183         return 0;
1184 }
1185 
1186 static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1187 {
1188         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1189         unsigned char ratio;
1190         ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1191         ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1192         return 0;
1193 }
1194 
1195 
1196 
1197 
1198 #define aureon_cs8415_mute_info         snd_ctl_boolean_mono_info
1199 
1200 static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1201 {
1202         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1203         snd_ice1712_save_gpio_status(ice);
1204         ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1205         snd_ice1712_restore_gpio_status(ice);
1206         return 0;
1207 }
1208 
1209 static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1210 {
1211         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212         unsigned char oval, nval;
1213         int change;
1214         snd_ice1712_save_gpio_status(ice);
1215         oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1216         if (ucontrol->value.integer.value[0])
1217                 nval = oval & ~0x20;
1218         else
1219                 nval = oval | 0x20;
1220         change = (oval != nval);
1221         if (change)
1222                 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1223         snd_ice1712_restore_gpio_status(ice);
1224         return change;
1225 }
1226 
1227 
1228 
1229 
1230 static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1231 {
1232         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1233         uinfo->count = 10;
1234         return 0;
1235 }
1236 
1237 static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1238 {
1239         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240 
1241         snd_ice1712_save_gpio_status(ice);
1242         aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1243         snd_ice1712_restore_gpio_status(ice);
1244 
1245         return 0;
1246 }
1247 
1248 static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1249 {
1250         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1251         uinfo->count = 1;
1252         return 0;
1253 }
1254 
1255 static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1256 {
1257         memset(ucontrol->value.iec958.status, 0xFF, 24);
1258         return 0;
1259 }
1260 
1261 static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1262 {
1263         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1264 
1265         snd_ice1712_save_gpio_status(ice);
1266         aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1267         snd_ice1712_restore_gpio_status(ice);
1268         return 0;
1269 }
1270 
1271 
1272 
1273 
1274 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1275 {
1276         unsigned int tmp, tmp2;
1277 
1278         tmp2 = tmp = snd_ice1712_gpio_read(ice);
1279         if (enable)
1280                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1281                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1282                         tmp |= AUREON_HP_SEL;
1283                 else
1284                         tmp |= PRODIGY_HP_SEL;
1285         else
1286                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1287                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1288                         tmp &= ~AUREON_HP_SEL;
1289                 else
1290                         tmp &= ~PRODIGY_HP_SEL;
1291         if (tmp != tmp2) {
1292                 snd_ice1712_gpio_write(ice, tmp);
1293                 return 1;
1294         }
1295         return 0;
1296 }
1297 
1298 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1299 {
1300         unsigned int tmp = snd_ice1712_gpio_read(ice);
1301 
1302         return (tmp & AUREON_HP_SEL) != 0;
1303 }
1304 
1305 #define aureon_hpamp_info       snd_ctl_boolean_mono_info
1306 
1307 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1308 {
1309         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1310 
1311         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1312         return 0;
1313 }
1314 
1315 
1316 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1317 {
1318         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1319 
1320         return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1321 }
1322 
1323 
1324 
1325 
1326 
1327 #define aureon_deemp_info       snd_ctl_boolean_mono_info
1328 
1329 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1330 {
1331         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1332         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1333         return 0;
1334 }
1335 
1336 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1337 {
1338         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1339         int temp, temp2;
1340         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1341         if (ucontrol->value.integer.value[0])
1342                 temp |= 0xf;
1343         else
1344                 temp &= ~0xf;
1345         if (temp != temp2) {
1346                 wm_put(ice, WM_DAC_CTRL2, temp);
1347                 return 1;
1348         }
1349         return 0;
1350 }
1351 
1352 
1353 
1354 
1355 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1356 {
1357         static const char * const texts[2] = { "128x", "64x"    };
1358 
1359         return snd_ctl_enum_info(uinfo, 1, 2, texts);
1360 }
1361 
1362 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363 {
1364         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1365         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1366         return 0;
1367 }
1368 
1369 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1370 {
1371         int temp, temp2;
1372         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1373 
1374         temp2 = temp = wm_get(ice, WM_MASTER);
1375 
1376         if (ucontrol->value.enumerated.item[0])
1377                 temp |= 0x8;
1378         else
1379                 temp &= ~0x8;
1380 
1381         if (temp != temp2) {
1382                 wm_put(ice, WM_MASTER, temp);
1383                 return 1;
1384         }
1385         return 0;
1386 }
1387 
1388 
1389 
1390 
1391 
1392 static struct snd_kcontrol_new aureon_dac_controls[] = {
1393         {
1394                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395                 .name = "Master Playback Switch",
1396                 .info = wm_master_mute_info,
1397                 .get = wm_master_mute_get,
1398                 .put = wm_master_mute_put
1399         },
1400         {
1401                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1402                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1403                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1404                 .name = "Master Playback Volume",
1405                 .info = wm_master_vol_info,
1406                 .get = wm_master_vol_get,
1407                 .put = wm_master_vol_put,
1408                 .tlv = { .p = db_scale_wm_dac }
1409         },
1410         {
1411                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412                 .name = "Front Playback Switch",
1413                 .info = wm_mute_info,
1414                 .get = wm_mute_get,
1415                 .put = wm_mute_put,
1416                 .private_value = (2 << 8) | 0
1417         },
1418         {
1419                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1421                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1422                 .name = "Front Playback Volume",
1423                 .info = wm_vol_info,
1424                 .get = wm_vol_get,
1425                 .put = wm_vol_put,
1426                 .private_value = (2 << 8) | 0,
1427                 .tlv = { .p = db_scale_wm_dac }
1428         },
1429         {
1430                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1431                 .name = "Rear Playback Switch",
1432                 .info = wm_mute_info,
1433                 .get = wm_mute_get,
1434                 .put = wm_mute_put,
1435                 .private_value = (2 << 8) | 2
1436         },
1437         {
1438                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1440                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1441                 .name = "Rear Playback Volume",
1442                 .info = wm_vol_info,
1443                 .get = wm_vol_get,
1444                 .put = wm_vol_put,
1445                 .private_value = (2 << 8) | 2,
1446                 .tlv = { .p = db_scale_wm_dac }
1447         },
1448         {
1449                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1450                 .name = "Center Playback Switch",
1451                 .info = wm_mute_info,
1452                 .get = wm_mute_get,
1453                 .put = wm_mute_put,
1454                 .private_value = (1 << 8) | 4
1455         },
1456         {
1457                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1458                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1459                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1460                 .name = "Center Playback Volume",
1461                 .info = wm_vol_info,
1462                 .get = wm_vol_get,
1463                 .put = wm_vol_put,
1464                 .private_value = (1 << 8) | 4,
1465                 .tlv = { .p = db_scale_wm_dac }
1466         },
1467         {
1468                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1469                 .name = "LFE Playback Switch",
1470                 .info = wm_mute_info,
1471                 .get = wm_mute_get,
1472                 .put = wm_mute_put,
1473                 .private_value = (1 << 8) | 5
1474         },
1475         {
1476                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1477                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1478                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1479                 .name = "LFE Playback Volume",
1480                 .info = wm_vol_info,
1481                 .get = wm_vol_get,
1482                 .put = wm_vol_put,
1483                 .private_value = (1 << 8) | 5,
1484                 .tlv = { .p = db_scale_wm_dac }
1485         },
1486         {
1487                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1488                 .name = "Side Playback Switch",
1489                 .info = wm_mute_info,
1490                 .get = wm_mute_get,
1491                 .put = wm_mute_put,
1492                 .private_value = (2 << 8) | 6
1493         },
1494         {
1495                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1496                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1497                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1498                 .name = "Side Playback Volume",
1499                 .info = wm_vol_info,
1500                 .get = wm_vol_get,
1501                 .put = wm_vol_put,
1502                 .private_value = (2 << 8) | 6,
1503                 .tlv = { .p = db_scale_wm_dac }
1504         }
1505 };
1506 
1507 static struct snd_kcontrol_new wm_controls[] = {
1508         {
1509                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1510                 .name = "PCM Playback Switch",
1511                 .info = wm_pcm_mute_info,
1512                 .get = wm_pcm_mute_get,
1513                 .put = wm_pcm_mute_put
1514         },
1515         {
1516                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1519                 .name = "PCM Playback Volume",
1520                 .info = wm_pcm_vol_info,
1521                 .get = wm_pcm_vol_get,
1522                 .put = wm_pcm_vol_put,
1523                 .tlv = { .p = db_scale_wm_pcm }
1524         },
1525         {
1526                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527                 .name = "Capture Switch",
1528                 .info = wm_adc_mute_info,
1529                 .get = wm_adc_mute_get,
1530                 .put = wm_adc_mute_put,
1531         },
1532         {
1533                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1536                 .name = "Capture Volume",
1537                 .info = wm_adc_vol_info,
1538                 .get = wm_adc_vol_get,
1539                 .put = wm_adc_vol_put,
1540                 .tlv = { .p = db_scale_wm_adc }
1541         },
1542         {
1543                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544                 .name = "Capture Source",
1545                 .info = wm_adc_mux_info,
1546                 .get = wm_adc_mux_get,
1547                 .put = wm_adc_mux_put,
1548                 .private_value = 5
1549         },
1550         {
1551                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1552                 .name = "External Amplifier",
1553                 .info = aureon_hpamp_info,
1554                 .get = aureon_hpamp_get,
1555                 .put = aureon_hpamp_put
1556         },
1557         {
1558                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1559                 .name = "DAC Deemphasis Switch",
1560                 .info = aureon_deemp_info,
1561                 .get = aureon_deemp_get,
1562                 .put = aureon_deemp_put
1563         },
1564         {
1565                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566                 .name = "ADC Oversampling",
1567                 .info = aureon_oversampling_info,
1568                 .get = aureon_oversampling_get,
1569                 .put = aureon_oversampling_put
1570         }
1571 };
1572 
1573 static struct snd_kcontrol_new ac97_controls[] = {
1574         {
1575                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576                 .name = "AC97 Playback Switch",
1577                 .info = aureon_ac97_mmute_info,
1578                 .get = aureon_ac97_mmute_get,
1579                 .put = aureon_ac97_mmute_put,
1580                 .private_value = AC97_MASTER
1581         },
1582         {
1583                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1585                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1586                 .name = "AC97 Playback Volume",
1587                 .info = aureon_ac97_vol_info,
1588                 .get = aureon_ac97_vol_get,
1589                 .put = aureon_ac97_vol_put,
1590                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1591                 .tlv = { .p = db_scale_ac97_master }
1592         },
1593         {
1594                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595                 .name = "CD Playback Switch",
1596                 .info = aureon_ac97_mute_info,
1597                 .get = aureon_ac97_mute_get,
1598                 .put = aureon_ac97_mute_put,
1599                 .private_value = AC97_CD
1600         },
1601         {
1602                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1604                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1605                 .name = "CD Playback Volume",
1606                 .info = aureon_ac97_vol_info,
1607                 .get = aureon_ac97_vol_get,
1608                 .put = aureon_ac97_vol_put,
1609                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1610                 .tlv = { .p = db_scale_ac97_gain }
1611         },
1612         {
1613                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1614                 .name = "Aux Playback Switch",
1615                 .info = aureon_ac97_mute_info,
1616                 .get = aureon_ac97_mute_get,
1617                 .put = aureon_ac97_mute_put,
1618                 .private_value = AC97_AUX,
1619         },
1620         {
1621                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1623                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1624                 .name = "Aux Playback Volume",
1625                 .info = aureon_ac97_vol_info,
1626                 .get = aureon_ac97_vol_get,
1627                 .put = aureon_ac97_vol_put,
1628                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1629                 .tlv = { .p = db_scale_ac97_gain }
1630         },
1631         {
1632                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1633                 .name = "Line Playback Switch",
1634                 .info = aureon_ac97_mute_info,
1635                 .get = aureon_ac97_mute_get,
1636                 .put = aureon_ac97_mute_put,
1637                 .private_value = AC97_LINE
1638         },
1639         {
1640                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1641                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1642                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1643                 .name = "Line Playback Volume",
1644                 .info = aureon_ac97_vol_info,
1645                 .get = aureon_ac97_vol_get,
1646                 .put = aureon_ac97_vol_put,
1647                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1648                 .tlv = { .p = db_scale_ac97_gain }
1649         },
1650         {
1651                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1652                 .name = "Mic Playback Switch",
1653                 .info = aureon_ac97_mute_info,
1654                 .get = aureon_ac97_mute_get,
1655                 .put = aureon_ac97_mute_put,
1656                 .private_value = AC97_MIC
1657         },
1658         {
1659                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1661                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1662                 .name = "Mic Playback Volume",
1663                 .info = aureon_ac97_vol_info,
1664                 .get = aureon_ac97_vol_get,
1665                 .put = aureon_ac97_vol_put,
1666                 .private_value = AC97_MIC,
1667                 .tlv = { .p = db_scale_ac97_gain }
1668         },
1669         {
1670                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671                 .name = "Mic Boost (+20dB)",
1672                 .info = aureon_ac97_micboost_info,
1673                 .get = aureon_ac97_micboost_get,
1674                 .put = aureon_ac97_micboost_put
1675         }
1676 };
1677 
1678 static struct snd_kcontrol_new universe_ac97_controls[] = {
1679         {
1680                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681                 .name = "AC97 Playback Switch",
1682                 .info = aureon_ac97_mmute_info,
1683                 .get = aureon_ac97_mmute_get,
1684                 .put = aureon_ac97_mmute_put,
1685                 .private_value = AC97_MASTER
1686         },
1687         {
1688                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1689                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1690                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1691                 .name = "AC97 Playback Volume",
1692                 .info = aureon_ac97_vol_info,
1693                 .get = aureon_ac97_vol_get,
1694                 .put = aureon_ac97_vol_put,
1695                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1696                 .tlv = { .p = db_scale_ac97_master }
1697         },
1698         {
1699                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700                 .name = "CD Playback Switch",
1701                 .info = aureon_ac97_mute_info,
1702                 .get = aureon_ac97_mute_get,
1703                 .put = aureon_ac97_mute_put,
1704                 .private_value = AC97_AUX
1705         },
1706         {
1707                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1709                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1710                 .name = "CD Playback Volume",
1711                 .info = aureon_ac97_vol_info,
1712                 .get = aureon_ac97_vol_get,
1713                 .put = aureon_ac97_vol_put,
1714                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1715                 .tlv = { .p = db_scale_ac97_gain }
1716         },
1717         {
1718                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719                 .name = "Phono Playback Switch",
1720                 .info = aureon_ac97_mute_info,
1721                 .get = aureon_ac97_mute_get,
1722                 .put = aureon_ac97_mute_put,
1723                 .private_value = AC97_CD
1724         },
1725         {
1726                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1727                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1728                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1729                 .name = "Phono Playback Volume",
1730                 .info = aureon_ac97_vol_info,
1731                 .get = aureon_ac97_vol_get,
1732                 .put = aureon_ac97_vol_put,
1733                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1734                 .tlv = { .p = db_scale_ac97_gain }
1735         },
1736         {
1737                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1738                 .name = "Line Playback Switch",
1739                 .info = aureon_ac97_mute_info,
1740                 .get = aureon_ac97_mute_get,
1741                 .put = aureon_ac97_mute_put,
1742                 .private_value = AC97_LINE
1743         },
1744         {
1745                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1747                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1748                 .name = "Line Playback Volume",
1749                 .info = aureon_ac97_vol_info,
1750                 .get = aureon_ac97_vol_get,
1751                 .put = aureon_ac97_vol_put,
1752                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1753                 .tlv = { .p = db_scale_ac97_gain }
1754         },
1755         {
1756                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1757                 .name = "Mic Playback Switch",
1758                 .info = aureon_ac97_mute_info,
1759                 .get = aureon_ac97_mute_get,
1760                 .put = aureon_ac97_mute_put,
1761                 .private_value = AC97_MIC
1762         },
1763         {
1764                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1766                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1767                 .name = "Mic Playback Volume",
1768                 .info = aureon_ac97_vol_info,
1769                 .get = aureon_ac97_vol_get,
1770                 .put = aureon_ac97_vol_put,
1771                 .private_value = AC97_MIC,
1772                 .tlv = { .p = db_scale_ac97_gain }
1773         },
1774         {
1775                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1776                 .name = "Mic Boost (+20dB)",
1777                 .info = aureon_ac97_micboost_info,
1778                 .get = aureon_ac97_micboost_get,
1779                 .put = aureon_ac97_micboost_put
1780         },
1781         {
1782                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1783                 .name = "Aux Playback Switch",
1784                 .info = aureon_ac97_mute_info,
1785                 .get = aureon_ac97_mute_get,
1786                 .put = aureon_ac97_mute_put,
1787                 .private_value = AC97_VIDEO,
1788         },
1789         {
1790                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1792                                 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1793                 .name = "Aux Playback Volume",
1794                 .info = aureon_ac97_vol_info,
1795                 .get = aureon_ac97_vol_get,
1796                 .put = aureon_ac97_vol_put,
1797                 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1798                 .tlv = { .p = db_scale_ac97_gain }
1799         },
1800         {
1801                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1802                 .name = "Aux Source",
1803                 .info = aureon_universe_inmux_info,
1804                 .get = aureon_universe_inmux_get,
1805                 .put = aureon_universe_inmux_put
1806         }
1807 
1808 };
1809 
1810 static struct snd_kcontrol_new cs8415_controls[] = {
1811         {
1812                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1813                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1814                 .info = aureon_cs8415_mute_info,
1815                 .get = aureon_cs8415_mute_get,
1816                 .put = aureon_cs8415_mute_put
1817         },
1818         {
1819                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1820                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1821                 .info = aureon_cs8415_mux_info,
1822                 .get = aureon_cs8415_mux_get,
1823                 .put = aureon_cs8415_mux_put,
1824         },
1825         {
1826                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1827                 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1828                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1829                 .info = aureon_cs8415_qsub_info,
1830                 .get = aureon_cs8415_qsub_get,
1831         },
1832         {
1833                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1834                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1835                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1836                 .info = aureon_cs8415_spdif_info,
1837                 .get = aureon_cs8415_mask_get
1838         },
1839         {
1840                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1841                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1842                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1843                 .info = aureon_cs8415_spdif_info,
1844                 .get = aureon_cs8415_spdif_get
1845         },
1846         {
1847                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1848                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1849                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1850                 .info = aureon_cs8415_rate_info,
1851                 .get = aureon_cs8415_rate_get
1852         }
1853 };
1854 
1855 static int aureon_add_controls(struct snd_ice1712 *ice)
1856 {
1857         unsigned int i, counts;
1858         int err;
1859 
1860         counts = ARRAY_SIZE(aureon_dac_controls);
1861         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1862                 counts -= 2; 
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 
1920 
1921 static int aureon_reset(struct snd_ice1712 *ice)
1922 {
1923         static const unsigned short wm_inits_aureon[] = {
1924                 
1925                 0x1b, 0x044,            
1926                 0x1c, 0x00B,            
1927                 0x1d, 0x009,            
1928 
1929                 0x18, 0x000,            
1930 
1931                 0x16, 0x122,            
1932                 0x17, 0x022,            
1933                 0x00, 0,                
1934                 0x01, 0,                
1935                 0x02, 0,                
1936                 0x03, 0,                
1937                 0x04, 0,                
1938                 0x05, 0,                
1939                 0x06, 0,                
1940                 0x07, 0,                
1941                 0x08, 0x100,            
1942                 0x09, 0xff,             
1943                 0x0a, 0xff,             
1944                 0x0b, 0xff,             
1945                 0x0c, 0xff,             
1946                 0x0d, 0xff,             
1947                 0x0e, 0xff,             
1948                 0x0f, 0xff,             
1949                 0x10, 0xff,             
1950                 0x11, 0x1ff,            
1951                 0x12, 0x000,            
1952                 0x13, 0x090,            
1953                 0x14, 0x000,            
1954                 0x15, 0x000,            
1955                 0x19, 0x000,            
1956                 0x1a, 0x000,            
1957                 (unsigned short)-1
1958         };
1959         static const unsigned short wm_inits_prodigy[] = {
1960 
1961                 
1962                 0x1b, 0x000,            
1963                 0x1c, 0x009,            
1964                 0x1d, 0x009,            
1965 
1966                 0x18, 0x000,            
1967 
1968                 0x16, 0x022,            
1969                 0x17, 0x006,            
1970 
1971                 0x00, 0,                
1972                 0x01, 0,                
1973                 0x02, 0,                
1974                 0x03, 0,                
1975                 0x04, 0,                
1976                 0x05, 0,                
1977                 0x06, 0,                
1978                 0x07, 0,                
1979                 0x08, 0x100,            
1980 
1981                 0x09, 0x7f,             
1982                 0x0a, 0x7f,             
1983                 0x0b, 0x7f,             
1984                 0x0c, 0x7f,             
1985                 0x0d, 0x7f,             
1986                 0x0e, 0x7f,             
1987                 0x0f, 0x7f,             
1988                 0x10, 0x7f,             
1989                 0x11, 0x1FF,            
1990 
1991                 0x12, 0x000,            
1992                 0x13, 0x090,            
1993                 0x14, 0x000,            
1994                 0x15, 0x000,            
1995 
1996                 0x19, 0x000,            
1997                 0x1a, 0x000,            
1998                 (unsigned short)-1
1999 
2000         };
2001         static const unsigned short cs_inits[] = {
2002                 0x0441, 
2003                 0x0180, 
2004                 0x0201, 
2005                 0x0605, 
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); 
2018 
2019         
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         
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         
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         
2057         aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2058         aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   
2059         return 0;
2060 }
2061 
2062 
2063 
2064 
2065 #ifdef CONFIG_PM_SLEEP
2066 static int aureon_resume(struct snd_ice1712 *ice)
2067 {
2068         struct aureon_spec *spec = ice->spec;
2069         int err, i;
2070 
2071         err = aureon_reset(ice);
2072         if (err != 0)
2073                 return err;
2074 
2075         
2076 
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 
2085 
2086 static int aureon_init(struct snd_ice1712 *ice)
2087 {
2088         struct aureon_spec *spec;
2089         int i, err;
2090 
2091         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2092         if (!spec)
2093                 return -ENOMEM;
2094         ice->spec = spec;
2095 
2096         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2097                 ice->num_total_dacs = 6;
2098                 ice->num_total_adcs = 2;
2099         } else {
2100                 
2101                 ice->num_total_dacs = 8;
2102                 ice->num_total_adcs = 2;
2103         }
2104 
2105         
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 
2133 
2134 
2135 
2136 static unsigned char aureon51_eeprom[] = {
2137         [ICE_EEP2_SYSCONF]     = 0x0a,  
2138         [ICE_EEP2_ACLINK]      = 0x80,  
2139         [ICE_EEP2_I2S]         = 0xfc,  
2140         [ICE_EEP2_SPDIF]       = 0xc3,  
2141         [ICE_EEP2_GPIO_DIR]    = 0xff,
2142         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2143         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2144         [ICE_EEP2_GPIO_MASK]   = 0x00,
2145         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2146         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2147         [ICE_EEP2_GPIO_STATE]  = 0x00,
2148         [ICE_EEP2_GPIO_STATE1] = 0x00,
2149         [ICE_EEP2_GPIO_STATE2] = 0x00,
2150 };
2151 
2152 static unsigned char aureon71_eeprom[] = {
2153         [ICE_EEP2_SYSCONF]     = 0x0b,  
2154         [ICE_EEP2_ACLINK]      = 0x80,  
2155         [ICE_EEP2_I2S]         = 0xfc,  
2156         [ICE_EEP2_SPDIF]       = 0xc3,  
2157         [ICE_EEP2_GPIO_DIR]    = 0xff,
2158         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2159         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2160         [ICE_EEP2_GPIO_MASK]   = 0x00,
2161         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2162         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2163         [ICE_EEP2_GPIO_STATE]  = 0x00,
2164         [ICE_EEP2_GPIO_STATE1] = 0x00,
2165         [ICE_EEP2_GPIO_STATE2] = 0x00,
2166 };
2167 #define prodigy71_eeprom aureon71_eeprom
2168 
2169 static unsigned char aureon71_universe_eeprom[] = {
2170         [ICE_EEP2_SYSCONF]     = 0x2b,  
2171 
2172 
2173         [ICE_EEP2_ACLINK]      = 0x80,  
2174         [ICE_EEP2_I2S]         = 0xfc,  
2175         [ICE_EEP2_SPDIF]       = 0xc3,  
2176         [ICE_EEP2_GPIO_DIR]    = 0xff,
2177         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2178         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2179         [ICE_EEP2_GPIO_MASK]   = 0x00,
2180         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2181         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2182         [ICE_EEP2_GPIO_STATE]  = 0x00,
2183         [ICE_EEP2_GPIO_STATE1] = 0x00,
2184         [ICE_EEP2_GPIO_STATE2] = 0x00,
2185 };
2186 
2187 static unsigned char prodigy71lt_eeprom[] = {
2188         [ICE_EEP2_SYSCONF]     = 0x4b,  
2189         [ICE_EEP2_ACLINK]      = 0x80,  
2190         [ICE_EEP2_I2S]         = 0xfc,  
2191         [ICE_EEP2_SPDIF]       = 0xc3,  
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 
2205 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
2206         {
2207                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2208                 .name = "Terratec Aureon 5.1-Sky",
2209                 .model = "aureon51",
2210                 .chip_init = aureon_init,
2211                 .build_controls = aureon_add_controls,
2212                 .eeprom_size = sizeof(aureon51_eeprom),
2213                 .eeprom_data = aureon51_eeprom,
2214                 .driver = "Aureon51",
2215         },
2216         {
2217                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2218                 .name = "Terratec Aureon 7.1-Space",
2219                 .model = "aureon71",
2220                 .chip_init = aureon_init,
2221                 .build_controls = aureon_add_controls,
2222                 .eeprom_size = sizeof(aureon71_eeprom),
2223                 .eeprom_data = aureon71_eeprom,
2224                 .driver = "Aureon71",
2225         },
2226         {
2227                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2228                 .name = "Terratec Aureon 7.1-Universe",
2229                 .model = "universe",
2230                 .chip_init = aureon_init,
2231                 .build_controls = aureon_add_controls,
2232                 .eeprom_size = sizeof(aureon71_universe_eeprom),
2233                 .eeprom_data = aureon71_universe_eeprom,
2234                 .driver = "Aureon71Univ", 
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", 
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         { } 
2267 };