1 /* $NetBSD: ztp.c,v 1.17 2023/12/20 15:34:46 thorpej Exp $ */ 2 /* $OpenBSD: zts.c,v 1.9 2005/04/24 18:55:49 uwe Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: ztp.c,v 1.17 2023/12/20 15:34:46 thorpej Exp $"); 22 23 #include "lcd.h" 24 #include "w100lcd.h" 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/device.h> 30 #include <sys/kernel.h> 31 #include <sys/callout.h> 32 33 #include <dev/wscons/wsconsio.h> 34 #include <dev/wscons/wsmousevar.h> 35 #include <dev/wscons/wsdisplayvar.h> 36 37 #include <dev/hpc/hpcfbio.h> /* XXX: for tpctl */ 38 #include <dev/hpc/hpctpanelvar.h> 39 40 #include <arm/xscale/pxa2x0cpu.h> 41 #include <arm/xscale/pxa2x0reg.h> 42 #include <arm/xscale/pxa2x0var.h> 43 #include <arm/xscale/xscalereg.h> 44 #include <arm/xscale/pxa2x0_gpio.h> 45 #if NLCD > 0 46 #include <arm/xscale/pxa2x0_lcd.h> 47 #endif 48 #if NW100LCD > 0 49 #include <zaurus/dev/w100var.h> 50 #endif 51 52 #include <zaurus/zaurus/zaurus_var.h> 53 #include <zaurus/dev/zsspvar.h> 54 #ifdef ZTP_DEBUG 55 #define DPRINTF(s) printf s 56 #else 57 #define DPRINTF(s) 58 #endif 59 60 /* 61 * ADS784x touch screen controller 62 */ 63 #define ADSCTRL_PD0_SH 0 /* PD0 bit */ 64 #define ADSCTRL_PD1_SH 1 /* PD1 bit */ 65 #define ADSCTRL_DFR_SH 2 /* SER/DFR bit */ 66 #define ADSCTRL_MOD_SH 3 /* Mode bit */ 67 #define ADSCTRL_ADR_SH 4 /* Address setting */ 68 #define ADSCTRL_STS_SH 7 /* Start bit */ 69 70 #define GPIO_TP_INT_C3K 11 71 #define GPIO_HSYNC_C3K 22 72 #define GPIO_TP_INT_C860 5 73 #define GPIO_HSYNC_C860 44 74 75 #define POLL_TIMEOUT_RATE0 ((hz * 150)/1000) 76 #define POLL_TIMEOUT_RATE1 (hz / 100) /* XXX every tick */ 77 78 #define CCNT_HS_400_VGA_C3K 6250 /* 15.024us */ 79 #define CCNT_HS_400_VGA_C860 7013 /* 17.615us */ 80 81 /* XXX need to ask lcd drivers for the screen dimension */ 82 #if NLCD > 0 83 extern const struct lcd_panel_geometry lcd_panel_geometry_c3000; 84 #endif 85 #if NW100LCD > 0 86 extern const struct w100_panel_geometry lcd_panel_geometry_c700; 87 #endif 88 89 /* Settable via sysctl. */ 90 int ztp_rawmode; 91 92 static const struct wsmouse_calibcoords ztp_default_calib = { 93 0, 0, 479, 639, /* minx, miny, maxx, maxy */ 94 5, /* samplelen */ 95 { 96 { 1929, 2021, 240, 320 }, /* rawx, rawy, x, y */ 97 { 545, 3464, 48, 64 }, 98 { 3308, 3452, 48, 576 }, 99 { 2854, 768, 432, 576 }, 100 { 542, 593, 432, 64 } 101 } 102 }; 103 104 struct ztp_pos { 105 int x; 106 int y; 107 int z; /* touch pressure */ 108 }; 109 110 struct ztp_softc { 111 device_t sc_dev; 112 struct callout sc_tp_poll; 113 void *sc_gh; 114 int sc_enabled; 115 int sc_buttons; /* button emulation ? */ 116 device_t sc_wsmousedev; 117 struct ztp_pos sc_oldpos; 118 int sc_resx; 119 int sc_resy; 120 struct tpcalib_softc sc_tpcalib; 121 122 u_int sc_tp_int_pin; 123 u_int sc_hsync_pin; 124 u_int sc_ccnt_hs; 125 }; 126 127 static int ztp_match(device_t, cfdata_t, void *); 128 static void ztp_attach(device_t, device_t, void *); 129 130 CFATTACH_DECL_NEW(ztp, sizeof(struct ztp_softc), 131 ztp_match, ztp_attach, NULL, NULL); 132 133 static int ztp_finalize(device_t); 134 static int ztp_enable(void *); 135 static void ztp_disable(void *); 136 static bool ztp_suspend(device_t dv, const pmf_qual_t *); 137 static bool ztp_resume(device_t dv, const pmf_qual_t *); 138 static void ztp_poll(void *); 139 static int ztp_irq(void *); 140 static int ztp_ioctl(void *, u_long, void *, int, struct lwp *); 141 142 static const struct wsmouse_accessops ztp_accessops = { 143 ztp_enable, 144 ztp_ioctl, 145 ztp_disable 146 }; 147 148 static int 149 ztp_match(device_t parent, cfdata_t cf, void *aux) 150 { 151 struct zssp_attach_args *aa = aux; 152 153 if (strcmp("ztp", aa->zaa_name)) 154 return 0; 155 return 1; 156 } 157 158 static void 159 ztp_attach(device_t parent, device_t self, void *aux) 160 { 161 struct ztp_softc *sc = device_private(self); 162 struct wsmousedev_attach_args a; 163 164 sc->sc_dev = self; 165 166 aprint_normal("\n"); 167 aprint_naive("\n"); 168 169 callout_init(&sc->sc_tp_poll, 0); 170 callout_setfunc(&sc->sc_tp_poll, ztp_poll, sc); 171 172 /* defer initialization until all other devices are attached */ 173 config_finalize_register(self, ztp_finalize); 174 175 a.accessops = &ztp_accessops; 176 a.accesscookie = sc; 177 178 #if NLCD > 0 || NW100LCD > 0 /* XXX */ 179 #if NLCD > 0 180 if (ZAURUS_ISC1000 || ZAURUS_ISC3000) { 181 sc->sc_resx = lcd_panel_geometry_c3000.panel_height; 182 sc->sc_resy = lcd_panel_geometry_c3000.panel_width; 183 } else 184 #endif 185 #if NW100LCD > 0 186 if (ZAURUS_ISC860) { 187 sc->sc_resx = lcd_panel_geometry_c700.panel_height; 188 sc->sc_resy = lcd_panel_geometry_c700.panel_width; 189 } else 190 #endif 191 #endif 192 { 193 sc->sc_resx = 480; /* XXX */ 194 sc->sc_resy = 640; /* XXX */ 195 } 196 197 if (ZAURUS_ISC1000 || ZAURUS_ISC3000) { 198 sc->sc_tp_int_pin = GPIO_TP_INT_C3K; 199 sc->sc_hsync_pin = GPIO_HSYNC_C3K; 200 sc->sc_ccnt_hs = CCNT_HS_400_VGA_C3K; 201 } else { 202 /* C7x0/C860 */ 203 sc->sc_tp_int_pin = GPIO_TP_INT_C860; 204 sc->sc_hsync_pin = GPIO_HSYNC_C860; 205 sc->sc_ccnt_hs = CCNT_HS_400_VGA_C860; 206 } 207 208 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE); 209 210 /* Initialize calibration, set default parameters. */ 211 tpcalib_init(&sc->sc_tpcalib); 212 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 213 __UNCONST(&ztp_default_calib), 0, 0); 214 } 215 216 static int 217 ztp_finalize(device_t dv) 218 { 219 220 /* Initialize ADS7846 Difference Reference mode */ 221 (void)zssp_ic_send(ZSSP_IC_ADS7846, 222 (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH)); 223 delay(5000); 224 (void)zssp_ic_send(ZSSP_IC_ADS7846, 225 (3<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH)); 226 delay(5000); 227 (void)zssp_ic_send(ZSSP_IC_ADS7846, 228 (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH)); 229 delay(5000); 230 (void)zssp_ic_send(ZSSP_IC_ADS7846, 231 (5<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH)); 232 delay(5000); 233 234 return 0; 235 } 236 237 static int 238 ztp_enable(void *v) 239 { 240 struct ztp_softc *sc = (struct ztp_softc *)v; 241 242 DPRINTF(("%s: ztp_enable()\n", device_xname(sc->sc_dev))); 243 244 if (sc->sc_enabled) { 245 DPRINTF(("%s: already enabled\n", device_xname(sc->sc_dev))); 246 return EBUSY; 247 } 248 249 callout_stop(&sc->sc_tp_poll); 250 251 if (!pmf_device_register(sc->sc_dev, ztp_suspend, ztp_resume)) 252 aprint_error_dev(sc->sc_dev, 253 "couldn't establish power handler\n"); 254 255 pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_IN); 256 257 /* XXX */ 258 if (sc->sc_gh == NULL) { 259 sc->sc_gh = pxa2x0_gpio_intr_establish(sc->sc_tp_int_pin, 260 IST_EDGE_FALLING, IPL_TTY, ztp_irq, sc); 261 } else { 262 pxa2x0_gpio_intr_unmask(sc->sc_gh); 263 } 264 265 /* enable interrupts */ 266 sc->sc_enabled = 1; 267 sc->sc_buttons = 0; 268 269 return 0; 270 } 271 272 static void 273 ztp_disable(void *v) 274 { 275 struct ztp_softc *sc = (struct ztp_softc *)v; 276 277 DPRINTF(("%s: ztp_disable()\n", device_xname(sc->sc_dev))); 278 279 callout_stop(&sc->sc_tp_poll); 280 281 pmf_device_deregister(sc->sc_dev); 282 283 if (sc->sc_gh) { 284 pxa2x0_gpio_intr_mask(sc->sc_gh); 285 } 286 287 /* disable interrupts */ 288 sc->sc_enabled = 0; 289 } 290 291 static bool 292 ztp_suspend(device_t dv, const pmf_qual_t *qual) 293 { 294 struct ztp_softc *sc = device_private(dv); 295 296 DPRINTF(("%s: ztp_suspend()\n", device_xname(sc->sc_dev))); 297 298 sc->sc_enabled = 0; 299 pxa2x0_gpio_intr_mask(sc->sc_gh); 300 301 callout_stop(&sc->sc_tp_poll); 302 303 /* Turn off reference voltage but leave ADC on. */ 304 (void)zssp_ic_send(ZSSP_IC_ADS7846, (1 << ADSCTRL_PD1_SH) | 305 (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH)); 306 307 pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_OUT | GPIO_SET); 308 309 return true; 310 } 311 312 static bool 313 ztp_resume(device_t dv, const pmf_qual_t *qual) 314 { 315 struct ztp_softc *sc = device_private(dv); 316 317 DPRINTF(("%s: ztp_resume()\n", device_xname(sc->sc_dev))); 318 319 pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_IN); 320 pxa2x0_gpio_intr_mask(sc->sc_gh); 321 322 /* Enable automatic low power mode. */ 323 (void)zssp_ic_send(ZSSP_IC_ADS7846, 324 (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH)); 325 326 pxa2x0_gpio_intr_unmask(sc->sc_gh); 327 sc->sc_enabled = 1; 328 329 return true; 330 } 331 332 #define HSYNC() \ 333 do { \ 334 while (pxa2x0_gpio_get_bit(sc->sc_hsync_pin) == 0) \ 335 continue; \ 336 while (pxa2x0_gpio_get_bit(sc->sc_hsync_pin) != 0) \ 337 continue; \ 338 } while (/*CONSTCOND*/0) 339 340 static inline uint32_t pxa2x0_ccnt_enable(uint32_t); 341 static inline uint32_t pxa2x0_read_ccnt(void); 342 static uint32_t ztp_sync_ads784x(struct ztp_softc *, int, int, uint32_t); 343 static void ztp_sync_send(struct ztp_softc *, uint32_t); 344 static int ztp_readpos(struct ztp_softc *, struct ztp_pos *); 345 346 static inline uint32_t 347 pxa2x0_ccnt_enable(uint32_t reg) 348 { 349 uint32_t rv; 350 351 __asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (rv)); 352 __asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (reg)); 353 354 return rv; 355 } 356 357 static inline uint32_t 358 pxa2x0_read_ccnt(void) 359 { 360 uint32_t rv; 361 362 __asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (rv)); 363 364 return rv; 365 } 366 367 /* 368 * Communicate synchronously with the ADS784x touch screen controller. 369 */ 370 static uint32_t 371 ztp_sync_ads784x(struct ztp_softc *sc, int dorecv/* XXX */, 372 int dosend/* XXX */, uint32_t cmd) 373 { 374 uint32_t ccen; 375 uint32_t rv = 0; 376 377 /* XXX poll hsync only if LCD is enabled */ 378 379 /* start clock counter */ 380 ccen = pxa2x0_ccnt_enable(PMNC_E); 381 382 HSYNC(); 383 384 if (dorecv) { 385 /* read SSDR and disable ADS784x */ 386 rv = zssp_ic_stop(ZSSP_IC_ADS7846); 387 } 388 389 if (dosend) { 390 ztp_sync_send(sc, cmd); 391 } 392 393 /* stop clock counter */ 394 pxa2x0_ccnt_enable(ccen); 395 396 return rv; 397 } 398 399 void 400 ztp_sync_send(struct ztp_softc *sc, uint32_t cmd) 401 { 402 volatile uint32_t base, now; 403 uint32_t tck; 404 405 /* XXX */ 406 tck = sc->sc_ccnt_hs - 151; 407 /* XXX: for one more delay(1) */ 408 tck -= 400; 409 410 /* send dummy command; discard SSDR */ 411 (void)zssp_ic_send(ZSSP_IC_ADS7846, cmd); 412 413 /* wait for refresh */ 414 HSYNC(); 415 416 /* wait after refresh */ 417 base = pxa2x0_read_ccnt(); 418 now = pxa2x0_read_ccnt(); 419 while ((now - base) < tck) 420 now = pxa2x0_read_ccnt(); 421 422 /* send the actual command; keep ADS784x enabled */ 423 zssp_ic_start(ZSSP_IC_ADS7846, cmd); 424 } 425 426 static int 427 ztp_readpos(struct ztp_softc *sc, struct ztp_pos *pos) 428 { 429 int cmd; 430 int t0, t1; 431 int down; 432 433 /* XXX */ 434 pxa2x0_gpio_set_function(sc->sc_hsync_pin, GPIO_IN); 435 436 /* check that pen is down */ 437 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 438 (3 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 439 t0 = zssp_ic_send(ZSSP_IC_ADS7846, cmd); 440 DPRINTF(("ztp_readpos(): t0 = %d\n", t0)); 441 442 down = (t0 >= 10); 443 if (down == 0) 444 goto out; 445 446 /* Y */ 447 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 448 (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 449 (void)ztp_sync_ads784x(sc, 0, 1, cmd); 450 451 /* Y */ 452 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 453 (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 454 (void)ztp_sync_ads784x(sc, 1, 1, cmd); 455 456 /* X */ 457 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 458 (5 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 459 pos->y = ztp_sync_ads784x(sc, 1, 1, cmd); 460 DPRINTF(("ztp_readpos(): y = %d\n", pos->y)); 461 462 /* T0 */ 463 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 464 (3 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 465 pos->x = ztp_sync_ads784x(sc, 1, 1, cmd); 466 DPRINTF(("ztp_readpos(): x = %d\n", pos->x)); 467 468 /* T1 */ 469 cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) | 470 (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 471 t0 = ztp_sync_ads784x(sc, 1, 1, cmd); 472 t1 = ztp_sync_ads784x(sc, 1, 0, cmd); 473 DPRINTF(("ztp_readpos(): t0 = %d, t1 = %d\n", t0, t1)); 474 475 /* check that pen is still down */ 476 /* XXX pressure sensitivity varies with X or what? */ 477 if (t0 == 0 || (pos->x * (t1 - t0) / t0) >= 15000) 478 down = 0; 479 pos->z = down; 480 481 out: 482 /* Enable automatic low power mode. */ 483 cmd = (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH); 484 (void)zssp_ic_send(ZSSP_IC_ADS7846, cmd); 485 486 return down; 487 } 488 489 static void 490 ztp_poll(void *v) 491 { 492 int s; 493 494 s = spltty(); 495 (void)ztp_irq(v); 496 splx(s); 497 } 498 499 static int 500 ztp_irq(void *v) 501 { 502 extern int zkbd_modstate; 503 struct ztp_softc *sc = (struct ztp_softc *)v; 504 struct ztp_pos tp = { 0, 0, 0 }; 505 int pindown; 506 int down; 507 int x, y; 508 int s; 509 510 if (!sc->sc_enabled) 511 return 0; 512 513 s = splhigh(); 514 515 pindown = pxa2x0_gpio_get_bit(sc->sc_tp_int_pin) ? 0 : 1; 516 DPRINTF(("%s: pindown = %d\n", device_xname(sc->sc_dev), pindown)); 517 if (pindown) { 518 pxa2x0_gpio_intr_mask(sc->sc_gh); 519 callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE1); 520 } 521 522 down = ztp_readpos(sc, &tp); 523 DPRINTF(("%s: x = %d, y = %d, z = %d, down = %d\n", 524 device_xname(sc->sc_dev), tp.x, tp.y, tp.z, down)); 525 526 if (!pindown) { 527 pxa2x0_gpio_intr_unmask(sc->sc_gh); 528 callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE0); 529 } 530 pxa2x0_gpio_clear_intr(sc->sc_tp_int_pin); 531 532 splx(s); 533 534 if (down) { 535 if (!ztp_rawmode) { 536 tpcalib_trans(&sc->sc_tpcalib, tp.x, tp.y, &x, &y); 537 DPRINTF(("%s: x = %d, y = %d\n", 538 device_xname(sc->sc_dev), x, y)); 539 tp.x = x; 540 tp.y = y; 541 } 542 } 543 544 if (zkbd_modstate != 0 && down) { 545 if (zkbd_modstate & (1 << 1)) { 546 /* Fn */ 547 down = 2; 548 } else if (zkbd_modstate & (1 << 2)) { 549 /* 'Alt' */ 550 down = 4; 551 } 552 } 553 if (!down) { 554 /* x/y values are not reliable when pen is up */ 555 tp = sc->sc_oldpos; 556 } 557 558 if (down || sc->sc_buttons != down) { 559 wsmouse_input(sc->sc_wsmousedev, down, tp.x, tp.y, 0, 0, 560 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 561 sc->sc_buttons = down; 562 sc->sc_oldpos = tp; 563 } 564 565 return 1; 566 } 567 568 static int 569 ztp_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 570 { 571 struct ztp_softc *sc = (struct ztp_softc *)v; 572 struct wsmouse_id *id; 573 574 switch (cmd) { 575 case WSMOUSEIO_GTYPE: 576 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 577 return 0; 578 579 case WSMOUSEIO_GETID: 580 /* 581 * return unique ID string, 582 * "<vendor> <model> <serial number>" 583 */ 584 id = (struct wsmouse_id *)data; 585 if (id->type != WSMOUSE_ID_TYPE_UIDSTR) 586 return EINVAL; 587 strlcpy(id->data, "Sharp SL-C3x00 SN000000", WSMOUSE_ID_MAXLEN); 588 id->length = strlen(id->data); 589 return 0; 590 591 case WSMOUSEIO_SCALIBCOORDS: 592 case WSMOUSEIO_GCALIBCOORDS: 593 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 594 } 595 596 return EPASSTHROUGH; 597 } 598