1 /* 2 * TI TSC2005 emulator. 3 * 4 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> 5 * Copyright (C) 2008 Nokia Corporation 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 or 10 * (at your option) version 3 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "hw/hw.h" 22 #include "qemu/timer.h" 23 #include "ui/console.h" 24 #include "hw/devices.h" 25 26 #define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - (p ? 12 : 10))) 27 28 typedef struct { 29 qemu_irq pint; /* Combination of the nPENIRQ and DAV signals */ 30 QEMUTimer *timer; 31 uint16_t model; 32 33 int x, y; 34 int pressure; 35 36 int state, reg, irq, command; 37 uint16_t data, dav; 38 39 int busy; 40 int enabled; 41 int host_mode; 42 int function; 43 int nextfunction; 44 int precision; 45 int nextprecision; 46 int filter; 47 int pin_func; 48 int timing[2]; 49 int noise; 50 int reset; 51 int pdst; 52 int pnd0; 53 uint16_t temp_thr[2]; 54 uint16_t aux_thr[2]; 55 56 int tr[8]; 57 } TSC2005State; 58 59 enum { 60 TSC_MODE_XYZ_SCAN = 0x0, 61 TSC_MODE_XY_SCAN, 62 TSC_MODE_X, 63 TSC_MODE_Y, 64 TSC_MODE_Z, 65 TSC_MODE_AUX, 66 TSC_MODE_TEMP1, 67 TSC_MODE_TEMP2, 68 TSC_MODE_AUX_SCAN, 69 TSC_MODE_X_TEST, 70 TSC_MODE_Y_TEST, 71 TSC_MODE_TS_TEST, 72 TSC_MODE_RESERVED, 73 TSC_MODE_XX_DRV, 74 TSC_MODE_YY_DRV, 75 TSC_MODE_YX_DRV, 76 }; 77 78 static const uint16_t mode_regs[16] = { 79 0xf000, /* X, Y, Z scan */ 80 0xc000, /* X, Y scan */ 81 0x8000, /* X */ 82 0x4000, /* Y */ 83 0x3000, /* Z */ 84 0x0800, /* AUX */ 85 0x0400, /* TEMP1 */ 86 0x0200, /* TEMP2 */ 87 0x0800, /* AUX scan */ 88 0x0040, /* X test */ 89 0x0020, /* Y test */ 90 0x0080, /* Short-circuit test */ 91 0x0000, /* Reserved */ 92 0x0000, /* X+, X- drivers */ 93 0x0000, /* Y+, Y- drivers */ 94 0x0000, /* Y+, X- drivers */ 95 }; 96 97 #define X_TRANSFORM(s) \ 98 ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3]) 99 #define Y_TRANSFORM(s) \ 100 ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7]) 101 #define Z1_TRANSFORM(s) \ 102 ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4) 103 #define Z2_TRANSFORM(s) \ 104 ((4000 + ((s)->y >> 7) - ((s)->pressure << 10)) << 4) 105 106 #define AUX_VAL (700 << 4) /* +/- 3 at 12-bit */ 107 #define TEMP1_VAL (1264 << 4) /* +/- 5 at 12-bit */ 108 #define TEMP2_VAL (1531 << 4) /* +/- 5 at 12-bit */ 109 110 static uint16_t tsc2005_read(TSC2005State *s, int reg) 111 { 112 uint16_t ret; 113 114 switch (reg) { 115 case 0x0: /* X */ 116 s->dav &= ~mode_regs[TSC_MODE_X]; 117 return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) + 118 (s->noise & 3); 119 case 0x1: /* Y */ 120 s->dav &= ~mode_regs[TSC_MODE_Y]; 121 s->noise ++; 122 return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^ 123 (s->noise & 3); 124 case 0x2: /* Z1 */ 125 s->dav &= 0xdfff; 126 return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) - 127 (s->noise & 3); 128 case 0x3: /* Z2 */ 129 s->dav &= 0xefff; 130 return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) | 131 (s->noise & 3); 132 133 case 0x4: /* AUX */ 134 s->dav &= ~mode_regs[TSC_MODE_AUX]; 135 return TSC_CUT_RESOLUTION(AUX_VAL, s->precision); 136 137 case 0x5: /* TEMP1 */ 138 s->dav &= ~mode_regs[TSC_MODE_TEMP1]; 139 return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision) - 140 (s->noise & 5); 141 case 0x6: /* TEMP2 */ 142 s->dav &= 0xdfff; 143 s->dav &= ~mode_regs[TSC_MODE_TEMP2]; 144 return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision) ^ 145 (s->noise & 3); 146 147 case 0x7: /* Status */ 148 ret = s->dav | (s->reset << 7) | (s->pdst << 2) | 0x0; 149 s->dav &= ~(mode_regs[TSC_MODE_X_TEST] | mode_regs[TSC_MODE_Y_TEST] | 150 mode_regs[TSC_MODE_TS_TEST]); 151 s->reset = 1; 152 return ret; 153 154 case 0x8: /* AUX high treshold */ 155 return s->aux_thr[1]; 156 case 0x9: /* AUX low treshold */ 157 return s->aux_thr[0]; 158 159 case 0xa: /* TEMP high treshold */ 160 return s->temp_thr[1]; 161 case 0xb: /* TEMP low treshold */ 162 return s->temp_thr[0]; 163 164 case 0xc: /* CFR0 */ 165 return (s->pressure << 15) | ((!s->busy) << 14) | 166 (s->nextprecision << 13) | s->timing[0]; 167 case 0xd: /* CFR1 */ 168 return s->timing[1]; 169 case 0xe: /* CFR2 */ 170 return (s->pin_func << 14) | s->filter; 171 172 case 0xf: /* Function select status */ 173 return s->function >= 0 ? 1 << s->function : 0; 174 } 175 176 /* Never gets here */ 177 return 0xffff; 178 } 179 180 static void tsc2005_write(TSC2005State *s, int reg, uint16_t data) 181 { 182 switch (reg) { 183 case 0x8: /* AUX high treshold */ 184 s->aux_thr[1] = data; 185 break; 186 case 0x9: /* AUX low treshold */ 187 s->aux_thr[0] = data; 188 break; 189 190 case 0xa: /* TEMP high treshold */ 191 s->temp_thr[1] = data; 192 break; 193 case 0xb: /* TEMP low treshold */ 194 s->temp_thr[0] = data; 195 break; 196 197 case 0xc: /* CFR0 */ 198 s->host_mode = data >> 15; 199 if (s->enabled != !(data & 0x4000)) { 200 s->enabled = !(data & 0x4000); 201 fprintf(stderr, "%s: touchscreen sense %sabled\n", 202 __FUNCTION__, s->enabled ? "en" : "dis"); 203 if (s->busy && !s->enabled) 204 qemu_del_timer(s->timer); 205 s->busy &= s->enabled; 206 } 207 s->nextprecision = (data >> 13) & 1; 208 s->timing[0] = data & 0x1fff; 209 if ((s->timing[0] >> 11) == 3) 210 fprintf(stderr, "%s: illegal conversion clock setting\n", 211 __FUNCTION__); 212 break; 213 case 0xd: /* CFR1 */ 214 s->timing[1] = data & 0xf07; 215 break; 216 case 0xe: /* CFR2 */ 217 s->pin_func = (data >> 14) & 3; 218 s->filter = data & 0x3fff; 219 break; 220 221 default: 222 fprintf(stderr, "%s: write into read-only register %x\n", 223 __FUNCTION__, reg); 224 } 225 } 226 227 /* This handles most of the chip's logic. */ 228 static void tsc2005_pin_update(TSC2005State *s) 229 { 230 int64_t expires; 231 int pin_state; 232 233 switch (s->pin_func) { 234 case 0: 235 pin_state = !s->pressure && !!s->dav; 236 break; 237 case 1: 238 case 3: 239 default: 240 pin_state = !s->dav; 241 break; 242 case 2: 243 pin_state = !s->pressure; 244 } 245 246 if (pin_state != s->irq) { 247 s->irq = pin_state; 248 qemu_set_irq(s->pint, s->irq); 249 } 250 251 switch (s->nextfunction) { 252 case TSC_MODE_XYZ_SCAN: 253 case TSC_MODE_XY_SCAN: 254 if (!s->host_mode && s->dav) 255 s->enabled = 0; 256 if (!s->pressure) 257 return; 258 /* Fall through */ 259 case TSC_MODE_AUX_SCAN: 260 break; 261 262 case TSC_MODE_X: 263 case TSC_MODE_Y: 264 case TSC_MODE_Z: 265 if (!s->pressure) 266 return; 267 /* Fall through */ 268 case TSC_MODE_AUX: 269 case TSC_MODE_TEMP1: 270 case TSC_MODE_TEMP2: 271 case TSC_MODE_X_TEST: 272 case TSC_MODE_Y_TEST: 273 case TSC_MODE_TS_TEST: 274 if (s->dav) 275 s->enabled = 0; 276 break; 277 278 case TSC_MODE_RESERVED: 279 case TSC_MODE_XX_DRV: 280 case TSC_MODE_YY_DRV: 281 case TSC_MODE_YX_DRV: 282 default: 283 return; 284 } 285 286 if (!s->enabled || s->busy) 287 return; 288 289 s->busy = 1; 290 s->precision = s->nextprecision; 291 s->function = s->nextfunction; 292 s->pdst = !s->pnd0; /* Synchronised on internal clock */ 293 expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 7); 294 qemu_mod_timer(s->timer, expires); 295 } 296 297 static void tsc2005_reset(TSC2005State *s) 298 { 299 s->state = 0; 300 s->pin_func = 0; 301 s->enabled = 0; 302 s->busy = 0; 303 s->nextprecision = 0; 304 s->nextfunction = 0; 305 s->timing[0] = 0; 306 s->timing[1] = 0; 307 s->irq = 0; 308 s->dav = 0; 309 s->reset = 0; 310 s->pdst = 1; 311 s->pnd0 = 0; 312 s->function = -1; 313 s->temp_thr[0] = 0x000; 314 s->temp_thr[1] = 0xfff; 315 s->aux_thr[0] = 0x000; 316 s->aux_thr[1] = 0xfff; 317 318 tsc2005_pin_update(s); 319 } 320 321 static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value) 322 { 323 TSC2005State *s = opaque; 324 uint32_t ret = 0; 325 326 switch (s->state ++) { 327 case 0: 328 if (value & 0x80) { 329 /* Command */ 330 if (value & (1 << 1)) 331 tsc2005_reset(s); 332 else { 333 s->nextfunction = (value >> 3) & 0xf; 334 s->nextprecision = (value >> 2) & 1; 335 if (s->enabled != !(value & 1)) { 336 s->enabled = !(value & 1); 337 fprintf(stderr, "%s: touchscreen sense %sabled\n", 338 __FUNCTION__, s->enabled ? "en" : "dis"); 339 if (s->busy && !s->enabled) 340 qemu_del_timer(s->timer); 341 s->busy &= s->enabled; 342 } 343 tsc2005_pin_update(s); 344 } 345 346 s->state = 0; 347 } else if (value) { 348 /* Data transfer */ 349 s->reg = (value >> 3) & 0xf; 350 s->pnd0 = (value >> 1) & 1; 351 s->command = value & 1; 352 353 if (s->command) { 354 /* Read */ 355 s->data = tsc2005_read(s, s->reg); 356 tsc2005_pin_update(s); 357 } else 358 s->data = 0; 359 } else 360 s->state = 0; 361 break; 362 363 case 1: 364 if (s->command) 365 ret = (s->data >> 8) & 0xff; 366 else 367 s->data |= value << 8; 368 break; 369 370 case 2: 371 if (s->command) 372 ret = s->data & 0xff; 373 else { 374 s->data |= value; 375 tsc2005_write(s, s->reg, s->data); 376 tsc2005_pin_update(s); 377 } 378 379 s->state = 0; 380 break; 381 } 382 383 return ret; 384 } 385 386 uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len) 387 { 388 uint32_t ret = 0; 389 390 len &= ~7; 391 while (len > 0) { 392 len -= 8; 393 ret |= tsc2005_txrx_word(opaque, (value >> len) & 0xff) << len; 394 } 395 396 return ret; 397 } 398 399 static void tsc2005_timer_tick(void *opaque) 400 { 401 TSC2005State *s = opaque; 402 403 /* Timer ticked -- a set of conversions has been finished. */ 404 405 if (!s->busy) 406 return; 407 408 s->busy = 0; 409 s->dav |= mode_regs[s->function]; 410 s->function = -1; 411 tsc2005_pin_update(s); 412 } 413 414 static void tsc2005_touchscreen_event(void *opaque, 415 int x, int y, int z, int buttons_state) 416 { 417 TSC2005State *s = opaque; 418 int p = s->pressure; 419 420 if (buttons_state) { 421 s->x = x; 422 s->y = y; 423 } 424 s->pressure = !!buttons_state; 425 426 /* 427 * Note: We would get better responsiveness in the guest by 428 * signaling TS events immediately, but for now we simulate 429 * the first conversion delay for sake of correctness. 430 */ 431 if (p != s->pressure) 432 tsc2005_pin_update(s); 433 } 434 435 static void tsc2005_save(QEMUFile *f, void *opaque) 436 { 437 TSC2005State *s = (TSC2005State *) opaque; 438 int i; 439 440 qemu_put_be16(f, s->x); 441 qemu_put_be16(f, s->y); 442 qemu_put_byte(f, s->pressure); 443 444 qemu_put_byte(f, s->state); 445 qemu_put_byte(f, s->reg); 446 qemu_put_byte(f, s->command); 447 448 qemu_put_byte(f, s->irq); 449 qemu_put_be16s(f, &s->dav); 450 qemu_put_be16s(f, &s->data); 451 452 qemu_put_timer(f, s->timer); 453 qemu_put_byte(f, s->enabled); 454 qemu_put_byte(f, s->host_mode); 455 qemu_put_byte(f, s->function); 456 qemu_put_byte(f, s->nextfunction); 457 qemu_put_byte(f, s->precision); 458 qemu_put_byte(f, s->nextprecision); 459 qemu_put_be16(f, s->filter); 460 qemu_put_byte(f, s->pin_func); 461 qemu_put_be16(f, s->timing[0]); 462 qemu_put_be16(f, s->timing[1]); 463 qemu_put_be16s(f, &s->temp_thr[0]); 464 qemu_put_be16s(f, &s->temp_thr[1]); 465 qemu_put_be16s(f, &s->aux_thr[0]); 466 qemu_put_be16s(f, &s->aux_thr[1]); 467 qemu_put_be32(f, s->noise); 468 qemu_put_byte(f, s->reset); 469 qemu_put_byte(f, s->pdst); 470 qemu_put_byte(f, s->pnd0); 471 472 for (i = 0; i < 8; i ++) 473 qemu_put_be32(f, s->tr[i]); 474 } 475 476 static int tsc2005_load(QEMUFile *f, void *opaque, int version_id) 477 { 478 TSC2005State *s = (TSC2005State *) opaque; 479 int i; 480 481 s->x = qemu_get_be16(f); 482 s->y = qemu_get_be16(f); 483 s->pressure = qemu_get_byte(f); 484 485 s->state = qemu_get_byte(f); 486 s->reg = qemu_get_byte(f); 487 s->command = qemu_get_byte(f); 488 489 s->irq = qemu_get_byte(f); 490 qemu_get_be16s(f, &s->dav); 491 qemu_get_be16s(f, &s->data); 492 493 qemu_get_timer(f, s->timer); 494 s->enabled = qemu_get_byte(f); 495 s->host_mode = qemu_get_byte(f); 496 s->function = qemu_get_byte(f); 497 s->nextfunction = qemu_get_byte(f); 498 s->precision = qemu_get_byte(f); 499 s->nextprecision = qemu_get_byte(f); 500 s->filter = qemu_get_be16(f); 501 s->pin_func = qemu_get_byte(f); 502 s->timing[0] = qemu_get_be16(f); 503 s->timing[1] = qemu_get_be16(f); 504 qemu_get_be16s(f, &s->temp_thr[0]); 505 qemu_get_be16s(f, &s->temp_thr[1]); 506 qemu_get_be16s(f, &s->aux_thr[0]); 507 qemu_get_be16s(f, &s->aux_thr[1]); 508 s->noise = qemu_get_be32(f); 509 s->reset = qemu_get_byte(f); 510 s->pdst = qemu_get_byte(f); 511 s->pnd0 = qemu_get_byte(f); 512 513 for (i = 0; i < 8; i ++) 514 s->tr[i] = qemu_get_be32(f); 515 516 s->busy = qemu_timer_pending(s->timer); 517 tsc2005_pin_update(s); 518 519 return 0; 520 } 521 522 void *tsc2005_init(qemu_irq pintdav) 523 { 524 TSC2005State *s; 525 526 s = (TSC2005State *) 527 g_malloc0(sizeof(TSC2005State)); 528 s->x = 400; 529 s->y = 240; 530 s->pressure = 0; 531 s->precision = s->nextprecision = 0; 532 s->timer = qemu_new_timer_ns(vm_clock, tsc2005_timer_tick, s); 533 s->pint = pintdav; 534 s->model = 0x2005; 535 536 s->tr[0] = 0; 537 s->tr[1] = 1; 538 s->tr[2] = 1; 539 s->tr[3] = 0; 540 s->tr[4] = 1; 541 s->tr[5] = 0; 542 s->tr[6] = 1; 543 s->tr[7] = 0; 544 545 tsc2005_reset(s); 546 547 qemu_add_mouse_event_handler(tsc2005_touchscreen_event, s, 1, 548 "QEMU TSC2005-driven Touchscreen"); 549 550 qemu_register_reset((void *) tsc2005_reset, s); 551 register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s); 552 553 return s; 554 } 555 556 /* 557 * Use tslib generated calibration data to generate ADC input values 558 * from the touchscreen. Assuming 12-bit precision was used during 559 * tslib calibration. 560 */ 561 void tsc2005_set_transform(void *opaque, MouseTransformInfo *info) 562 { 563 TSC2005State *s = (TSC2005State *) opaque; 564 565 /* This version assumes touchscreen X & Y axis are parallel or 566 * perpendicular to LCD's X & Y axis in some way. */ 567 if (abs(info->a[0]) > abs(info->a[1])) { 568 s->tr[0] = 0; 569 s->tr[1] = -info->a[6] * info->x; 570 s->tr[2] = info->a[0]; 571 s->tr[3] = -info->a[2] / info->a[0]; 572 s->tr[4] = info->a[6] * info->y; 573 s->tr[5] = 0; 574 s->tr[6] = info->a[4]; 575 s->tr[7] = -info->a[5] / info->a[4]; 576 } else { 577 s->tr[0] = info->a[6] * info->y; 578 s->tr[1] = 0; 579 s->tr[2] = info->a[1]; 580 s->tr[3] = -info->a[2] / info->a[1]; 581 s->tr[4] = 0; 582 s->tr[5] = -info->a[6] * info->x; 583 s->tr[6] = info->a[3]; 584 s->tr[7] = -info->a[5] / info->a[3]; 585 } 586 587 s->tr[0] >>= 11; 588 s->tr[1] >>= 11; 589 s->tr[3] <<= 4; 590 s->tr[4] >>= 11; 591 s->tr[5] >>= 11; 592 s->tr[7] <<= 4; 593 } 594