1 /* 2 * ALSA driver for ICEnsemble VT1724 (Envy24HT) 3 * 4 * Lowlevel functions for Ego Sys Waveterminal 192M 5 * 6 * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com> 7 * Some functions are taken from the Prodigy192 driver 8 * source 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 */ 25 26 27 28 #include <linux/delay.h> 29 #include <linux/interrupt.h> 30 #include <linux/init.h> 31 #include <sound/core.h> 32 33 #include "ice1712.h" 34 #include "envy24ht.h" 35 #include "wtm.h" 36 #include "stac946x.h" 37 38 39 /* 40 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 41 */ 42 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 43 unsigned char val) 44 { 45 snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); 46 } 47 48 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) 49 { 50 return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); 51 } 52 53 /* 54 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus 55 */ 56 static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, 57 unsigned char val) 58 { 59 snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); 60 } 61 62 static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) 63 { 64 return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); 65 } 66 67 68 /* 69 * DAC mute control 70 */ 71 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info 72 73 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, 74 struct snd_ctl_elem_value *ucontrol) 75 { 76 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 77 unsigned char val; 78 int idx, id; 79 80 if (kcontrol->private_value) { 81 idx = STAC946X_MASTER_VOLUME; 82 id = 0; 83 } else { 84 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 85 idx = id + STAC946X_LF_VOLUME; 86 } 87 if (id < 6) 88 val = stac9460_get(ice, idx); 89 else 90 val = stac9460_2_get(ice, idx - 6); 91 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; 92 return 0; 93 } 94 95 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, 96 struct snd_ctl_elem_value *ucontrol) 97 { 98 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 99 unsigned char new, old; 100 int id, idx; 101 int change; 102 103 if (kcontrol->private_value) { 104 idx = STAC946X_MASTER_VOLUME; 105 old = stac9460_get(ice, idx); 106 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 107 (old & ~0x80); 108 change = (new != old); 109 if (change) { 110 stac9460_put(ice, idx, new); 111 stac9460_2_put(ice, idx, new); 112 } 113 } else { 114 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 115 idx = id + STAC946X_LF_VOLUME; 116 if (id < 6) 117 old = stac9460_get(ice, idx); 118 else 119 old = stac9460_2_get(ice, idx - 6); 120 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 121 (old & ~0x80); 122 change = (new != old); 123 if (change) { 124 if (id < 6) 125 stac9460_put(ice, idx, new); 126 else 127 stac9460_2_put(ice, idx - 6, new); 128 } 129 } 130 return change; 131 } 132 133 /* 134 * DAC volume attenuation mixer control 135 */ 136 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, 137 struct snd_ctl_elem_info *uinfo) 138 { 139 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 140 uinfo->count = 1; 141 uinfo->value.integer.min = 0; /* mute */ 142 uinfo->value.integer.max = 0x7f; /* 0dB */ 143 return 0; 144 } 145 146 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, 147 struct snd_ctl_elem_value *ucontrol) 148 { 149 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 150 int idx, id; 151 unsigned char vol; 152 153 if (kcontrol->private_value) { 154 idx = STAC946X_MASTER_VOLUME; 155 id = 0; 156 } else { 157 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 158 idx = id + STAC946X_LF_VOLUME; 159 } 160 if (id < 6) 161 vol = stac9460_get(ice, idx) & 0x7f; 162 else 163 vol = stac9460_2_get(ice, idx - 6) & 0x7f; 164 ucontrol->value.integer.value[0] = 0x7f - vol; 165 return 0; 166 } 167 168 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, 169 struct snd_ctl_elem_value *ucontrol) 170 { 171 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 172 int idx, id; 173 unsigned char tmp, ovol, nvol; 174 int change; 175 176 if (kcontrol->private_value) { 177 idx = STAC946X_MASTER_VOLUME; 178 nvol = ucontrol->value.integer.value[0] & 0x7f; 179 tmp = stac9460_get(ice, idx); 180 ovol = 0x7f - (tmp & 0x7f); 181 change = (ovol != nvol); 182 if (change) { 183 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 184 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 185 } 186 } else { 187 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 188 idx = id + STAC946X_LF_VOLUME; 189 nvol = ucontrol->value.integer.value[0] & 0x7f; 190 if (id < 6) 191 tmp = stac9460_get(ice, idx); 192 else 193 tmp = stac9460_2_get(ice, idx - 6); 194 ovol = 0x7f - (tmp & 0x7f); 195 change = (ovol != nvol); 196 if (change) { 197 if (id < 6) 198 stac9460_put(ice, idx, (0x7f - nvol) | 199 (tmp & 0x80)); 200 else 201 stac9460_2_put(ice, idx-6, (0x7f - nvol) | 202 (tmp & 0x80)); 203 } 204 } 205 return change; 206 } 207 208 /* 209 * ADC mute control 210 */ 211 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info 212 213 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, 214 struct snd_ctl_elem_value *ucontrol) 215 { 216 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 217 unsigned char val; 218 int i, id; 219 220 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 221 if (id == 0) { 222 for (i = 0; i < 2; ++i) { 223 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); 224 ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 225 } 226 } else { 227 for (i = 0; i < 2; ++i) { 228 val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); 229 ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 230 } 231 } 232 return 0; 233 } 234 235 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, 236 struct snd_ctl_elem_value *ucontrol) 237 { 238 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 239 unsigned char new, old; 240 int i, reg, id; 241 int change; 242 243 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 244 if (id == 0) { 245 for (i = 0; i < 2; ++i) { 246 reg = STAC946X_MIC_L_VOLUME + i; 247 old = stac9460_get(ice, reg); 248 new = (~ucontrol->value.integer.value[i]<<7&0x80) | 249 (old&~0x80); 250 change = (new != old); 251 if (change) 252 stac9460_put(ice, reg, new); 253 } 254 } else { 255 for (i = 0; i < 2; ++i) { 256 reg = STAC946X_MIC_L_VOLUME + i; 257 old = stac9460_2_get(ice, reg); 258 new = (~ucontrol->value.integer.value[i]<<7&0x80) | 259 (old&~0x80); 260 change = (new != old); 261 if (change) 262 stac9460_2_put(ice, reg, new); 263 } 264 } 265 return change; 266 } 267 268 /* 269 *ADC gain mixer control 270 */ 271 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, 272 struct snd_ctl_elem_info *uinfo) 273 { 274 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 275 uinfo->count = 2; 276 uinfo->value.integer.min = 0; /* 0dB */ 277 uinfo->value.integer.max = 0x0f; /* 22.5dB */ 278 return 0; 279 } 280 281 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, 282 struct snd_ctl_elem_value *ucontrol) 283 { 284 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 285 int i, reg, id; 286 unsigned char vol; 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 vol = stac9460_get(ice, reg) & 0x0f; 293 ucontrol->value.integer.value[i] = 0x0f - vol; 294 } 295 } else { 296 for (i = 0; i < 2; ++i) { 297 reg = STAC946X_MIC_L_VOLUME + i; 298 vol = stac9460_2_get(ice, reg) & 0x0f; 299 ucontrol->value.integer.value[i] = 0x0f - vol; 300 } 301 } 302 return 0; 303 } 304 305 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, 306 struct snd_ctl_elem_value *ucontrol) 307 { 308 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 309 int i, reg, id; 310 unsigned char ovol, nvol; 311 int change; 312 313 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 314 if (id == 0) { 315 for (i = 0; i < 2; ++i) { 316 reg = STAC946X_MIC_L_VOLUME + i; 317 nvol = ucontrol->value.integer.value[i] & 0x0f; 318 ovol = 0x0f - stac9460_get(ice, reg); 319 change = ((ovol & 0x0f) != nvol); 320 if (change) 321 stac9460_put(ice, reg, (0x0f - nvol) | 322 (ovol & ~0x0f)); 323 } 324 } else { 325 for (i = 0; i < 2; ++i) { 326 reg = STAC946X_MIC_L_VOLUME + i; 327 nvol = ucontrol->value.integer.value[i] & 0x0f; 328 ovol = 0x0f - stac9460_2_get(ice, reg); 329 change = ((ovol & 0x0f) != nvol); 330 if (change) 331 stac9460_2_put(ice, reg, (0x0f - nvol) | 332 (ovol & ~0x0f)); 333 } 334 } 335 return change; 336 } 337 338 /* 339 * MIC / LINE switch fonction 340 */ 341 342 #define stac9460_mic_sw_info snd_ctl_boolean_mono_info 343 344 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, 345 struct snd_ctl_elem_value *ucontrol) 346 { 347 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 348 unsigned char val; 349 int id; 350 351 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 352 if (id == 0) 353 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 354 else 355 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 356 ucontrol->value.integer.value[0] = ~val>>7 & 0x1; 357 return 0; 358 } 359 360 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, 361 struct snd_ctl_elem_value *ucontrol) 362 { 363 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 364 unsigned char new, old; 365 int change, id; 366 367 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 368 if (id == 0) 369 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 370 else 371 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 372 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80); 373 change = (new != old); 374 if (change) { 375 if (id == 0) 376 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 377 else 378 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); 379 } 380 return change; 381 } 382 383 /* 384 * Control tabs 385 */ 386 static struct snd_kcontrol_new stac9640_controls[] = { 387 { 388 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 389 .name = "Master Playback Switch", 390 .info = stac9460_dac_mute_info, 391 .get = stac9460_dac_mute_get, 392 .put = stac9460_dac_mute_put, 393 .private_value = 1 394 }, 395 { 396 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 397 .name = "Master Playback Volume", 398 .info = stac9460_dac_vol_info, 399 .get = stac9460_dac_vol_get, 400 .put = stac9460_dac_vol_put, 401 .private_value = 1, 402 }, 403 { 404 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 405 .name = "MIC/Line switch", 406 .count = 2, 407 .info = stac9460_mic_sw_info, 408 .get = stac9460_mic_sw_get, 409 .put = stac9460_mic_sw_put, 410 411 }, 412 { 413 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 414 .name = "DAC Switch", 415 .count = 8, 416 .info = stac9460_dac_mute_info, 417 .get = stac9460_dac_mute_get, 418 .put = stac9460_dac_mute_put, 419 }, 420 { 421 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 422 .name = "DAC Volume", 423 .count = 8, 424 .info = stac9460_dac_vol_info, 425 .get = stac9460_dac_vol_get, 426 .put = stac9460_dac_vol_put, 427 }, 428 { 429 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 430 .name = "ADC Switch", 431 .count = 2, 432 .info = stac9460_adc_mute_info, 433 .get = stac9460_adc_mute_get, 434 .put = stac9460_adc_mute_put, 435 }, 436 { 437 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 438 .name = "ADC Volume", 439 .count = 2, 440 .info = stac9460_adc_vol_info, 441 .get = stac9460_adc_vol_get, 442 .put = stac9460_adc_vol_put, 443 444 } 445 }; 446 447 448 449 /*INIT*/ 450 static int wtm_add_controls(struct snd_ice1712 *ice) 451 { 452 unsigned int i; 453 int err; 454 455 for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { 456 err = snd_ctl_add(ice->card, 457 snd_ctl_new1(&stac9640_controls[i], ice)); 458 if (err < 0) 459 return err; 460 } 461 return 0; 462 } 463 464 static int wtm_init(struct snd_ice1712 *ice) 465 { 466 static unsigned short stac_inits_prodigy[] = { 467 STAC946X_RESET, 0, 468 (unsigned short)-1 469 }; 470 unsigned short *p; 471 472 /*WTM 192M*/ 473 ice->num_total_dacs = 8; 474 ice->num_total_adcs = 4; 475 ice->force_rdma1 = 1; 476 477 /*initialize codec*/ 478 p = stac_inits_prodigy; 479 for (; *p != (unsigned short)-1; p += 2) { 480 stac9460_put(ice, p[0], p[1]); 481 stac9460_2_put(ice, p[0], p[1]); 482 } 483 return 0; 484 } 485 486 487 static unsigned char wtm_eeprom[] = { 488 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */ 489 0x80, /* ACLINK : I2S */ 490 0xf8, /* I2S: vol; 96k, 24bit, 192k */ 491 0xc1 /*SPDIF: out-en, spidf ext out*/, 492 0x9f, /* GPIO_DIR */ 493 0xff, /* GPIO_DIR1 */ 494 0x7f, /* GPIO_DIR2 */ 495 0x9f, /* GPIO_MASK */ 496 0xff, /* GPIO_MASK1 */ 497 0x7f, /* GPIO_MASK2 */ 498 0x16, /* GPIO_STATE */ 499 0x80, /* GPIO_STATE1 */ 500 0x00, /* GPIO_STATE2 */ 501 }; 502 503 504 /*entry point*/ 505 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = { 506 { 507 .subvendor = VT1724_SUBDEVICE_WTM, 508 .name = "ESI Waveterminal 192M", 509 .model = "WT192M", 510 .chip_init = wtm_init, 511 .build_controls = wtm_add_controls, 512 .eeprom_size = sizeof(wtm_eeprom), 513 .eeprom_data = wtm_eeprom, 514 }, 515 {} /*terminator*/ 516 }; 517