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