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) + (get_ticks_per_sec() >> 7); 295 timer_mod(s->timer, expires); 296 } 297 298 static void tsc2005_reset(TSC2005State *s) 299 { 300 s->state = 0; 301 s->pin_func = 0; 302 s->enabled = 0; 303 s->busy = 0; 304 s->nextprecision = 0; 305 s->nextfunction = 0; 306 s->timing[0] = 0; 307 s->timing[1] = 0; 308 s->irq = 0; 309 s->dav = 0; 310 s->reset = 0; 311 s->pdst = 1; 312 s->pnd0 = 0; 313 s->function = -1; 314 s->temp_thr[0] = 0x000; 315 s->temp_thr[1] = 0xfff; 316 s->aux_thr[0] = 0x000; 317 s->aux_thr[1] = 0xfff; 318 319 tsc2005_pin_update(s); 320 } 321 322 static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value) 323 { 324 TSC2005State *s = opaque; 325 uint32_t ret = 0; 326 327 switch (s->state ++) { 328 case 0: 329 if (value & 0x80) { 330 /* Command */ 331 if (value & (1 << 1)) 332 tsc2005_reset(s); 333 else { 334 s->nextfunction = (value >> 3) & 0xf; 335 s->nextprecision = (value >> 2) & 1; 336 if (s->enabled != !(value & 1)) { 337 s->enabled = !(value & 1); 338 fprintf(stderr, "%s: touchscreen sense %sabled\n", 339 __FUNCTION__, s->enabled ? "en" : "dis"); 340 if (s->busy && !s->enabled) 341 timer_del(s->timer); 342 s->busy &= s->enabled; 343 } 344 tsc2005_pin_update(s); 345 } 346 347 s->state = 0; 348 } else if (value) { 349 /* Data transfer */ 350 s->reg = (value >> 3) & 0xf; 351 s->pnd0 = (value >> 1) & 1; 352 s->command = value & 1; 353 354 if (s->command) { 355 /* Read */ 356 s->data = tsc2005_read(s, s->reg); 357 tsc2005_pin_update(s); 358 } else 359 s->data = 0; 360 } else 361 s->state = 0; 362 break; 363 364 case 1: 365 if (s->command) 366 ret = (s->data >> 8) & 0xff; 367 else 368 s->data |= value << 8; 369 break; 370 371 case 2: 372 if (s->command) 373 ret = s->data & 0xff; 374 else { 375 s->data |= value; 376 tsc2005_write(s, s->reg, s->data); 377 tsc2005_pin_update(s); 378 } 379 380 s->state = 0; 381 break; 382 } 383 384 return ret; 385 } 386 387 uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len) 388 { 389 uint32_t ret = 0; 390 391 len &= ~7; 392 while (len > 0) { 393 len -= 8; 394 ret |= tsc2005_txrx_word(opaque, (value >> len) & 0xff) << len; 395 } 396 397 return ret; 398 } 399 400 static void tsc2005_timer_tick(void *opaque) 401 { 402 TSC2005State *s = opaque; 403 404 /* Timer ticked -- a set of conversions has been finished. */ 405 406 if (!s->busy) 407 return; 408 409 s->busy = 0; 410 s->dav |= mode_regs[s->function]; 411 s->function = -1; 412 tsc2005_pin_update(s); 413 } 414 415 static void tsc2005_touchscreen_event(void *opaque, 416 int x, int y, int z, int buttons_state) 417 { 418 TSC2005State *s = opaque; 419 int p = s->pressure; 420 421 if (buttons_state) { 422 s->x = x; 423 s->y = y; 424 } 425 s->pressure = !!buttons_state; 426 427 /* 428 * Note: We would get better responsiveness in the guest by 429 * signaling TS events immediately, but for now we simulate 430 * the first conversion delay for sake of correctness. 431 */ 432 if (p != s->pressure) 433 tsc2005_pin_update(s); 434 } 435 436 static void tsc2005_save(QEMUFile *f, void *opaque) 437 { 438 TSC2005State *s = (TSC2005State *) opaque; 439 int i; 440 441 qemu_put_be16(f, s->x); 442 qemu_put_be16(f, s->y); 443 qemu_put_byte(f, s->pressure); 444 445 qemu_put_byte(f, s->state); 446 qemu_put_byte(f, s->reg); 447 qemu_put_byte(f, s->command); 448 449 qemu_put_byte(f, s->irq); 450 qemu_put_be16s(f, &s->dav); 451 qemu_put_be16s(f, &s->data); 452 453 timer_put(f, s->timer); 454 qemu_put_byte(f, s->enabled); 455 qemu_put_byte(f, s->host_mode); 456 qemu_put_byte(f, s->function); 457 qemu_put_byte(f, s->nextfunction); 458 qemu_put_byte(f, s->precision); 459 qemu_put_byte(f, s->nextprecision); 460 qemu_put_be16(f, s->filter); 461 qemu_put_byte(f, s->pin_func); 462 qemu_put_be16(f, s->timing[0]); 463 qemu_put_be16(f, s->timing[1]); 464 qemu_put_be16s(f, &s->temp_thr[0]); 465 qemu_put_be16s(f, &s->temp_thr[1]); 466 qemu_put_be16s(f, &s->aux_thr[0]); 467 qemu_put_be16s(f, &s->aux_thr[1]); 468 qemu_put_be32(f, s->noise); 469 qemu_put_byte(f, s->reset); 470 qemu_put_byte(f, s->pdst); 471 qemu_put_byte(f, s->pnd0); 472 473 for (i = 0; i < 8; i ++) 474 qemu_put_be32(f, s->tr[i]); 475 } 476 477 static int tsc2005_load(QEMUFile *f, void *opaque, int version_id) 478 { 479 TSC2005State *s = (TSC2005State *) opaque; 480 int i; 481 482 s->x = qemu_get_be16(f); 483 s->y = qemu_get_be16(f); 484 s->pressure = qemu_get_byte(f); 485 486 s->state = qemu_get_byte(f); 487 s->reg = qemu_get_byte(f); 488 s->command = qemu_get_byte(f); 489 490 s->irq = qemu_get_byte(f); 491 qemu_get_be16s(f, &s->dav); 492 qemu_get_be16s(f, &s->data); 493 494 timer_get(f, s->timer); 495 s->enabled = qemu_get_byte(f); 496 s->host_mode = qemu_get_byte(f); 497 s->function = qemu_get_byte(f); 498 s->nextfunction = qemu_get_byte(f); 499 s->precision = qemu_get_byte(f); 500 s->nextprecision = qemu_get_byte(f); 501 s->filter = qemu_get_be16(f); 502 s->pin_func = qemu_get_byte(f); 503 s->timing[0] = qemu_get_be16(f); 504 s->timing[1] = qemu_get_be16(f); 505 qemu_get_be16s(f, &s->temp_thr[0]); 506 qemu_get_be16s(f, &s->temp_thr[1]); 507 qemu_get_be16s(f, &s->aux_thr[0]); 508 qemu_get_be16s(f, &s->aux_thr[1]); 509 s->noise = qemu_get_be32(f); 510 s->reset = qemu_get_byte(f); 511 s->pdst = qemu_get_byte(f); 512 s->pnd0 = qemu_get_byte(f); 513 514 for (i = 0; i < 8; i ++) 515 s->tr[i] = qemu_get_be32(f); 516 517 s->busy = timer_pending(s->timer); 518 tsc2005_pin_update(s); 519 520 return 0; 521 } 522 523 void *tsc2005_init(qemu_irq pintdav) 524 { 525 TSC2005State *s; 526 527 s = (TSC2005State *) 528 g_malloc0(sizeof(TSC2005State)); 529 s->x = 400; 530 s->y = 240; 531 s->pressure = 0; 532 s->precision = s->nextprecision = 0; 533 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc2005_timer_tick, s); 534 s->pint = pintdav; 535 s->model = 0x2005; 536 537 s->tr[0] = 0; 538 s->tr[1] = 1; 539 s->tr[2] = 1; 540 s->tr[3] = 0; 541 s->tr[4] = 1; 542 s->tr[5] = 0; 543 s->tr[6] = 1; 544 s->tr[7] = 0; 545 546 tsc2005_reset(s); 547 548 qemu_add_mouse_event_handler(tsc2005_touchscreen_event, s, 1, 549 "QEMU TSC2005-driven Touchscreen"); 550 551 qemu_register_reset((void *) tsc2005_reset, s); 552 register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s); 553 554 return s; 555 } 556 557 /* 558 * Use tslib generated calibration data to generate ADC input values 559 * from the touchscreen. Assuming 12-bit precision was used during 560 * tslib calibration. 561 */ 562 void tsc2005_set_transform(void *opaque, MouseTransformInfo *info) 563 { 564 TSC2005State *s = (TSC2005State *) opaque; 565 566 /* This version assumes touchscreen X & Y axis are parallel or 567 * perpendicular to LCD's X & Y axis in some way. */ 568 if (abs(info->a[0]) > abs(info->a[1])) { 569 s->tr[0] = 0; 570 s->tr[1] = -info->a[6] * info->x; 571 s->tr[2] = info->a[0]; 572 s->tr[3] = -info->a[2] / info->a[0]; 573 s->tr[4] = info->a[6] * info->y; 574 s->tr[5] = 0; 575 s->tr[6] = info->a[4]; 576 s->tr[7] = -info->a[5] / info->a[4]; 577 } else { 578 s->tr[0] = info->a[6] * info->y; 579 s->tr[1] = 0; 580 s->tr[2] = info->a[1]; 581 s->tr[3] = -info->a[2] / info->a[1]; 582 s->tr[4] = 0; 583 s->tr[5] = -info->a[6] * info->x; 584 s->tr[6] = info->a[3]; 585 s->tr[7] = -info->a[5] / info->a[3]; 586 } 587 588 s->tr[0] >>= 11; 589 s->tr[1] >>= 11; 590 s->tr[3] <<= 4; 591 s->tr[4] >>= 11; 592 s->tr[5] >>= 11; 593 s->tr[7] <<= 4; 594 } 595