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