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