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