1 /* 2 * ALSA driver for ICEnsemble VT1724 (Envy24HT) 3 * 4 * Lowlevel functions for AudioTrak Prodigy 192 cards 5 * Supported IEC958 input from optional MI/ODI/O add-on card. 6 * 7 * Specifics (SW, HW): 8 * ------------------- 9 * * 49.5MHz crystal 10 * * SPDIF-OUT on the card: 11 * - coax (through isolation transformer)/toslink supplied by 12 * 74HC04 gates - 3 in parallel 13 * - output switched between on-board CD drive dig-out connector 14 * and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled 15 * by GPIO20 (0 = CD dig-out, 1 = SPDTX) 16 * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax 17 * 18 * * MI/ODI/O card: AK4114 based, used for iec958 input only 19 * - toslink input -> RX0 20 * - coax input -> RX1 21 * - 4wire protocol: 22 * AK4114 ICE1724 23 * ------------------------------ 24 * CDTO (pin 32) -- GPIO11 pin 86 25 * CDTI (pin 33) -- GPIO10 pin 77 26 * CCLK (pin 34) -- GPIO9 pin 76 27 * CSN (pin 35) -- GPIO8 pin 75 28 * - output data Mode 7 (24bit, I2S, slave) 29 * - both MCKO1 and MCKO2 of ak4114 are fed to FPGA, which 30 * outputs master clock to SPMCLKIN of ice1724. 31 * Experimentally I found out that only a combination of 32 * OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 - 33 * VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct 34 * sampling rate. That means the the FPGA doubles the 35 * MCK01 rate. 36 * 37 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de> 38 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca> 39 * Copyright (c) 2004 Kouichi ONO <co2b@ceres.dti.ne.jp> 40 * 41 * This program is free software; you can redistribute it and/or modify 42 * it under the terms of the GNU General Public License as published by 43 * the Free Software Foundation; either version 2 of the License, or 44 * (at your option) any later version. 45 * 46 * This program is distributed in the hope that it will be useful, 47 * but WITHOUT ANY WARRANTY; without even the implied warranty of 48 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 49 * GNU General Public License for more details. 50 * 51 * You should have received a copy of the GNU General Public License 52 * along with this program; if not, write to the Free Software 53 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 54 * 55 */ 56 57 #include <sound/driver.h> 58 #include <asm/io.h> 59 #include <linux/delay.h> 60 #include <linux/interrupt.h> 61 #include <linux/init.h> 62 #include <linux/slab.h> 63 #include <sound/core.h> 64 65 #include "ice1712.h" 66 #include "envy24ht.h" 67 #include "prodigy192.h" 68 #include "stac946x.h" 69 #include <sound/tlv.h> 70 71 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) 72 { 73 snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val); 74 } 75 76 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) 77 { 78 return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg); 79 } 80 81 /* 82 * DAC mute control 83 */ 84 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info 85 86 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 87 { 88 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 89 unsigned char val; 90 int idx; 91 92 if (kcontrol->private_value) 93 idx = STAC946X_MASTER_VOLUME; 94 else 95 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; 96 val = stac9460_get(ice, idx); 97 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; 98 return 0; 99 } 100 101 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 102 { 103 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 104 unsigned char new, old; 105 int idx; 106 int change; 107 108 if (kcontrol->private_value) 109 idx = STAC946X_MASTER_VOLUME; 110 else 111 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; 112 old = stac9460_get(ice, idx); 113 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); 114 change = (new != old); 115 if (change) 116 stac9460_put(ice, idx, new); 117 118 return change; 119 } 120 121 /* 122 * DAC volume attenuation mixer control 123 */ 124 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 125 { 126 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 127 uinfo->count = 1; 128 uinfo->value.integer.min = 0; /* mute */ 129 uinfo->value.integer.max = 0x7f; /* 0dB */ 130 return 0; 131 } 132 133 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 134 { 135 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 136 int idx; 137 unsigned char vol; 138 139 if (kcontrol->private_value) 140 idx = STAC946X_MASTER_VOLUME; 141 else 142 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; 143 vol = stac9460_get(ice, idx) & 0x7f; 144 ucontrol->value.integer.value[0] = 0x7f - vol; 145 146 return 0; 147 } 148 149 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 150 { 151 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 152 int idx; 153 unsigned char tmp, ovol, nvol; 154 int change; 155 156 if (kcontrol->private_value) 157 idx = STAC946X_MASTER_VOLUME; 158 else 159 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; 160 nvol = ucontrol->value.integer.value[0]; 161 tmp = stac9460_get(ice, idx); 162 ovol = 0x7f - (tmp & 0x7f); 163 change = (ovol != nvol); 164 if (change) { 165 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 166 } 167 return change; 168 } 169 170 /* 171 * ADC mute control 172 */ 173 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info 174 175 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 176 { 177 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 178 unsigned char val; 179 int i; 180 181 for (i = 0; i < 2; ++i) { 182 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); 183 ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 184 } 185 186 return 0; 187 } 188 189 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 190 { 191 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 192 unsigned char new, old; 193 int i, reg; 194 int change; 195 196 for (i = 0; i < 2; ++i) { 197 reg = STAC946X_MIC_L_VOLUME + i; 198 old = stac9460_get(ice, reg); 199 new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80); 200 change = (new != old); 201 if (change) 202 stac9460_put(ice, reg, new); 203 } 204 205 return change; 206 } 207 208 /* 209 * ADC gain mixer control 210 */ 211 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 212 { 213 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 214 uinfo->count = 2; 215 uinfo->value.integer.min = 0; /* 0dB */ 216 uinfo->value.integer.max = 0x0f; /* 22.5dB */ 217 return 0; 218 } 219 220 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 221 { 222 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 223 int i, reg; 224 unsigned char vol; 225 226 for (i = 0; i < 2; ++i) { 227 reg = STAC946X_MIC_L_VOLUME + i; 228 vol = stac9460_get(ice, reg) & 0x0f; 229 ucontrol->value.integer.value[i] = 0x0f - vol; 230 } 231 232 return 0; 233 } 234 235 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 236 { 237 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 238 int i, reg; 239 unsigned char ovol, nvol; 240 int change; 241 242 for (i = 0; i < 2; ++i) { 243 reg = STAC946X_MIC_L_VOLUME + i; 244 nvol = ucontrol->value.integer.value[i]; 245 ovol = 0x0f - stac9460_get(ice, reg); 246 change = ((ovol & 0x0f) != nvol); 247 if (change) 248 stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f)); 249 } 250 251 return change; 252 } 253 254 #if 0 255 /* 256 * Headphone Amplifier 257 */ 258 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) 259 { 260 unsigned int tmp, tmp2; 261 262 tmp2 = tmp = snd_ice1712_gpio_read(ice); 263 if (enable) 264 tmp |= AUREON_HP_SEL; 265 else 266 tmp &= ~ AUREON_HP_SEL; 267 if (tmp != tmp2) { 268 snd_ice1712_gpio_write(ice, tmp); 269 return 1; 270 } 271 return 0; 272 } 273 274 static int aureon_get_headphone_amp(struct snd_ice1712 *ice) 275 { 276 unsigned int tmp = snd_ice1712_gpio_read(ice); 277 278 return ( tmp & AUREON_HP_SEL )!= 0; 279 } 280 281 #define aureon_bool_info snd_ctl_boolean_mono_info 282 283 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 284 { 285 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 286 287 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice); 288 return 0; 289 } 290 291 292 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 293 { 294 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 295 296 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]); 297 } 298 299 /* 300 * Deemphasis 301 */ 302 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 303 { 304 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 305 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; 306 return 0; 307 } 308 309 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 310 { 311 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 312 int temp, temp2; 313 temp2 = temp = wm_get(ice, WM_DAC_CTRL2); 314 if (ucontrol->value.integer.value[0]) 315 temp |= 0xf; 316 else 317 temp &= ~0xf; 318 if (temp != temp2) { 319 wm_put(ice, WM_DAC_CTRL2, temp); 320 return 1; 321 } 322 return 0; 323 } 324 325 /* 326 * ADC Oversampling 327 */ 328 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) 329 { 330 static char *texts[2] = { "128x", "64x" }; 331 332 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 333 uinfo->count = 1; 334 uinfo->value.enumerated.items = 2; 335 336 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 337 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 338 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 339 340 return 0; 341 } 342 343 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 344 { 345 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 346 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; 347 return 0; 348 } 349 350 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 351 { 352 int temp, temp2; 353 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 354 355 temp2 = temp = wm_get(ice, WM_MASTER); 356 357 if (ucontrol->value.enumerated.item[0]) 358 temp |= 0x8; 359 else 360 temp &= ~0x8; 361 362 if (temp != temp2) { 363 wm_put(ice, WM_MASTER, temp); 364 return 1; 365 } 366 return 0; 367 } 368 #endif 369 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, 370 struct snd_ctl_elem_info *uinfo) 371 { 372 static char *texts[2] = { "Line In", "Mic" }; 373 374 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 375 uinfo->count = 1; 376 uinfo->value.enumerated.items = 2; 377 378 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 379 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 380 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 381 382 return 0; 383 } 384 385 386 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, 387 struct snd_ctl_elem_value *ucontrol) 388 { 389 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 390 unsigned char val; 391 392 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 393 ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1; 394 return 0; 395 } 396 397 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, 398 struct snd_ctl_elem_value *ucontrol) 399 { 400 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 401 unsigned char new, old; 402 int change; 403 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 404 new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80); 405 change = (new != old); 406 if (change) 407 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 408 return change; 409 } 410 411 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); 412 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); 413 414 /* 415 * mixers 416 */ 417 418 static struct snd_kcontrol_new stac_controls[] __devinitdata = { 419 { 420 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 421 .name = "Master Playback Switch", 422 .info = stac9460_dac_mute_info, 423 .get = stac9460_dac_mute_get, 424 .put = stac9460_dac_mute_put, 425 .private_value = 1, 426 .tlv = { .p = db_scale_dac } 427 }, 428 { 429 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 430 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 431 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 432 .name = "Master Playback Volume", 433 .info = stac9460_dac_vol_info, 434 .get = stac9460_dac_vol_get, 435 .put = stac9460_dac_vol_put, 436 .private_value = 1, 437 .tlv = { .p = db_scale_dac } 438 }, 439 { 440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 441 .name = "DAC Switch", 442 .count = 6, 443 .info = stac9460_dac_mute_info, 444 .get = stac9460_dac_mute_get, 445 .put = stac9460_dac_mute_put, 446 }, 447 { 448 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 449 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 450 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 451 .name = "DAC Volume", 452 .count = 6, 453 .info = stac9460_dac_vol_info, 454 .get = stac9460_dac_vol_get, 455 .put = stac9460_dac_vol_put, 456 .tlv = { .p = db_scale_dac } 457 }, 458 { 459 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 460 .name = "ADC Capture Switch", 461 .count = 1, 462 .info = stac9460_adc_mute_info, 463 .get = stac9460_adc_mute_get, 464 .put = stac9460_adc_mute_put, 465 466 }, 467 { 468 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 469 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 470 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 471 .name = "ADC Capture Volume", 472 .count = 1, 473 .info = stac9460_adc_vol_info, 474 .get = stac9460_adc_vol_get, 475 .put = stac9460_adc_vol_put, 476 .tlv = { .p = db_scale_adc } 477 }, 478 { 479 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 480 .name = "Analog Capture Input", 481 .info = stac9460_mic_sw_info, 482 .get = stac9460_mic_sw_get, 483 .put = stac9460_mic_sw_put, 484 485 }, 486 #if 0 487 { 488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 489 .name = "Capture Route", 490 .info = wm_adc_mux_info, 491 .get = wm_adc_mux_get, 492 .put = wm_adc_mux_put, 493 }, 494 { 495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 496 .name = "Headphone Amplifier Switch", 497 .info = aureon_bool_info, 498 .get = aureon_hpamp_get, 499 .put = aureon_hpamp_put 500 }, 501 { 502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 503 .name = "DAC Deemphasis Switch", 504 .info = aureon_bool_info, 505 .get = aureon_deemp_get, 506 .put = aureon_deemp_put 507 }, 508 { 509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 510 .name = "ADC Oversampling", 511 .info = aureon_oversampling_info, 512 .get = aureon_oversampling_get, 513 .put = aureon_oversampling_put 514 }, 515 #endif 516 }; 517 518 519 /* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ 520 /* CDTO (pin 32) -- GPIO11 pin 86 521 * CDTI (pin 33) -- GPIO10 pin 77 522 * CCLK (pin 34) -- GPIO9 pin 76 523 * CSN (pin 35) -- GPIO8 pin 75 524 */ 525 #define AK4114_ADDR 0x00 /* C1-C0: Chip Address 526 * (According to datasheet fixed to “00”) 527 */ 528 529 /* 530 * 4wire ak4114 protocol - writing data 531 */ 532 static void write_data(struct snd_ice1712 *ice, unsigned int gpio, 533 unsigned int data, int idx) 534 { 535 for (; idx >= 0; idx--) { 536 /* drop clock */ 537 gpio &= ~VT1724_PRODIGY192_CCLK; 538 snd_ice1712_gpio_write(ice, gpio); 539 udelay(1); 540 /* set data */ 541 if (data & (1 << idx)) 542 gpio |= VT1724_PRODIGY192_CDOUT; 543 else 544 gpio &= ~VT1724_PRODIGY192_CDOUT; 545 snd_ice1712_gpio_write(ice, gpio); 546 udelay(1); 547 /* raise clock */ 548 gpio |= VT1724_PRODIGY192_CCLK; 549 snd_ice1712_gpio_write(ice, gpio); 550 udelay(1); 551 } 552 } 553 554 /* 555 * 4wire ak4114 protocol - reading data 556 */ 557 static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio, 558 int idx) 559 { 560 unsigned char data = 0; 561 562 for (; idx >= 0; idx--) { 563 /* drop clock */ 564 gpio &= ~VT1724_PRODIGY192_CCLK; 565 snd_ice1712_gpio_write(ice, gpio); 566 udelay(1); 567 /* read data */ 568 if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN) 569 data |= (1 << idx); 570 udelay(1); 571 /* raise clock */ 572 gpio |= VT1724_PRODIGY192_CCLK; 573 snd_ice1712_gpio_write(ice, gpio); 574 udelay(1); 575 } 576 return data; 577 } 578 /* 579 * 4wire ak4114 protocol - starting sequence 580 */ 581 static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice) 582 { 583 unsigned int tmp; 584 585 snd_ice1712_save_gpio_status(ice); 586 tmp = snd_ice1712_gpio_read(ice); 587 588 tmp |= VT1724_PRODIGY192_CCLK; /* high at init */ 589 tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */ 590 snd_ice1712_gpio_write(ice, tmp); 591 udelay(1); 592 return tmp; 593 } 594 595 /* 596 * 4wire ak4114 protocol - final sequence 597 */ 598 static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp) 599 { 600 tmp |= VT1724_PRODIGY192_CS; /* raise chip select */ 601 snd_ice1712_gpio_write(ice, tmp); 602 udelay(1); 603 snd_ice1712_restore_gpio_status(ice); 604 } 605 606 /* 607 * Write data to addr register of ak4114 608 */ 609 static void prodigy192_ak4114_write(void *private_data, unsigned char addr, 610 unsigned char data) 611 { 612 struct snd_ice1712 *ice = private_data; 613 unsigned int tmp, addrdata; 614 tmp = prodigy192_4wire_start(ice); 615 addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f); 616 addrdata = (addrdata << 8) | data; 617 write_data(ice, tmp, addrdata, 15); 618 prodigy192_4wire_finish(ice, tmp); 619 } 620 621 /* 622 * Read data from addr register of ak4114 623 */ 624 static unsigned char prodigy192_ak4114_read(void *private_data, 625 unsigned char addr) 626 { 627 struct snd_ice1712 *ice = private_data; 628 unsigned int tmp; 629 unsigned char data; 630 631 tmp = prodigy192_4wire_start(ice); 632 write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7); 633 data = read_data(ice, tmp, 7); 634 prodigy192_4wire_finish(ice, tmp); 635 return data; 636 } 637 638 639 static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol, 640 struct snd_ctl_elem_info *uinfo) 641 { 642 static char *texts[2] = { "Toslink", "Coax" }; 643 644 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 645 uinfo->count = 1; 646 uinfo->value.enumerated.items = 2; 647 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 648 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 649 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 650 return 0; 651 } 652 653 654 static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol, 655 struct snd_ctl_elem_value *ucontrol) 656 { 657 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 658 unsigned char val; 659 660 val = prodigy192_ak4114_read(ice, AK4114_REG_IO1); 661 /* AK4114_IPS0 bit = 0 -> RX0 = Toslink 662 * AK4114_IPS0 bit = 1 -> RX1 = Coax 663 */ 664 ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0; 665 return 0; 666 } 667 668 static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol, 669 struct snd_ctl_elem_value *ucontrol) 670 { 671 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 672 unsigned char new, old, itemvalue; 673 int change; 674 675 old = prodigy192_ak4114_read(ice, AK4114_REG_IO1); 676 /* AK4114_IPS0 could be any bit */ 677 itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00; 678 679 new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0); 680 change = (new != old); 681 if (change) 682 prodigy192_ak4114_write(ice, AK4114_REG_IO1, new); 683 return change; 684 } 685 686 687 static struct snd_kcontrol_new ak4114_controls[] __devinitdata = { 688 { 689 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 690 .name = "MIODIO IEC958 Capture Input", 691 .info = ak4114_input_sw_info, 692 .get = ak4114_input_sw_get, 693 .put = ak4114_input_sw_put, 694 695 } 696 }; 697 698 699 static int prodigy192_ak4114_init(struct snd_ice1712 *ice) 700 { 701 static const unsigned char ak4114_init_vals[] = { 702 AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, 703 /* ice1724 expects I2S and provides clock, 704 * DEM0 disables the deemphasis filter 705 */ 706 AK4114_DIF_I24I2S | AK4114_DEM0 , 707 AK4114_TX1E, 708 AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */ 709 0, 710 0 711 }; 712 static const unsigned char ak4114_init_txcsb[] = { 713 0x41, 0x02, 0x2c, 0x00, 0x00 714 }; 715 716 return snd_ak4114_create(ice->card, 717 prodigy192_ak4114_read, 718 prodigy192_ak4114_write, 719 ak4114_init_vals, ak4114_init_txcsb, 720 ice, &ice->spec.prodigy192.ak4114); 721 } 722 723 static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) 724 { 725 unsigned int i; 726 int err; 727 728 for (i = 0; i < ARRAY_SIZE(stac_controls); i++) { 729 err = snd_ctl_add(ice->card, 730 snd_ctl_new1(&stac_controls[i], ice)); 731 if (err < 0) 732 return err; 733 } 734 if (ice->spec.prodigy192.ak4114) { 735 /* ak4114 is connected */ 736 for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) { 737 err = snd_ctl_add(ice->card, 738 snd_ctl_new1(&ak4114_controls[i], 739 ice)); 740 if (err < 0) 741 return err; 742 } 743 err = snd_ak4114_build(ice->spec.prodigy192.ak4114, 744 NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */ 745 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 746 if (err < 0) 747 return err; 748 } 749 return 0; 750 } 751 752 /* 753 * check for presence of MI/ODI/O add-on card with digital inputs 754 */ 755 static int prodigy192_miodio_exists(struct snd_ice1712 *ice) 756 { 757 758 unsigned char orig_value; 759 const unsigned char test_data = 0xd1; /* random value */ 760 unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */ 761 int exists = 0; 762 763 orig_value = prodigy192_ak4114_read(ice, addr); 764 prodigy192_ak4114_write(ice, addr, test_data); 765 if (prodigy192_ak4114_read(ice, addr) == test_data) { 766 /* ak4114 seems to communicate, apparently exists */ 767 /* writing back original value */ 768 prodigy192_ak4114_write(ice, addr, orig_value); 769 exists = 1; 770 } 771 return exists; 772 } 773 774 /* 775 * initialize the chip 776 */ 777 static int __devinit prodigy192_init(struct snd_ice1712 *ice) 778 { 779 static const unsigned short stac_inits_prodigy[] = { 780 STAC946X_RESET, 0, 781 /* STAC946X_MASTER_VOLUME, 0, 782 STAC946X_LF_VOLUME, 0, 783 STAC946X_RF_VOLUME, 0, 784 STAC946X_LR_VOLUME, 0, 785 STAC946X_RR_VOLUME, 0, 786 STAC946X_CENTER_VOLUME, 0, 787 STAC946X_LFE_VOLUME, 0,*/ 788 (unsigned short)-1 789 }; 790 const unsigned short *p; 791 int err = 0; 792 793 /* prodigy 192 */ 794 ice->num_total_dacs = 6; 795 ice->num_total_adcs = 2; 796 ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */ 797 798 /* initialize codec */ 799 p = stac_inits_prodigy; 800 for (; *p != (unsigned short)-1; p += 2) 801 stac9460_put(ice, p[0], p[1]); 802 803 /* MI/ODI/O add on card with AK4114 */ 804 if (prodigy192_miodio_exists(ice)) { 805 err = prodigy192_ak4114_init(ice); 806 /* from this moment if err = 0 then 807 * ice->spec.prodigy192.ak4114 should not be null 808 */ 809 snd_printdd("AK4114 initialized with status %d\n", err); 810 } else 811 snd_printdd("AK4114 not found\n"); 812 if (err < 0) 813 return err; 814 815 return 0; 816 } 817 818 819 /* 820 * Aureon boards don't provide the EEPROM data except for the vendor IDs. 821 * hence the driver needs to sets up it properly. 822 */ 823 824 static unsigned char prodigy71_eeprom[] __devinitdata = { 825 [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401, 826 * spdif-in+ 1 stereo ADC, 827 * 3 stereo DACs 828 */ 829 [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 830 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ 831 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 832 [ICE_EEP2_GPIO_DIR] = 0xff, 833 [ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) , 834 [ICE_EEP2_GPIO_DIR2] = 0xbf, 835 [ICE_EEP2_GPIO_MASK] = 0x00, 836 [ICE_EEP2_GPIO_MASK1] = 0x00, 837 [ICE_EEP2_GPIO_MASK2] = 0x00, 838 [ICE_EEP2_GPIO_STATE] = 0x00, 839 [ICE_EEP2_GPIO_STATE1] = 0x00, 840 [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. input 841 * passthrough, 842 * 1 = SPDIF-OUT from ice1724 843 */ 844 }; 845 846 847 /* entry point */ 848 struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { 849 { 850 .subvendor = VT1724_SUBDEVICE_PRODIGY192VE, 851 .name = "Audiotrak Prodigy 192", 852 .model = "prodigy192", 853 .chip_init = prodigy192_init, 854 .build_controls = prodigy192_add_controls, 855 .eeprom_size = sizeof(prodigy71_eeprom), 856 .eeprom_data = prodigy71_eeprom, 857 }, 858 { } /* terminator */ 859 }; 860