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