1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ALSA driver for ICEnsemble VT1724 (Envy24HT) 4 * 5 * Lowlevel functions for Ego Sys Waveterminal 192M 6 * 7 * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com> 8 * Some functions are taken from the Prodigy192 driver 9 * source 10 */ 11 12 13 14 #include <linux/delay.h> 15 #include <linux/interrupt.h> 16 #include <linux/init.h> 17 #include <sound/core.h> 18 #include <sound/tlv.h> 19 #include <linux/slab.h> 20 21 #include "ice1712.h" 22 #include "envy24ht.h" 23 #include "wtm.h" 24 #include "stac946x.h" 25 26 struct wtm_spec { 27 /* rate change needs atomic mute/unmute of all dacs*/ 28 struct mutex mute_mutex; 29 }; 30 31 32 /* 33 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 34 */ 35 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 36 unsigned char val) 37 { 38 snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); 39 } 40 41 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) 42 { 43 return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); 44 } 45 46 /* 47 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus 48 */ 49 static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, 50 unsigned char val) 51 { 52 snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); 53 } 54 55 static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) 56 { 57 return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); 58 } 59 60 61 /* 62 * DAC mute control 63 */ 64 static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute, 65 unsigned short int *change_mask) 66 { 67 unsigned char new, old; 68 int id, idx, change; 69 70 /*stac9460 1*/ 71 for (id = 0; id < 7; id++) { 72 if (*change_mask & (0x01 << id)) { 73 if (id == 0) 74 idx = STAC946X_MASTER_VOLUME; 75 else 76 idx = STAC946X_LF_VOLUME - 1 + id; 77 old = stac9460_get(ice, idx); 78 new = (~mute << 7 & 0x80) | (old & ~0x80); 79 change = (new != old); 80 if (change) { 81 stac9460_put(ice, idx, new); 82 *change_mask = *change_mask | (0x01 << id); 83 } else { 84 *change_mask = *change_mask & ~(0x01 << id); 85 } 86 } 87 } 88 89 /*stac9460 2*/ 90 for (id = 0; id < 3; id++) { 91 if (*change_mask & (0x01 << (id + 7))) { 92 if (id == 0) 93 idx = STAC946X_MASTER_VOLUME; 94 else 95 idx = STAC946X_LF_VOLUME - 1 + id; 96 old = stac9460_2_get(ice, idx); 97 new = (~mute << 7 & 0x80) | (old & ~0x80); 98 change = (new != old); 99 if (change) { 100 stac9460_2_put(ice, idx, new); 101 *change_mask = *change_mask | (0x01 << id); 102 } else { 103 *change_mask = *change_mask & ~(0x01 << id); 104 } 105 } 106 } 107 } 108 109 110 111 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info 112 113 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, 114 struct snd_ctl_elem_value *ucontrol) 115 { 116 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 117 struct wtm_spec *spec = ice->spec; 118 unsigned char val; 119 int idx, id; 120 121 mutex_lock(&spec->mute_mutex); 122 123 if (kcontrol->private_value) { 124 idx = STAC946X_MASTER_VOLUME; 125 id = 0; 126 } else { 127 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 128 idx = id + STAC946X_LF_VOLUME; 129 } 130 if (id < 6) 131 val = stac9460_get(ice, idx); 132 else 133 val = stac9460_2_get(ice, idx - 6); 134 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; 135 136 mutex_unlock(&spec->mute_mutex); 137 return 0; 138 } 139 140 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, 141 struct snd_ctl_elem_value *ucontrol) 142 { 143 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 144 unsigned char new, old; 145 int id, idx; 146 int change; 147 148 if (kcontrol->private_value) { 149 idx = STAC946X_MASTER_VOLUME; 150 old = stac9460_get(ice, idx); 151 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 152 (old & ~0x80); 153 change = (new != old); 154 if (change) { 155 stac9460_put(ice, idx, new); 156 stac9460_2_put(ice, idx, new); 157 } 158 } else { 159 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 160 idx = id + STAC946X_LF_VOLUME; 161 if (id < 6) 162 old = stac9460_get(ice, idx); 163 else 164 old = stac9460_2_get(ice, idx - 6); 165 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 166 (old & ~0x80); 167 change = (new != old); 168 if (change) { 169 if (id < 6) 170 stac9460_put(ice, idx, new); 171 else 172 stac9460_2_put(ice, idx - 6, new); 173 } 174 } 175 return change; 176 } 177 178 /* 179 * DAC volume attenuation mixer control 180 */ 181 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, 182 struct snd_ctl_elem_info *uinfo) 183 { 184 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 185 uinfo->count = 1; 186 uinfo->value.integer.min = 0; /* mute */ 187 uinfo->value.integer.max = 0x7f; /* 0dB */ 188 return 0; 189 } 190 191 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, 192 struct snd_ctl_elem_value *ucontrol) 193 { 194 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 195 int idx, id; 196 unsigned char vol; 197 198 if (kcontrol->private_value) { 199 idx = STAC946X_MASTER_VOLUME; 200 id = 0; 201 } else { 202 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 203 idx = id + STAC946X_LF_VOLUME; 204 } 205 if (id < 6) 206 vol = stac9460_get(ice, idx) & 0x7f; 207 else 208 vol = stac9460_2_get(ice, idx - 6) & 0x7f; 209 ucontrol->value.integer.value[0] = 0x7f - vol; 210 return 0; 211 } 212 213 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, 214 struct snd_ctl_elem_value *ucontrol) 215 { 216 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 217 int idx, id; 218 unsigned char tmp, ovol, nvol; 219 int change; 220 221 if (kcontrol->private_value) { 222 idx = STAC946X_MASTER_VOLUME; 223 nvol = ucontrol->value.integer.value[0] & 0x7f; 224 tmp = stac9460_get(ice, idx); 225 ovol = 0x7f - (tmp & 0x7f); 226 change = (ovol != nvol); 227 if (change) { 228 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 229 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 230 } 231 } else { 232 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 233 idx = id + STAC946X_LF_VOLUME; 234 nvol = ucontrol->value.integer.value[0] & 0x7f; 235 if (id < 6) 236 tmp = stac9460_get(ice, idx); 237 else 238 tmp = stac9460_2_get(ice, idx - 6); 239 ovol = 0x7f - (tmp & 0x7f); 240 change = (ovol != nvol); 241 if (change) { 242 if (id < 6) 243 stac9460_put(ice, idx, (0x7f - nvol) | 244 (tmp & 0x80)); 245 else 246 stac9460_2_put(ice, idx-6, (0x7f - nvol) | 247 (tmp & 0x80)); 248 } 249 } 250 return change; 251 } 252 253 /* 254 * ADC mute control 255 */ 256 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info 257 258 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, 259 struct snd_ctl_elem_value *ucontrol) 260 { 261 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 262 unsigned char val; 263 int i, id; 264 265 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 266 if (id == 0) { 267 for (i = 0; i < 2; ++i) { 268 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); 269 ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 270 } 271 } else { 272 for (i = 0; i < 2; ++i) { 273 val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); 274 ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 275 } 276 } 277 return 0; 278 } 279 280 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, 281 struct snd_ctl_elem_value *ucontrol) 282 { 283 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 284 unsigned char new, old; 285 int i, reg, id; 286 int change; 287 288 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 289 if (id == 0) { 290 for (i = 0; i < 2; ++i) { 291 reg = STAC946X_MIC_L_VOLUME + i; 292 old = stac9460_get(ice, reg); 293 new = (~ucontrol->value.integer.value[i]<<7&0x80) | 294 (old&~0x80); 295 change = (new != old); 296 if (change) 297 stac9460_put(ice, reg, new); 298 } 299 } else { 300 for (i = 0; i < 2; ++i) { 301 reg = STAC946X_MIC_L_VOLUME + i; 302 old = stac9460_2_get(ice, reg); 303 new = (~ucontrol->value.integer.value[i]<<7&0x80) | 304 (old&~0x80); 305 change = (new != old); 306 if (change) 307 stac9460_2_put(ice, reg, new); 308 } 309 } 310 return change; 311 } 312 313 /* 314 *ADC gain mixer control 315 */ 316 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, 317 struct snd_ctl_elem_info *uinfo) 318 { 319 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 320 uinfo->count = 2; 321 uinfo->value.integer.min = 0; /* 0dB */ 322 uinfo->value.integer.max = 0x0f; /* 22.5dB */ 323 return 0; 324 } 325 326 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, 327 struct snd_ctl_elem_value *ucontrol) 328 { 329 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 330 int i, reg, id; 331 unsigned char vol; 332 333 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 334 if (id == 0) { 335 for (i = 0; i < 2; ++i) { 336 reg = STAC946X_MIC_L_VOLUME + i; 337 vol = stac9460_get(ice, reg) & 0x0f; 338 ucontrol->value.integer.value[i] = 0x0f - vol; 339 } 340 } else { 341 for (i = 0; i < 2; ++i) { 342 reg = STAC946X_MIC_L_VOLUME + i; 343 vol = stac9460_2_get(ice, reg) & 0x0f; 344 ucontrol->value.integer.value[i] = 0x0f - vol; 345 } 346 } 347 return 0; 348 } 349 350 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, 351 struct snd_ctl_elem_value *ucontrol) 352 { 353 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 354 int i, reg, id; 355 unsigned char ovol, nvol; 356 int change; 357 358 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 359 if (id == 0) { 360 for (i = 0; i < 2; ++i) { 361 reg = STAC946X_MIC_L_VOLUME + i; 362 nvol = ucontrol->value.integer.value[i] & 0x0f; 363 ovol = 0x0f - stac9460_get(ice, reg); 364 change = ((ovol & 0x0f) != nvol); 365 if (change) 366 stac9460_put(ice, reg, (0x0f - nvol) | 367 (ovol & ~0x0f)); 368 } 369 } else { 370 for (i = 0; i < 2; ++i) { 371 reg = STAC946X_MIC_L_VOLUME + i; 372 nvol = ucontrol->value.integer.value[i] & 0x0f; 373 ovol = 0x0f - stac9460_2_get(ice, reg); 374 change = ((ovol & 0x0f) != nvol); 375 if (change) 376 stac9460_2_put(ice, reg, (0x0f - nvol) | 377 (ovol & ~0x0f)); 378 } 379 } 380 return change; 381 } 382 383 /* 384 * MIC / LINE switch fonction 385 */ 386 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, 387 struct snd_ctl_elem_info *uinfo) 388 { 389 static const char * const texts[2] = { "Line In", "Mic" }; 390 391 return snd_ctl_enum_info(uinfo, 1, 2, texts); 392 } 393 394 395 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, 396 struct snd_ctl_elem_value *ucontrol) 397 { 398 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 399 unsigned char val; 400 int id; 401 402 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 403 if (id == 0) 404 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 405 else 406 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 407 ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1; 408 return 0; 409 } 410 411 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, 412 struct snd_ctl_elem_value *ucontrol) 413 { 414 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 415 unsigned char new, old; 416 int change, id; 417 418 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 419 if (id == 0) 420 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 421 else 422 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 423 new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80); 424 change = (new != old); 425 if (change) { 426 if (id == 0) 427 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 428 else 429 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); 430 } 431 return change; 432 } 433 434 435 /* 436 * Handler for setting correct codec rate - called when rate change is detected 437 */ 438 static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) 439 { 440 unsigned char old, new; 441 unsigned short int changed; 442 struct wtm_spec *spec = ice->spec; 443 444 if (rate == 0) /* no hint - S/PDIF input is master, simply return */ 445 return; 446 else if (rate <= 48000) 447 new = 0x08; /* 256x, base rate mode */ 448 else if (rate <= 96000) 449 new = 0x11; /* 256x, mid rate mode */ 450 else 451 new = 0x12; /* 128x, high rate mode */ 452 453 old = stac9460_get(ice, STAC946X_MASTER_CLOCKING); 454 if (old == new) 455 return; 456 /* change detected, setting master clock, muting first */ 457 /* due to possible conflicts with mute controls - mutexing */ 458 mutex_lock(&spec->mute_mutex); 459 /* we have to remember current mute status for each DAC */ 460 changed = 0xFFFF; 461 stac9460_dac_mute_all(ice, 0, &changed); 462 /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ 463 stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); 464 stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new); 465 udelay(10); 466 /* unmuting - only originally unmuted dacs - 467 * i.e. those changed when muting */ 468 stac9460_dac_mute_all(ice, 1, &changed); 469 mutex_unlock(&spec->mute_mutex); 470 } 471 472 473 /*Limits value in dB for fader*/ 474 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); 475 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); 476 477 /* 478 * Control tabs 479 */ 480 static const struct snd_kcontrol_new stac9640_controls[] = { 481 { 482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 483 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 484 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 485 .name = "Master Playback Switch", 486 .info = stac9460_dac_mute_info, 487 .get = stac9460_dac_mute_get, 488 .put = stac9460_dac_mute_put, 489 .private_value = 1, 490 .tlv = { .p = db_scale_dac } 491 }, 492 { 493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 494 .name = "Master Playback Volume", 495 .info = stac9460_dac_vol_info, 496 .get = stac9460_dac_vol_get, 497 .put = stac9460_dac_vol_put, 498 .private_value = 1, 499 }, 500 { 501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 502 .name = "MIC/Line Input Enum", 503 .count = 2, 504 .info = stac9460_mic_sw_info, 505 .get = stac9460_mic_sw_get, 506 .put = stac9460_mic_sw_put, 507 508 }, 509 { 510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 511 .name = "DAC Switch", 512 .count = 8, 513 .info = stac9460_dac_mute_info, 514 .get = stac9460_dac_mute_get, 515 .put = stac9460_dac_mute_put, 516 }, 517 { 518 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 519 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 520 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 521 522 .name = "DAC Volume", 523 .count = 8, 524 .info = stac9460_dac_vol_info, 525 .get = stac9460_dac_vol_get, 526 .put = stac9460_dac_vol_put, 527 .tlv = { .p = db_scale_dac } 528 }, 529 { 530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 531 .name = "ADC Switch", 532 .count = 2, 533 .info = stac9460_adc_mute_info, 534 .get = stac9460_adc_mute_get, 535 .put = stac9460_adc_mute_put, 536 }, 537 { 538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 539 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 540 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 541 542 .name = "ADC Volume", 543 .count = 2, 544 .info = stac9460_adc_vol_info, 545 .get = stac9460_adc_vol_get, 546 .put = stac9460_adc_vol_put, 547 .tlv = { .p = db_scale_adc } 548 } 549 }; 550 551 552 553 /*INIT*/ 554 static int wtm_add_controls(struct snd_ice1712 *ice) 555 { 556 unsigned int i; 557 int err; 558 559 for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { 560 err = snd_ctl_add(ice->card, 561 snd_ctl_new1(&stac9640_controls[i], ice)); 562 if (err < 0) 563 return err; 564 } 565 return 0; 566 } 567 568 static int wtm_init(struct snd_ice1712 *ice) 569 { 570 static const unsigned short stac_inits_wtm[] = { 571 STAC946X_RESET, 0, 572 STAC946X_MASTER_CLOCKING, 0x11, 573 (unsigned short)-1 574 }; 575 const unsigned short *p; 576 struct wtm_spec *spec; 577 578 /*WTM 192M*/ 579 ice->num_total_dacs = 8; 580 ice->num_total_adcs = 4; 581 ice->force_rdma1 = 1; 582 583 /*init mutex for dac mute conflict*/ 584 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 585 if (!spec) 586 return -ENOMEM; 587 ice->spec = spec; 588 mutex_init(&spec->mute_mutex); 589 590 591 /*initialize codec*/ 592 p = stac_inits_wtm; 593 for (; *p != (unsigned short)-1; p += 2) { 594 stac9460_put(ice, p[0], p[1]); 595 stac9460_2_put(ice, p[0], p[1]); 596 } 597 ice->gpio.set_pro_rate = stac9460_set_rate_val; 598 return 0; 599 } 600 601 602 static const unsigned char wtm_eeprom[] = { 603 [ICE_EEP2_SYSCONF] = 0x67, /*SYSCONF: clock 192KHz, mpu401, 604 4ADC, 8DAC */ 605 [ICE_EEP2_ACLINK] = 0x80, /* ACLINK : I2S */ 606 [ICE_EEP2_I2S] = 0xf8, /* I2S: vol; 96k, 24bit, 192k */ 607 [ICE_EEP2_SPDIF] = 0xc1, /*SPDIF: out-en, spidf ext out*/ 608 [ICE_EEP2_GPIO_DIR] = 0x9f, 609 [ICE_EEP2_GPIO_DIR1] = 0xff, 610 [ICE_EEP2_GPIO_DIR2] = 0x7f, 611 [ICE_EEP2_GPIO_MASK] = 0x9f, 612 [ICE_EEP2_GPIO_MASK1] = 0xff, 613 [ICE_EEP2_GPIO_MASK2] = 0x7f, 614 [ICE_EEP2_GPIO_STATE] = 0x16, 615 [ICE_EEP2_GPIO_STATE1] = 0x80, 616 [ICE_EEP2_GPIO_STATE2] = 0x00, 617 }; 618 619 620 /*entry point*/ 621 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = { 622 { 623 .subvendor = VT1724_SUBDEVICE_WTM, 624 .name = "ESI Waveterminal 192M", 625 .model = "WT192M", 626 .chip_init = wtm_init, 627 .build_controls = wtm_add_controls, 628 .eeprom_size = sizeof(wtm_eeprom), 629 .eeprom_data = wtm_eeprom, 630 }, 631 {} /*terminator*/ 632 }; 633
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.