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