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