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