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