1 /* $NetBSD: ztp.c,v 1.8 2009/12/12 07:49:31 nonaka Exp $ */
2 /* $OpenBSD: zts.c,v 1.9 2005/04/24 18:55:49 uwe Exp $ */
5 * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
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.
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.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: ztp.c,v 1.8 2009/12/12 07:49:31 nonaka Exp $");
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/device.h>
29 #include <sys/malloc.h>
30 #include <sys/kernel.h>
31 #include <sys/callout.h>
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wscons/wsmousevar.h>
35 #include <dev/wscons/wsdisplayvar.h>
37 #include <dev/hpc/hpcfbio.h> /* XXX: for tpctl */
38 #include <dev/hpc/hpctpanelvar.h>
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_lcd.h>
45 #include <arm/xscale/pxa2x0_gpio.h>
47 #include <zaurus/dev/zsspvar.h>
50 #define DPRINTF(s) printf s
56 * ADS784x touch screen controller
58 #define ADSCTRL_PD0_SH 0 /* PD0 bit */
59 #define ADSCTRL_PD1_SH 1 /* PD1 bit */
60 #define ADSCTRL_DFR_SH 2 /* SER/DFR bit */
61 #define ADSCTRL_MOD_SH 3 /* Mode bit */
62 #define ADSCTRL_ADR_SH 4 /* Address setting */
63 #define ADSCTRL_STS_SH 7 /* Start bit */
65 #define GPIO_TP_INT_C3K 11
66 #define GPIO_HSYNC_C3K 22
68 #define POLL_TIMEOUT_RATE0 ((hz * 150)/1000)
69 #define POLL_TIMEOUT_RATE1 (hz / 100) /* XXX every tick */
71 #define CCNT_HS_400_VGA_C3K 6250 /* 15.024us */
73 /* XXX need to ask zaurus_lcd.c for the screen dimension */
74 #define CURRENT_DISPLAY (&sharp_zaurus_C3000)
75 extern const struct lcd_panel_geometry sharp_zaurus_C3000
;
77 /* Settable via sysctl. */
80 static const struct wsmouse_calibcoords ztp_default_calib
= {
81 0, 0, 479, 639, /* minx, miny, maxx, maxy */
84 { 1929, 2021, 240, 320 }, /* rawx, rawy, x, y */
85 { 545, 3464, 48, 64 },
86 { 3308, 3452, 48, 576 },
87 { 2854, 768, 432, 576 },
95 int z
; /* touch pressure */
100 struct callout sc_tp_poll
;
103 int sc_buttons
; /* button emulation ? */
104 struct device
*sc_wsmousedev
;
105 struct ztp_pos sc_oldpos
;
108 struct tpcalib_softc sc_tpcalib
;
111 static int ztp_match(device_t
, cfdata_t
, void *);
112 static void ztp_attach(device_t
, device_t
, void *);
114 CFATTACH_DECL_NEW(ztp
, sizeof(struct ztp_softc
),
115 ztp_match
, ztp_attach
, NULL
, NULL
);
117 static int ztp_enable(void *);
118 static void ztp_disable(void *);
119 static bool ztp_suspend(device_t dv
, pmf_qual_t
);
120 static bool ztp_resume(device_t dv
, pmf_qual_t
);
121 static void ztp_poll(void *);
122 static int ztp_irq(void *);
123 static int ztp_ioctl(void *, u_long
, void *, int, struct lwp
*);
125 static const struct wsmouse_accessops ztp_accessops
= {
132 ztp_match(device_t parent
, cfdata_t cf
, void *aux
)
139 ztp_attach(device_t parent
, device_t self
, void *aux
)
141 struct ztp_softc
*sc
= device_private(self
);
142 struct wsmousedev_attach_args a
;
149 callout_init(&sc
->sc_tp_poll
, 0);
150 callout_setfunc(&sc
->sc_tp_poll
, ztp_poll
, sc
);
152 /* Initialize ADS7846 Difference Reference mode */
153 (void)zssp_ic_send(ZSSP_IC_ADS7846
,
154 (1<<ADSCTRL_ADR_SH
) | (1<<ADSCTRL_STS_SH
));
156 (void)zssp_ic_send(ZSSP_IC_ADS7846
,
157 (3<<ADSCTRL_ADR_SH
) | (1<<ADSCTRL_STS_SH
));
159 (void)zssp_ic_send(ZSSP_IC_ADS7846
,
160 (4<<ADSCTRL_ADR_SH
) | (1<<ADSCTRL_STS_SH
));
162 (void)zssp_ic_send(ZSSP_IC_ADS7846
,
163 (5<<ADSCTRL_ADR_SH
) | (1<<ADSCTRL_STS_SH
));
166 a
.accessops
= &ztp_accessops
;
170 sc
->sc_resx
= CURRENT_DISPLAY
->panel_height
;
171 sc
->sc_resy
= CURRENT_DISPLAY
->panel_width
;
173 sc
->sc_resx
= 480; /* XXX */
174 sc
->sc_resy
= 640; /* XXX */
177 sc
->sc_wsmousedev
= config_found(self
, &a
, wsmousedevprint
);
179 /* Initialize calibration, set default parameters. */
180 tpcalib_init(&sc
->sc_tpcalib
);
181 tpcalib_ioctl(&sc
->sc_tpcalib
, WSMOUSEIO_SCALIBCOORDS
,
182 __UNCONST(&ztp_default_calib
), 0, 0);
188 struct ztp_softc
*sc
= (struct ztp_softc
*)v
;
190 DPRINTF(("%s: ztp_enable()\n", device_xname(sc
->sc_dev
)));
192 if (sc
->sc_enabled
) {
193 DPRINTF(("%s: already enabled\n", device_xname(sc
->sc_dev
)));
197 callout_stop(&sc
->sc_tp_poll
);
199 if (!pmf_device_register(sc
->sc_dev
, ztp_suspend
, ztp_resume
))
200 aprint_error_dev(sc
->sc_dev
,
201 "couldn't establish power handler\n");
203 pxa2x0_gpio_set_function(GPIO_TP_INT_C3K
, GPIO_IN
);
206 if (sc
->sc_gh
== NULL
) {
207 sc
->sc_gh
= pxa2x0_gpio_intr_establish(GPIO_TP_INT_C3K
,
208 IST_EDGE_FALLING
, IPL_TTY
, ztp_irq
, sc
);
210 pxa2x0_gpio_intr_unmask(sc
->sc_gh
);
213 /* enable interrupts */
223 struct ztp_softc
*sc
= (struct ztp_softc
*)v
;
225 DPRINTF(("%s: ztp_disable()\n", device_xname(sc
->sc_dev
)));
227 callout_stop(&sc
->sc_tp_poll
);
229 pmf_device_deregister(sc
->sc_dev
);
232 pxa2x0_gpio_intr_mask(sc
->sc_gh
);
235 /* disable interrupts */
240 ztp_suspend(device_t dv
, pmf_qual_t qual
)
242 struct ztp_softc
*sc
= device_private(dv
);
244 DPRINTF(("%s: ztp_suspend()\n", device_xname(sc
->sc_dev
)));
247 pxa2x0_gpio_intr_mask(sc
->sc_gh
);
249 callout_stop(&sc
->sc_tp_poll
);
251 /* Turn off reference voltage but leave ADC on. */
252 (void)zssp_ic_send(ZSSP_IC_ADS7846
, (1 << ADSCTRL_PD1_SH
) |
253 (1 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
));
255 pxa2x0_gpio_set_function(GPIO_TP_INT_C3K
, GPIO_OUT
| GPIO_SET
);
261 ztp_resume(device_t dv
, pmf_qual_t qual
)
263 struct ztp_softc
*sc
= device_private(dv
);
265 DPRINTF(("%s: ztp_resume()\n", device_xname(sc
->sc_dev
)));
267 pxa2x0_gpio_set_function(GPIO_TP_INT_C3K
, GPIO_IN
);
268 pxa2x0_gpio_intr_mask(sc
->sc_gh
);
270 /* Enable automatic low power mode. */
271 (void)zssp_ic_send(ZSSP_IC_ADS7846
,
272 (4 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
));
274 pxa2x0_gpio_intr_unmask(sc
->sc_gh
);
282 while (pxa2x0_gpio_get_bit(GPIO_HSYNC_C3K) == 0) \
284 while (pxa2x0_gpio_get_bit(GPIO_HSYNC_C3K) != 0) \
286 } while (/*CONSTCOND*/0)
288 static inline uint32_t pxa2x0_ccnt_enable(uint32_t);
289 static inline uint32_t pxa2x0_read_ccnt(void);
290 static uint32_t ztp_sync_ads784x(int, int, uint32_t);
291 static void ztp_sync_send(uint32_t);
292 static int ztp_readpos(struct ztp_pos
*);
294 static inline uint32_t
295 pxa2x0_ccnt_enable(uint32_t reg
)
299 __asm
volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (rv
));
300 __asm
volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (reg
));
305 static inline uint32_t
306 pxa2x0_read_ccnt(void)
310 __asm
volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (rv
));
316 * Communicate synchronously with the ADS784x touch screen controller.
319 ztp_sync_ads784x(int dorecv
/* XXX */, int dosend
/* XXX */, uint32_t cmd
)
324 /* XXX poll hsync only if LCD is enabled */
326 /* start clock counter */
327 ccen
= pxa2x0_ccnt_enable(PMNC_E
);
332 /* read SSDR and disable ADS784x */
333 rv
= zssp_ic_stop(ZSSP_IC_ADS7846
);
340 /* stop clock counter */
341 pxa2x0_ccnt_enable(ccen
);
347 ztp_sync_send(uint32_t cmd
)
349 volatile uint32_t base
, now
;
353 tck
= CCNT_HS_400_VGA_C3K
- 151;
355 /* send dummy command; discard SSDR */
356 (void)zssp_ic_send(ZSSP_IC_ADS7846
, cmd
);
358 /* wait for refresh */
361 /* wait after refresh */
362 base
= pxa2x0_read_ccnt();
363 now
= pxa2x0_read_ccnt();
364 while ((now
- base
) < tck
)
365 now
= pxa2x0_read_ccnt();
367 /* send the actual command; keep ADS784x enabled */
368 zssp_ic_start(ZSSP_IC_ADS7846
, cmd
);
372 ztp_readpos(struct ztp_pos
*pos
)
379 pxa2x0_gpio_set_function(GPIO_HSYNC_C3K
, GPIO_IN
);
381 /* check that pen is down */
382 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
383 (3 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
384 t0
= zssp_ic_send(ZSSP_IC_ADS7846
, cmd
);
385 DPRINTF(("ztp_readpos(): t0 = %d\n", t0
));
392 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
393 (1 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
394 (void)ztp_sync_ads784x(0, 1, cmd
);
397 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
398 (1 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
399 (void)ztp_sync_ads784x(1, 1, cmd
);
402 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
403 (5 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
404 pos
->y
= ztp_sync_ads784x(1, 1, cmd
);
405 DPRINTF(("ztp_readpos(): y = %d\n", pos
->y
));
408 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
409 (3 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
410 pos
->x
= ztp_sync_ads784x(1, 1, cmd
);
411 DPRINTF(("ztp_readpos(): x = %d\n", pos
->x
));
414 cmd
= (1 << ADSCTRL_PD0_SH
) | (1 << ADSCTRL_PD1_SH
) |
415 (4 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
416 t0
= ztp_sync_ads784x(1, 1, cmd
);
417 t1
= ztp_sync_ads784x(1, 0, cmd
);
418 DPRINTF(("ztp_readpos(): t0 = %d, t1 = %d\n", t0
, t1
));
420 /* check that pen is still down */
421 /* XXX pressure sensitivity varies with X or what? */
422 if (t0
== 0 || (pos
->x
* (t1
- t0
) / t0
) >= 15000)
427 /* Enable automatic low power mode. */
428 cmd
= (4 << ADSCTRL_ADR_SH
) | (1 << ADSCTRL_STS_SH
);
429 (void)zssp_ic_send(ZSSP_IC_ADS7846
, cmd
);
447 extern int zkbd_modstate
;
448 struct ztp_softc
*sc
= (struct ztp_softc
*)v
;
449 struct ztp_pos tp
= { 0, 0, 0 };
460 pindown
= pxa2x0_gpio_get_bit(GPIO_TP_INT_C3K
) ? 0 : 1;
461 DPRINTF(("%s: pindown = %d\n", device_xname(sc
->sc_dev
), pindown
));
463 pxa2x0_gpio_intr_mask(sc
->sc_gh
);
464 callout_schedule(&sc
->sc_tp_poll
, POLL_TIMEOUT_RATE1
);
467 down
= ztp_readpos(&tp
);
468 DPRINTF(("%s: x = %d, y = %d, z = %d, down = %d\n",
469 device_xname(sc
->sc_dev
), tp
.x
, tp
.y
, tp
.z
, down
));
472 pxa2x0_gpio_intr_unmask(sc
->sc_gh
);
473 callout_schedule(&sc
->sc_tp_poll
, POLL_TIMEOUT_RATE0
);
475 pxa2x0_gpio_clear_intr(GPIO_TP_INT_C3K
);
481 tpcalib_trans(&sc
->sc_tpcalib
, tp
.x
, tp
.y
, &x
, &y
);
482 DPRINTF(("%s: x = %d, y = %d\n",
483 device_xname(sc
->sc_dev
), x
, y
));
489 if (zkbd_modstate
!= 0 && down
) {
490 if (zkbd_modstate
& (1 << 1)) {
493 } else if (zkbd_modstate
& (1 << 2)) {
499 /* x/y values are not reliable when pen is up */
503 if (down
|| sc
->sc_buttons
!= down
) {
504 wsmouse_input(sc
->sc_wsmousedev
, down
, tp
.x
, tp
.y
, 0, 0,
505 WSMOUSE_INPUT_ABSOLUTE_X
| WSMOUSE_INPUT_ABSOLUTE_Y
);
506 sc
->sc_buttons
= down
;
514 ztp_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
516 struct ztp_softc
*sc
= (struct ztp_softc
*)v
;
517 struct wsmouse_id
*id
;
520 case WSMOUSEIO_GTYPE
:
521 *(u_int
*)data
= WSMOUSE_TYPE_TPANEL
;
524 case WSMOUSEIO_GETID
:
526 * return unique ID string,
527 * "<vendor> <model> <serial number>"
529 id
= (struct wsmouse_id
*)data
;
530 if (id
->type
!= WSMOUSE_ID_TYPE_UIDSTR
)
532 strlcpy(id
->data
, "Sharp SL-C3x00 SN000000", WSMOUSE_ID_MAXLEN
);
533 id
->length
= strlen(id
->data
);
536 case WSMOUSEIO_SCALIBCOORDS
:
537 case WSMOUSEIO_GCALIBCOORDS
:
538 return tpcalib_ioctl(&sc
->sc_tpcalib
, cmd
, data
, flag
, l
);