1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ALSA driver for ICEnsemble VT1724 (Envy24HT) 4 * 5 * Lowlevel functions for Terratec Aureon cards 6 * 7 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de> 8 * 9 * NOTES: 10 * 11 * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data. 12 * both wm and akm codecs are pretty similar, so we can integrate 13 * both controls in the future, once if wm codecs are reused in 14 * many boards. 15 * 16 * - DAC digital volumes are not implemented in the mixer. 17 * if they show better response than DAC analog volumes, we can use them 18 * instead. 19 * 20 * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards 21 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca> 22 * 23 * version 0.82: Stable / not all features work yet (no communication with AC97 secondary) 24 * added 64x/128x oversampling switch (should be 64x only for 96khz) 25 * fixed some recording labels (still need to check the rest) 26 * recording is working probably thanks to correct wm8770 initialization 27 * 28 * version 0.5: Initial release: 29 * working: analog output, mixer, headphone amplifier switch 30 * not working: prety much everything else, at least i could verify that 31 * we have no digital output, no capture, pretty bad clicks and poops 32 * on mixer switch and other coll stuff. 33 */ 34 35 #include <linux/delay.h> 36 #include <linux/interrupt.h> 37 #include <linux/init.h> 38 #include <linux/slab.h> 39 #include <linux/mutex.h> 40 41 #include <sound/core.h> 42 43 #include "ice1712.h" 44 #include "envy24ht.h" 45 #include "aureon.h" 46 #include <sound/tlv.h> 47 48 /* AC97 register cache for Aureon */ 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 /* WM8770 registers */ 58 #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ 59 #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ 60 #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ 61 #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ 62 #define WM_PHASE_SWAP 0x12 /* DAC phase */ 63 #define WM_DAC_CTRL1 0x13 /* DAC control bits */ 64 #define WM_MUTE 0x14 /* mute controls */ 65 #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ 66 #define WM_INT_CTRL 0x16 /* interface control */ 67 #define WM_MASTER 0x17 /* master clock and mode */ 68 #define WM_POWERDOWN 0x18 /* power-down controls */ 69 #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ 70 #define WM_ADC_MUX 0x1b /* input MUX */ 71 #define WM_OUT_MUX1 0x1c /* output MUX */ 72 #define WM_OUT_MUX2 0x1e /* output MUX */ 73 #define WM_RESET 0x1f /* software reset */ 74 75 /* CS8415A registers */ 76 #define CS8415_CTRL1 0x01 77 #define CS8415_CTRL2 0x02 78 #define CS8415_QSUB 0x14 79 #define CS8415_RATIO 0x1E 80 #define CS8415_C_BUFFER 0x20 81 #define CS8415_ID 0x7F 82 83 /* PCA9554 registers */ 84 #define PCA9554_DEV 0x40 /* I2C device address */ 85 #define PCA9554_IN 0x00 /* input port */ 86 #define PCA9554_OUT 0x01 /* output port */ 87 #define PCA9554_INVERT 0x02 /* input invert */ 88 #define PCA9554_DIR 0x03 /* port directions */ 89 90 /* 91 * Aureon Universe additional controls using PCA9554 92 */ 93 94 /* 95 * Send data to pca9554 96 */ 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; /* ID 0100000, write */ 103 unsigned char val = 0; 104 105 tmp = snd_ice1712_gpio_read(ice); 106 107 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK| 108 AUREON_WM_RW|AUREON_WM_CS| 109 AUREON_CS8415_CS)); 110 tmp |= AUREON_WM_RW; 111 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */ 112 113 tmp &= ~AUREON_SPI_MOSI; 114 tmp &= ~AUREON_SPI_CLK; 115 snd_ice1712_gpio_write(ice, tmp); 116 udelay(50); 117 118 /* 119 * send i2c stop condition and start condition 120 * to obtain sane state 121 */ 122 tmp |= AUREON_SPI_CLK; 123 snd_ice1712_gpio_write(ice, tmp); 124 udelay(50); 125 tmp |= AUREON_SPI_MOSI; 126 snd_ice1712_gpio_write(ice, tmp); 127 udelay(100); 128 tmp &= ~AUREON_SPI_MOSI; 129 snd_ice1712_gpio_write(ice, tmp); 130 udelay(50); 131 tmp &= ~AUREON_SPI_CLK; 132 snd_ice1712_gpio_write(ice, tmp); 133 udelay(100); 134 /* 135 * send device address, command and value, 136 * skipping ack cycles in between 137 */ 138 for (j = 0; j < 3; j++) { 139 switch (j) { 140 case 0: 141 val = dev; 142 break; 143 case 1: 144 val = reg; 145 break; 146 case 2: 147 val = data; 148 break; 149 } 150 for (i = 7; i >= 0; i--) { 151 tmp &= ~AUREON_SPI_CLK; 152 snd_ice1712_gpio_write(ice, tmp); 153 udelay(40); 154 if (val & (1 << i)) 155 tmp |= AUREON_SPI_MOSI; 156 else 157 tmp &= ~AUREON_SPI_MOSI; 158 snd_ice1712_gpio_write(ice, tmp); 159 udelay(40); 160 tmp |= AUREON_SPI_CLK; 161 snd_ice1712_gpio_write(ice, tmp); 162 udelay(40); 163 } 164 tmp &= ~AUREON_SPI_CLK; 165 snd_ice1712_gpio_write(ice, tmp); 166 udelay(40); 167 tmp |= AUREON_SPI_CLK; 168 snd_ice1712_gpio_write(ice, tmp); 169 udelay(40); 170 tmp &= ~AUREON_SPI_CLK; 171 snd_ice1712_gpio_write(ice, tmp); 172 udelay(40); 173 } 174 tmp &= ~AUREON_SPI_CLK; 175 snd_ice1712_gpio_write(ice, tmp); 176 udelay(40); 177 tmp &= ~AUREON_SPI_MOSI; 178 snd_ice1712_gpio_write(ice, tmp); 179 udelay(40); 180 tmp |= AUREON_SPI_CLK; 181 snd_ice1712_gpio_write(ice, tmp); 182 udelay(50); 183 tmp |= AUREON_SPI_MOSI; 184 snd_ice1712_gpio_write(ice, tmp); 185 udelay(100); 186 } 187 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 /* Send address to XILINX chip */ 236 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F); 237 snd_ice1712_gpio_write(ice, tmp); 238 udelay(10); 239 tmp |= AUREON_AC97_ADDR; 240 snd_ice1712_gpio_write(ice, tmp); 241 udelay(10); 242 tmp &= ~AUREON_AC97_ADDR; 243 snd_ice1712_gpio_write(ice, tmp); 244 udelay(10); 245 246 /* Send low-order byte to XILINX chip */ 247 tmp &= ~AUREON_AC97_DATA_MASK; 248 tmp |= val & AUREON_AC97_DATA_MASK; 249 snd_ice1712_gpio_write(ice, tmp); 250 udelay(10); 251 tmp |= AUREON_AC97_DATA_LOW; 252 snd_ice1712_gpio_write(ice, tmp); 253 udelay(10); 254 tmp &= ~AUREON_AC97_DATA_LOW; 255 snd_ice1712_gpio_write(ice, tmp); 256 udelay(10); 257 258 /* Send high-order byte to XILINX chip */ 259 tmp &= ~AUREON_AC97_DATA_MASK; 260 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK; 261 262 snd_ice1712_gpio_write(ice, tmp); 263 udelay(10); 264 tmp |= AUREON_AC97_DATA_HIGH; 265 snd_ice1712_gpio_write(ice, tmp); 266 udelay(10); 267 tmp &= ~AUREON_AC97_DATA_HIGH; 268 snd_ice1712_gpio_write(ice, tmp); 269 udelay(10); 270 271 /* Instruct XILINX chip to parse the data to the STAC9744 chip */ 272 tmp |= AUREON_AC97_COMMIT; 273 snd_ice1712_gpio_write(ice, tmp); 274 udelay(10); 275 tmp &= ~AUREON_AC97_COMMIT; 276 snd_ice1712_gpio_write(ice, tmp); 277 udelay(10); 278 279 /* Store the data in out private buffer */ 280 spec->stac9744[(reg & 0x7F) >> 1] = val; 281 } 282 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 * Initialize STAC9744 chip 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 /* Cold reset */ 320 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK; 321 snd_ice1712_gpio_write(ice, tmp); 322 udelay(3); 323 324 tmp &= ~AUREON_AC97_RESET; 325 snd_ice1712_gpio_write(ice, tmp); 326 udelay(3); 327 328 tmp |= AUREON_AC97_RESET; 329 snd_ice1712_gpio_write(ice, tmp); 330 udelay(3); 331 332 memset(&spec->stac9744, 0, sizeof(spec->stac9744)); 333 for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2) 334 spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1]; 335 336 /* Unmute AC'97 master volume permanently - muting is done by WM8770 */ 337 aureon_ac97_write(ice, AC97_MASTER, 0x0000); 338 339 return 0; 340 } 341 342 #define AUREON_AC97_STEREO 0x80 343 344 /* 345 * AC'97 volume controls 346 */ 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 * AC'97 mute controls 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 * AC'97 mute controls 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 * write data in the SPI mode 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 * Read data in SPI mode 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 * get the current register value of WM codec 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 * set the register value of WM codec 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 * set the register value of WM codec and remember it 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 * AC'97 master playback mute controls (Mute on WM8770 chip) 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 /* 0dB .. -100dB */ 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 * DAC mute control 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 * Master volume attenuation mixer control 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 * DAC volume attenuation mixer control 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; /* mute (-101dB) */ 788 uinfo->value.integer.max = WM_VOL_MAX; /* 0dB */ 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 * WM8770 mute control 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 * WM8770 master mute control 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 /* digital master volume */ 930 #define PCM_0dB 0xff 931 #define PCM_RES 128 /* -64dB */ 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; /* mute (-64dB) */ 938 uinfo->value.integer.max = PCM_RES; /* 0dB */ 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); /* prelatch */ 969 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ 970 change = 1; 971 } 972 snd_ice1712_restore_gpio_status(ice); 973 return change; 974 } 975 976 /* 977 * ADC mute control 978 */ 979 #define wm_adc_mute_info snd_ctl_boolean_stereo_info 980 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 * ADC gain mixer control 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; /* -12dB */ 1024 uinfo->value.integer.max = 0x1f; /* 19dB */ 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 * ADC input mux mixer control 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", /* AIN1 */ 1072 "Aux", /* AIN2 */ 1073 "Line", /* AIN3 */ 1074 "Mic", /* AIN4 */ 1075 "AC97" /* AIN5 */ 1076 }; 1077 static const char * const universe_texts[] = { 1078 "Aux1", /* AIN1 */ 1079 "CD", /* AIN2 */ 1080 "Phono", /* AIN3 */ 1081 "Line", /* AIN4 */ 1082 "Aux2", /* AIN5 */ 1083 "Mic", /* AIN6 */ 1084 "Aux3", /* AIN7 */ 1085 "AC97" /* AIN8 */ 1086 }; 1087 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1088 1089 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) 1090 return snd_ctl_enum_info(uinfo, 2, 8, universe_texts); 1091 else 1092 return snd_ctl_enum_info(uinfo, 2, 5, texts); 1093 } 1094 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 * CS8415 Input mux 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", /* RXP0 */ 1134 "Optical" /* RXP1 */ 1135 }; 1136 static const char * const prodigy_texts[] = { 1137 "CD", 1138 "Coax" 1139 }; 1140 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) 1141 return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts); 1142 else 1143 return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts); 1144 } 1145 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 /* snd_ice1712_save_gpio_status(ice); */ 1152 /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */ 1153 ucontrol->value.enumerated.item[0] = spec->cs8415_mux; 1154 /* snd_ice1712_restore_gpio_status(ice); */ 1155 return 0; 1156 } 1157 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 * CS8415A Mute 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 * CS8415A Q-Sub info 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 * Headphone Amplifier 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 * Deemphasis 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 * ADC Oversampling 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 * mixers 1390 */ 1391 1392 static const struct snd_kcontrol_new aureon_dac_controls[] = { 1393 { 1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1395 .name = "Master Playback Switch", 1396 .info = wm_master_mute_info, 1397 .get = wm_master_mute_get, 1398 .put = wm_master_mute_put 1399 }, 1400 { 1401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1402 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1403 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1404 .name = "Master Playback Volume", 1405 .info = wm_master_vol_info, 1406 .get = wm_master_vol_get, 1407 .put = wm_master_vol_put, 1408 .tlv = { .p = db_scale_wm_dac } 1409 }, 1410 { 1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1412 .name = "Front Playback Switch", 1413 .info = wm_mute_info, 1414 .get = wm_mute_get, 1415 .put = wm_mute_put, 1416 .private_value = (2 << 8) | 0 1417 }, 1418 { 1419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1420 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1421 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1422 .name = "Front Playback Volume", 1423 .info = wm_vol_info, 1424 .get = wm_vol_get, 1425 .put = wm_vol_put, 1426 .private_value = (2 << 8) | 0, 1427 .tlv = { .p = db_scale_wm_dac } 1428 }, 1429 { 1430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1431 .name = "Rear Playback Switch", 1432 .info = wm_mute_info, 1433 .get = wm_mute_get, 1434 .put = wm_mute_put, 1435 .private_value = (2 << 8) | 2 1436 }, 1437 { 1438 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1439 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1440 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1441 .name = "Rear Playback Volume", 1442 .info = wm_vol_info, 1443 .get = wm_vol_get, 1444 .put = wm_vol_put, 1445 .private_value = (2 << 8) | 2, 1446 .tlv = { .p = db_scale_wm_dac } 1447 }, 1448 { 1449 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1450 .name = "Center Playback Switch", 1451 .info = wm_mute_info, 1452 .get = wm_mute_get, 1453 .put = wm_mute_put, 1454 .private_value = (1 << 8) | 4 1455 }, 1456 { 1457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1458 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1459 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1460 .name = "Center Playback Volume", 1461 .info = wm_vol_info, 1462 .get = wm_vol_get, 1463 .put = wm_vol_put, 1464 .private_value = (1 << 8) | 4, 1465 .tlv = { .p = db_scale_wm_dac } 1466 }, 1467 { 1468 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1469 .name = "LFE Playback Switch", 1470 .info = wm_mute_info, 1471 .get = wm_mute_get, 1472 .put = wm_mute_put, 1473 .private_value = (1 << 8) | 5 1474 }, 1475 { 1476 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1477 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1478 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1479 .name = "LFE Playback Volume", 1480 .info = wm_vol_info, 1481 .get = wm_vol_get, 1482 .put = wm_vol_put, 1483 .private_value = (1 << 8) | 5, 1484 .tlv = { .p = db_scale_wm_dac } 1485 }, 1486 { 1487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1488 .name = "Side Playback Switch", 1489 .info = wm_mute_info, 1490 .get = wm_mute_get, 1491 .put = wm_mute_put, 1492 .private_value = (2 << 8) | 6 1493 }, 1494 { 1495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1496 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1497 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1498 .name = "Side Playback Volume", 1499 .info = wm_vol_info, 1500 .get = wm_vol_get, 1501 .put = wm_vol_put, 1502 .private_value = (2 << 8) | 6, 1503 .tlv = { .p = db_scale_wm_dac } 1504 } 1505 }; 1506 1507 static const struct snd_kcontrol_new wm_controls[] = { 1508 { 1509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1510 .name = "PCM Playback Switch", 1511 .info = wm_pcm_mute_info, 1512 .get = wm_pcm_mute_get, 1513 .put = wm_pcm_mute_put 1514 }, 1515 { 1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1517 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1518 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1519 .name = "PCM Playback Volume", 1520 .info = wm_pcm_vol_info, 1521 .get = wm_pcm_vol_get, 1522 .put = wm_pcm_vol_put, 1523 .tlv = { .p = db_scale_wm_pcm } 1524 }, 1525 { 1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1527 .name = "Capture Switch", 1528 .info = wm_adc_mute_info, 1529 .get = wm_adc_mute_get, 1530 .put = wm_adc_mute_put, 1531 }, 1532 { 1533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1534 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1535 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1536 .name = "Capture Volume", 1537 .info = wm_adc_vol_info, 1538 .get = wm_adc_vol_get, 1539 .put = wm_adc_vol_put, 1540 .tlv = { .p = db_scale_wm_adc } 1541 }, 1542 { 1543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1544 .name = "Capture Source", 1545 .info = wm_adc_mux_info, 1546 .get = wm_adc_mux_get, 1547 .put = wm_adc_mux_put, 1548 .private_value = 5 1549 }, 1550 { 1551 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1552 .name = "External Amplifier", 1553 .info = aureon_hpamp_info, 1554 .get = aureon_hpamp_get, 1555 .put = aureon_hpamp_put 1556 }, 1557 { 1558 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1559 .name = "DAC Deemphasis Switch", 1560 .info = aureon_deemp_info, 1561 .get = aureon_deemp_get, 1562 .put = aureon_deemp_put 1563 }, 1564 { 1565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1566 .name = "ADC Oversampling", 1567 .info = aureon_oversampling_info, 1568 .get = aureon_oversampling_get, 1569 .put = aureon_oversampling_put 1570 } 1571 }; 1572 1573 static const struct snd_kcontrol_new ac97_controls[] = { 1574 { 1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1576 .name = "AC97 Playback Switch", 1577 .info = aureon_ac97_mmute_info, 1578 .get = aureon_ac97_mmute_get, 1579 .put = aureon_ac97_mmute_put, 1580 .private_value = AC97_MASTER 1581 }, 1582 { 1583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1584 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1585 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1586 .name = "AC97 Playback Volume", 1587 .info = aureon_ac97_vol_info, 1588 .get = aureon_ac97_vol_get, 1589 .put = aureon_ac97_vol_put, 1590 .private_value = AC97_MASTER|AUREON_AC97_STEREO, 1591 .tlv = { .p = db_scale_ac97_master } 1592 }, 1593 { 1594 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1595 .name = "CD Playback Switch", 1596 .info = aureon_ac97_mute_info, 1597 .get = aureon_ac97_mute_get, 1598 .put = aureon_ac97_mute_put, 1599 .private_value = AC97_CD 1600 }, 1601 { 1602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1603 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1604 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1605 .name = "CD Playback Volume", 1606 .info = aureon_ac97_vol_info, 1607 .get = aureon_ac97_vol_get, 1608 .put = aureon_ac97_vol_put, 1609 .private_value = AC97_CD|AUREON_AC97_STEREO, 1610 .tlv = { .p = db_scale_ac97_gain } 1611 }, 1612 { 1613 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1614 .name = "Aux Playback Switch", 1615 .info = aureon_ac97_mute_info, 1616 .get = aureon_ac97_mute_get, 1617 .put = aureon_ac97_mute_put, 1618 .private_value = AC97_AUX, 1619 }, 1620 { 1621 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1622 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1623 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1624 .name = "Aux Playback Volume", 1625 .info = aureon_ac97_vol_info, 1626 .get = aureon_ac97_vol_get, 1627 .put = aureon_ac97_vol_put, 1628 .private_value = AC97_AUX|AUREON_AC97_STEREO, 1629 .tlv = { .p = db_scale_ac97_gain } 1630 }, 1631 { 1632 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1633 .name = "Line Playback Switch", 1634 .info = aureon_ac97_mute_info, 1635 .get = aureon_ac97_mute_get, 1636 .put = aureon_ac97_mute_put, 1637 .private_value = AC97_LINE 1638 }, 1639 { 1640 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1641 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1642 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1643 .name = "Line Playback Volume", 1644 .info = aureon_ac97_vol_info, 1645 .get = aureon_ac97_vol_get, 1646 .put = aureon_ac97_vol_put, 1647 .private_value = AC97_LINE|AUREON_AC97_STEREO, 1648 .tlv = { .p = db_scale_ac97_gain } 1649 }, 1650 { 1651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1652 .name = "Mic Playback Switch", 1653 .info = aureon_ac97_mute_info, 1654 .get = aureon_ac97_mute_get, 1655 .put = aureon_ac97_mute_put, 1656 .private_value = AC97_MIC 1657 }, 1658 { 1659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1660 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1661 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1662 .name = "Mic Playback Volume", 1663 .info = aureon_ac97_vol_info, 1664 .get = aureon_ac97_vol_get, 1665 .put = aureon_ac97_vol_put, 1666 .private_value = AC97_MIC, 1667 .tlv = { .p = db_scale_ac97_gain } 1668 }, 1669 { 1670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1671 .name = "Mic Boost (+20dB)", 1672 .info = aureon_ac97_micboost_info, 1673 .get = aureon_ac97_micboost_get, 1674 .put = aureon_ac97_micboost_put 1675 } 1676 }; 1677 1678 static const struct snd_kcontrol_new universe_ac97_controls[] = { 1679 { 1680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1681 .name = "AC97 Playback Switch", 1682 .info = aureon_ac97_mmute_info, 1683 .get = aureon_ac97_mmute_get, 1684 .put = aureon_ac97_mmute_put, 1685 .private_value = AC97_MASTER 1686 }, 1687 { 1688 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1689 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1690 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1691 .name = "AC97 Playback Volume", 1692 .info = aureon_ac97_vol_info, 1693 .get = aureon_ac97_vol_get, 1694 .put = aureon_ac97_vol_put, 1695 .private_value = AC97_MASTER|AUREON_AC97_STEREO, 1696 .tlv = { .p = db_scale_ac97_master } 1697 }, 1698 { 1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1700 .name = "CD Playback Switch", 1701 .info = aureon_ac97_mute_info, 1702 .get = aureon_ac97_mute_get, 1703 .put = aureon_ac97_mute_put, 1704 .private_value = AC97_AUX 1705 }, 1706 { 1707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1708 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1709 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1710 .name = "CD Playback Volume", 1711 .info = aureon_ac97_vol_info, 1712 .get = aureon_ac97_vol_get, 1713 .put = aureon_ac97_vol_put, 1714 .private_value = AC97_AUX|AUREON_AC97_STEREO, 1715 .tlv = { .p = db_scale_ac97_gain } 1716 }, 1717 { 1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1719 .name = "Phono Playback Switch", 1720 .info = aureon_ac97_mute_info, 1721 .get = aureon_ac97_mute_get, 1722 .put = aureon_ac97_mute_put, 1723 .private_value = AC97_CD 1724 }, 1725 { 1726 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1727 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1728 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1729 .name = "Phono Playback Volume", 1730 .info = aureon_ac97_vol_info, 1731 .get = aureon_ac97_vol_get, 1732 .put = aureon_ac97_vol_put, 1733 .private_value = AC97_CD|AUREON_AC97_STEREO, 1734 .tlv = { .p = db_scale_ac97_gain } 1735 }, 1736 { 1737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1738 .name = "Line Playback Switch", 1739 .info = aureon_ac97_mute_info, 1740 .get = aureon_ac97_mute_get, 1741 .put = aureon_ac97_mute_put, 1742 .private_value = AC97_LINE 1743 }, 1744 { 1745 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1746 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1747 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1748 .name = "Line Playback Volume", 1749 .info = aureon_ac97_vol_info, 1750 .get = aureon_ac97_vol_get, 1751 .put = aureon_ac97_vol_put, 1752 .private_value = AC97_LINE|AUREON_AC97_STEREO, 1753 .tlv = { .p = db_scale_ac97_gain } 1754 }, 1755 { 1756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1757 .name = "Mic Playback Switch", 1758 .info = aureon_ac97_mute_info, 1759 .get = aureon_ac97_mute_get, 1760 .put = aureon_ac97_mute_put, 1761 .private_value = AC97_MIC 1762 }, 1763 { 1764 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1765 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1766 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1767 .name = "Mic Playback Volume", 1768 .info = aureon_ac97_vol_info, 1769 .get = aureon_ac97_vol_get, 1770 .put = aureon_ac97_vol_put, 1771 .private_value = AC97_MIC, 1772 .tlv = { .p = db_scale_ac97_gain } 1773 }, 1774 { 1775 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1776 .name = "Mic Boost (+20dB)", 1777 .info = aureon_ac97_micboost_info, 1778 .get = aureon_ac97_micboost_get, 1779 .put = aureon_ac97_micboost_put 1780 }, 1781 { 1782 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1783 .name = "Aux Playback Switch", 1784 .info = aureon_ac97_mute_info, 1785 .get = aureon_ac97_mute_get, 1786 .put = aureon_ac97_mute_put, 1787 .private_value = AC97_VIDEO, 1788 }, 1789 { 1790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1791 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1792 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1793 .name = "Aux Playback Volume", 1794 .info = aureon_ac97_vol_info, 1795 .get = aureon_ac97_vol_get, 1796 .put = aureon_ac97_vol_put, 1797 .private_value = AC97_VIDEO|AUREON_AC97_STEREO, 1798 .tlv = { .p = db_scale_ac97_gain } 1799 }, 1800 { 1801 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1802 .name = "Aux Source", 1803 .info = aureon_universe_inmux_info, 1804 .get = aureon_universe_inmux_get, 1805 .put = aureon_universe_inmux_put 1806 } 1807 1808 }; 1809 1810 static const struct snd_kcontrol_new cs8415_controls[] = { 1811 { 1812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1813 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), 1814 .info = aureon_cs8415_mute_info, 1815 .get = aureon_cs8415_mute_get, 1816 .put = aureon_cs8415_mute_put 1817 }, 1818 { 1819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1820 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source", 1821 .info = aureon_cs8415_mux_info, 1822 .get = aureon_cs8415_mux_get, 1823 .put = aureon_cs8415_mux_put, 1824 }, 1825 { 1826 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1827 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT), 1828 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 1829 .info = aureon_cs8415_qsub_info, 1830 .get = aureon_cs8415_qsub_get, 1831 }, 1832 { 1833 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1834 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), 1835 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1836 .info = aureon_cs8415_spdif_info, 1837 .get = aureon_cs8415_mask_get 1838 }, 1839 { 1840 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1841 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), 1842 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 1843 .info = aureon_cs8415_spdif_info, 1844 .get = aureon_cs8415_spdif_get 1845 }, 1846 { 1847 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1848 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate", 1849 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 1850 .info = aureon_cs8415_rate_info, 1851 .get = aureon_cs8415_rate_get 1852 } 1853 }; 1854 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; /* no side */ 1863 for (i = 0; i < counts; i++) { 1864 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice)); 1865 if (err < 0) 1866 return err; 1867 } 1868 1869 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { 1870 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice)); 1871 if (err < 0) 1872 return err; 1873 } 1874 1875 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { 1876 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) { 1877 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice)); 1878 if (err < 0) 1879 return err; 1880 } 1881 } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 1882 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 1883 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { 1884 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); 1885 if (err < 0) 1886 return err; 1887 } 1888 } 1889 1890 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 1891 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 1892 unsigned char id; 1893 snd_ice1712_save_gpio_status(ice); 1894 id = aureon_cs8415_get(ice, CS8415_ID); 1895 snd_ice1712_restore_gpio_status(ice); 1896 if (id != 0x41) 1897 dev_info(ice->card->dev, 1898 "No CS8415 chip. Skipping CS8415 controls.\n"); 1899 else { 1900 for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { 1901 struct snd_kcontrol *kctl; 1902 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice))); 1903 if (err < 0) 1904 return err; 1905 if (i > 1) 1906 kctl->id.device = ice->pcm->device; 1907 } 1908 } 1909 } 1910 1911 return 0; 1912 } 1913 1914 /* 1915 * reset the chip 1916 */ 1917 static int aureon_reset(struct snd_ice1712 *ice) 1918 { 1919 static const unsigned short wm_inits_aureon[] = { 1920 /* These come first to reduce init pop noise */ 1921 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 1922 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 1923 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ 1924 1925 0x18, 0x000, /* All power-up */ 1926 1927 0x16, 0x122, /* I2S, normal polarity, 24bit */ 1928 0x17, 0x022, /* 256fs, slave mode */ 1929 0x00, 0, /* DAC1 analog mute */ 1930 0x01, 0, /* DAC2 analog mute */ 1931 0x02, 0, /* DAC3 analog mute */ 1932 0x03, 0, /* DAC4 analog mute */ 1933 0x04, 0, /* DAC5 analog mute */ 1934 0x05, 0, /* DAC6 analog mute */ 1935 0x06, 0, /* DAC7 analog mute */ 1936 0x07, 0, /* DAC8 analog mute */ 1937 0x08, 0x100, /* master analog mute */ 1938 0x09, 0xff, /* DAC1 digital full */ 1939 0x0a, 0xff, /* DAC2 digital full */ 1940 0x0b, 0xff, /* DAC3 digital full */ 1941 0x0c, 0xff, /* DAC4 digital full */ 1942 0x0d, 0xff, /* DAC5 digital full */ 1943 0x0e, 0xff, /* DAC6 digital full */ 1944 0x0f, 0xff, /* DAC7 digital full */ 1945 0x10, 0xff, /* DAC8 digital full */ 1946 0x11, 0x1ff, /* master digital full */ 1947 0x12, 0x000, /* phase normal */ 1948 0x13, 0x090, /* unmute DAC L/R */ 1949 0x14, 0x000, /* all unmute */ 1950 0x15, 0x000, /* no deemphasis, no ZFLG */ 1951 0x19, 0x000, /* -12dB ADC/L */ 1952 0x1a, 0x000, /* -12dB ADC/R */ 1953 (unsigned short)-1 1954 }; 1955 static const unsigned short wm_inits_prodigy[] = { 1956 1957 /* These come first to reduce init pop noise */ 1958 0x1b, 0x000, /* ADC Mux */ 1959 0x1c, 0x009, /* Out Mux1 */ 1960 0x1d, 0x009, /* Out Mux2 */ 1961 1962 0x18, 0x000, /* All power-up */ 1963 1964 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */ 1965 0x17, 0x006, /* 128fs, slave mode */ 1966 1967 0x00, 0, /* DAC1 analog mute */ 1968 0x01, 0, /* DAC2 analog mute */ 1969 0x02, 0, /* DAC3 analog mute */ 1970 0x03, 0, /* DAC4 analog mute */ 1971 0x04, 0, /* DAC5 analog mute */ 1972 0x05, 0, /* DAC6 analog mute */ 1973 0x06, 0, /* DAC7 analog mute */ 1974 0x07, 0, /* DAC8 analog mute */ 1975 0x08, 0x100, /* master analog mute */ 1976 1977 0x09, 0x7f, /* DAC1 digital full */ 1978 0x0a, 0x7f, /* DAC2 digital full */ 1979 0x0b, 0x7f, /* DAC3 digital full */ 1980 0x0c, 0x7f, /* DAC4 digital full */ 1981 0x0d, 0x7f, /* DAC5 digital full */ 1982 0x0e, 0x7f, /* DAC6 digital full */ 1983 0x0f, 0x7f, /* DAC7 digital full */ 1984 0x10, 0x7f, /* DAC8 digital full */ 1985 0x11, 0x1FF, /* master digital full */ 1986 1987 0x12, 0x000, /* phase normal */ 1988 0x13, 0x090, /* unmute DAC L/R */ 1989 0x14, 0x000, /* all unmute */ 1990 0x15, 0x000, /* no deemphasis, no ZFLG */ 1991 1992 0x19, 0x000, /* -12dB ADC/L */ 1993 0x1a, 0x000, /* -12dB ADC/R */ 1994 (unsigned short)-1 1995 1996 }; 1997 static const unsigned short cs_inits[] = { 1998 0x0441, /* RUN */ 1999 0x0180, /* no mute, OMCK output on RMCK pin */ 2000 0x0201, /* S/PDIF source on RXP1 */ 2001 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ 2002 (unsigned short)-1 2003 }; 2004 unsigned int tmp; 2005 const unsigned short *p; 2006 int err; 2007 struct aureon_spec *spec = ice->spec; 2008 2009 err = aureon_ac97_init(ice); 2010 if (err != 0) 2011 return err; 2012 2013 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ 2014 2015 /* reset the wm codec as the SPI mode */ 2016 snd_ice1712_save_gpio_status(ice); 2017 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL)); 2018 2019 tmp = snd_ice1712_gpio_read(ice); 2020 tmp &= ~AUREON_WM_RESET; 2021 snd_ice1712_gpio_write(ice, tmp); 2022 udelay(1); 2023 tmp |= AUREON_WM_CS | AUREON_CS8415_CS; 2024 snd_ice1712_gpio_write(ice, tmp); 2025 udelay(1); 2026 tmp |= AUREON_WM_RESET; 2027 snd_ice1712_gpio_write(ice, tmp); 2028 udelay(1); 2029 2030 /* initialize WM8770 codec */ 2031 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 || 2032 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || 2033 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) 2034 p = wm_inits_prodigy; 2035 else 2036 p = wm_inits_aureon; 2037 for (; *p != (unsigned short)-1; p += 2) 2038 wm_put(ice, p[0], p[1]); 2039 2040 /* initialize CS8415A codec */ 2041 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && 2042 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { 2043 for (p = cs_inits; *p != (unsigned short)-1; p++) 2044 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); 2045 spec->cs8415_mux = 1; 2046 2047 aureon_set_headphone_amp(ice, 1); 2048 } 2049 2050 snd_ice1712_restore_gpio_status(ice); 2051 2052 /* initialize PCA9554 pin directions & set default input */ 2053 aureon_pca9554_write(ice, PCA9554_DIR, 0x00); 2054 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ 2055 return 0; 2056 } 2057 2058 /* 2059 * suspend/resume 2060 */ 2061 #ifdef CONFIG_PM_SLEEP 2062 static int aureon_resume(struct snd_ice1712 *ice) 2063 { 2064 struct aureon_spec *spec = ice->spec; 2065 int err, i; 2066 2067 err = aureon_reset(ice); 2068 if (err != 0) 2069 return err; 2070 2071 /* workaround for poking volume with alsamixer after resume: 2072 * just set stored volume again */ 2073 for (i = 0; i < ice->num_total_dacs; i++) 2074 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 2075 return 0; 2076 } 2077 #endif 2078 2079 /* 2080 * initialize the chip 2081 */ 2082 static int aureon_init(struct snd_ice1712 *ice) 2083 { 2084 struct aureon_spec *spec; 2085 int i, err; 2086 2087 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2088 if (!spec) 2089 return -ENOMEM; 2090 ice->spec = spec; 2091 2092 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { 2093 ice->num_total_dacs = 6; 2094 ice->num_total_adcs = 2; 2095 } else { 2096 /* aureon 7.1 and prodigy 7.1 */ 2097 ice->num_total_dacs = 8; 2098 ice->num_total_adcs = 2; 2099 } 2100 2101 /* to remember the register values of CS8415 */ 2102 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); 2103 if (!ice->akm) 2104 return -ENOMEM; 2105 ice->akm_codecs = 1; 2106 2107 err = aureon_reset(ice); 2108 if (err != 0) 2109 return err; 2110 2111 spec->master[0] = WM_VOL_MUTE; 2112 spec->master[1] = WM_VOL_MUTE; 2113 for (i = 0; i < ice->num_total_dacs; i++) { 2114 spec->vol[i] = WM_VOL_MUTE; 2115 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 2116 } 2117 2118 #ifdef CONFIG_PM_SLEEP 2119 ice->pm_resume = aureon_resume; 2120 ice->pm_suspend_enabled = 1; 2121 #endif 2122 2123 return 0; 2124 } 2125 2126 2127 /* 2128 * Aureon boards don't provide the EEPROM data except for the vendor IDs. 2129 * hence the driver needs to sets up it properly. 2130 */ 2131 2132 static const unsigned char aureon51_eeprom[] = { 2133 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */ 2134 [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 2135 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 2136 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 2137 [ICE_EEP2_GPIO_DIR] = 0xff, 2138 [ICE_EEP2_GPIO_DIR1] = 0xff, 2139 [ICE_EEP2_GPIO_DIR2] = 0x5f, 2140 [ICE_EEP2_GPIO_MASK] = 0x00, 2141 [ICE_EEP2_GPIO_MASK1] = 0x00, 2142 [ICE_EEP2_GPIO_MASK2] = 0x00, 2143 [ICE_EEP2_GPIO_STATE] = 0x00, 2144 [ICE_EEP2_GPIO_STATE1] = 0x00, 2145 [ICE_EEP2_GPIO_STATE2] = 0x00, 2146 }; 2147 2148 static const unsigned char aureon71_eeprom[] = { 2149 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */ 2150 [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 2151 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 2152 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 2153 [ICE_EEP2_GPIO_DIR] = 0xff, 2154 [ICE_EEP2_GPIO_DIR1] = 0xff, 2155 [ICE_EEP2_GPIO_DIR2] = 0x5f, 2156 [ICE_EEP2_GPIO_MASK] = 0x00, 2157 [ICE_EEP2_GPIO_MASK1] = 0x00, 2158 [ICE_EEP2_GPIO_MASK2] = 0x00, 2159 [ICE_EEP2_GPIO_STATE] = 0x00, 2160 [ICE_EEP2_GPIO_STATE1] = 0x00, 2161 [ICE_EEP2_GPIO_STATE2] = 0x00, 2162 }; 2163 #define prodigy71_eeprom aureon71_eeprom 2164 2165 static const unsigned char aureon71_universe_eeprom[] = { 2166 [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, 2167 * 4DACs 2168 */ 2169 [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 2170 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 2171 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 2172 [ICE_EEP2_GPIO_DIR] = 0xff, 2173 [ICE_EEP2_GPIO_DIR1] = 0xff, 2174 [ICE_EEP2_GPIO_DIR2] = 0x5f, 2175 [ICE_EEP2_GPIO_MASK] = 0x00, 2176 [ICE_EEP2_GPIO_MASK1] = 0x00, 2177 [ICE_EEP2_GPIO_MASK2] = 0x00, 2178 [ICE_EEP2_GPIO_STATE] = 0x00, 2179 [ICE_EEP2_GPIO_STATE1] = 0x00, 2180 [ICE_EEP2_GPIO_STATE2] = 0x00, 2181 }; 2182 2183 static const unsigned char prodigy71lt_eeprom[] = { 2184 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */ 2185 [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 2186 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ 2187 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 2188 [ICE_EEP2_GPIO_DIR] = 0xff, 2189 [ICE_EEP2_GPIO_DIR1] = 0xff, 2190 [ICE_EEP2_GPIO_DIR2] = 0x5f, 2191 [ICE_EEP2_GPIO_MASK] = 0x00, 2192 [ICE_EEP2_GPIO_MASK1] = 0x00, 2193 [ICE_EEP2_GPIO_MASK2] = 0x00, 2194 [ICE_EEP2_GPIO_STATE] = 0x00, 2195 [ICE_EEP2_GPIO_STATE1] = 0x00, 2196 [ICE_EEP2_GPIO_STATE2] = 0x00, 2197 }; 2198 #define prodigy71xt_eeprom prodigy71lt_eeprom 2199 2200 /* entry point */ 2201 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = { 2202 { 2203 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY, 2204 .name = "Terratec Aureon 5.1-Sky", 2205 .model = "aureon51", 2206 .chip_init = aureon_init, 2207 .build_controls = aureon_add_controls, 2208 .eeprom_size = sizeof(aureon51_eeprom), 2209 .eeprom_data = aureon51_eeprom, 2210 .driver = "Aureon51", 2211 }, 2212 { 2213 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE, 2214 .name = "Terratec Aureon 7.1-Space", 2215 .model = "aureon71", 2216 .chip_init = aureon_init, 2217 .build_controls = aureon_add_controls, 2218 .eeprom_size = sizeof(aureon71_eeprom), 2219 .eeprom_data = aureon71_eeprom, 2220 .driver = "Aureon71", 2221 }, 2222 { 2223 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE, 2224 .name = "Terratec Aureon 7.1-Universe", 2225 .model = "universe", 2226 .chip_init = aureon_init, 2227 .build_controls = aureon_add_controls, 2228 .eeprom_size = sizeof(aureon71_universe_eeprom), 2229 .eeprom_data = aureon71_universe_eeprom, 2230 .driver = "Aureon71Univ", /* keep in 15 letters */ 2231 }, 2232 { 2233 .subvendor = VT1724_SUBDEVICE_PRODIGY71, 2234 .name = "Audiotrak Prodigy 7.1", 2235 .model = "prodigy71", 2236 .chip_init = aureon_init, 2237 .build_controls = aureon_add_controls, 2238 .eeprom_size = sizeof(prodigy71_eeprom), 2239 .eeprom_data = prodigy71_eeprom, 2240 .driver = "Prodigy71", /* should be identical with Aureon71 */ 2241 }, 2242 { 2243 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT, 2244 .name = "Audiotrak Prodigy 7.1 LT", 2245 .model = "prodigy71lt", 2246 .chip_init = aureon_init, 2247 .build_controls = aureon_add_controls, 2248 .eeprom_size = sizeof(prodigy71lt_eeprom), 2249 .eeprom_data = prodigy71lt_eeprom, 2250 .driver = "Prodigy71LT", 2251 }, 2252 { 2253 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT, 2254 .name = "Audiotrak Prodigy 7.1 XT", 2255 .model = "prodigy71xt", 2256 .chip_init = aureon_init, 2257 .build_controls = aureon_add_controls, 2258 .eeprom_size = sizeof(prodigy71xt_eeprom), 2259 .eeprom_data = prodigy71xt_eeprom, 2260 .driver = "Prodigy71LT", 2261 }, 2262 { } /* terminator */ 2263 }; 2264