Home | History | Annotate | Line # | Download | only in dev
psh3tp.c revision 1.11.16.1
      1  1.11.16.1       mjf /*	$NetBSD: psh3tp.c,v 1.11.16.1 2008/04/03 12:42:17 mjf Exp $	*/
      2        1.1  kiyohara /*
      3        1.1  kiyohara  * Copyright (c) 2005 KIYOHARA Takashi
      4        1.1  kiyohara  * All rights reserved.
      5        1.1  kiyohara  *
      6        1.1  kiyohara  * Redistribution and use in source and binary forms, with or without
      7        1.1  kiyohara  * modification, are permitted provided that the following conditions
      8        1.1  kiyohara  * are met:
      9        1.1  kiyohara  * 1. Redistributions of source code must retain the above copyright
     10        1.1  kiyohara  *    notice, this list of conditions and the following disclaimer.
     11        1.1  kiyohara  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1  kiyohara  *    notice, this list of conditions and the following disclaimer in the
     13        1.1  kiyohara  *    documentation and/or other materials provided with the distribution.
     14        1.1  kiyohara  *
     15        1.1  kiyohara  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16        1.1  kiyohara  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17        1.1  kiyohara  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18        1.1  kiyohara  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19        1.1  kiyohara  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20        1.1  kiyohara  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21        1.1  kiyohara  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1  kiyohara  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23        1.1  kiyohara  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24        1.1  kiyohara  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25        1.1  kiyohara  * POSSIBILITY OF SUCH DAMAGE.
     26        1.1  kiyohara  *
     27        1.1  kiyohara  */
     28        1.1  kiyohara 
     29        1.1  kiyohara #include <sys/cdefs.h>
     30        1.1  kiyohara 
     31        1.7  kiyohara #include <sys/types.h>
     32        1.1  kiyohara #include <sys/param.h>
     33        1.7  kiyohara #include <sys/device.h>
     34        1.7  kiyohara #include <sys/errno.h>
     35        1.1  kiyohara #include <sys/kernel.h>
     36        1.1  kiyohara #include <sys/malloc.h>
     37        1.1  kiyohara #include <sys/systm.h>
     38        1.1  kiyohara #include <sys/callout.h>
     39        1.1  kiyohara 
     40        1.1  kiyohara #include "opt_psh3tp.h"
     41        1.1  kiyohara 
     42        1.1  kiyohara #include <dev/wscons/wsconsio.h>
     43        1.1  kiyohara #include <dev/wscons/wsmousevar.h>
     44        1.1  kiyohara #include <dev/hpc/hpctpanelvar.h>
     45        1.1  kiyohara 
     46        1.1  kiyohara #include <machine/platid.h>
     47        1.1  kiyohara #include <machine/platid_mask.h>
     48        1.1  kiyohara 
     49        1.1  kiyohara #include <machine/intr.h>
     50        1.1  kiyohara 
     51        1.1  kiyohara #include <sh3/exception.h>
     52        1.1  kiyohara #include <sh3/intcreg.h>
     53        1.1  kiyohara #include <sh3/pfcreg.h>
     54        1.1  kiyohara #include <sh3/adcreg.h>
     55        1.1  kiyohara 
     56        1.1  kiyohara #include <sh3/dev/adcvar.h>
     57        1.1  kiyohara 
     58        1.1  kiyohara 
     59        1.1  kiyohara #ifdef PSH3TP_DEBUG
     60        1.1  kiyohara volatile int psh3tp_debug = 4;
     61        1.1  kiyohara #define DPRINTF_PRINTF		printf_nolog
     62        1.1  kiyohara #define DPRINTF(arg)		if (psh3tp_debug) DPRINTF_PRINTF arg
     63        1.1  kiyohara #define DPRINTFN(n, arg)	if (psh3tp_debug > (n)) DPRINTF_PRINTF arg
     64        1.1  kiyohara #else
     65        1.1  kiyohara #define DPRINTF(arg)		((void)0)
     66        1.1  kiyohara #define DPRINTFN(n, arg)	((void)0)
     67        1.1  kiyohara #endif
     68        1.1  kiyohara 
     69        1.1  kiyohara 
     70        1.1  kiyohara /*
     71        1.1  kiyohara  * PFC bits pertinent to PERSONA HPW-50PA touch-panel
     72        1.1  kiyohara  */
     73        1.1  kiyohara #define PHDR_TP_PEN_UP		0x40
     74        1.1  kiyohara #define SCPDR_TP_SCAN_ENABLE	0x20
     75        1.1  kiyohara #define SCPDR_TP_SCAN_DISABLE	0x01
     76        1.1  kiyohara #define SCPDR_TP_SCAN_X		0x06
     77        1.1  kiyohara #define SCPDR_TP_SCAN_Y		0x09
     78        1.1  kiyohara 
     79        1.1  kiyohara /*
     80        1.1  kiyohara  * A/D converter channels to get x/y from
     81        1.1  kiyohara  */
     82        1.1  kiyohara #define ADC_CHANNEL_TP_X	1
     83        1.1  kiyohara #define ADC_CHANNEL_TP_Y	0
     84        1.1  kiyohara 
     85        1.1  kiyohara /*
     86        1.1  kiyohara  * Default (read: my device) raw X/Y values for framebuffer edges.
     87        1.1  kiyohara  */
     88        1.1  kiyohara #define PSH3TP_FB_RIGHT		 56
     89        1.1  kiyohara #define PSH3TP_FB_LEFT		969
     90        1.1  kiyohara #define PSH3TP_FB_TOP		848
     91        1.1  kiyohara #define PSH3TP_FB_BOTTOM	121
     92        1.1  kiyohara 
     93        1.1  kiyohara 
     94        1.1  kiyohara struct psh3tp_softc {
     95  1.11.16.1       mjf 	device_t sc_dev;
     96        1.1  kiyohara 
     97        1.1  kiyohara #define PSH3TP_WSMOUSE_ENABLED	0x01
     98        1.1  kiyohara 	int sc_enabled;
     99        1.1  kiyohara 	struct callout sc_touch_ch;
    100  1.11.16.1       mjf 	device_t sc_wsmousedev;
    101        1.1  kiyohara 	struct tpcalib_softc sc_tpcalib; /* calibration info for wsmouse */
    102        1.1  kiyohara };
    103        1.1  kiyohara 
    104        1.1  kiyohara 
    105        1.1  kiyohara /* config machinery */
    106  1.11.16.1       mjf static int psh3tp_match(device_t, struct cfdata *, void *);
    107  1.11.16.1       mjf static void psh3tp_attach(device_t, device_t, void *);
    108        1.1  kiyohara 
    109        1.1  kiyohara /* wsmouse accessops */
    110        1.1  kiyohara static int psh3tp_wsmouse_enable(void *);
    111        1.9  christos static int psh3tp_wsmouse_ioctl(void *, u_long, void *, int, struct lwp *);
    112        1.1  kiyohara static void psh3tp_wsmouse_disable(void *);
    113        1.1  kiyohara 
    114        1.1  kiyohara /* internal driver routines */
    115        1.1  kiyohara static void psh3tp_enable(struct psh3tp_softc *);
    116        1.1  kiyohara static void psh3tp_disable(struct psh3tp_softc *);
    117        1.1  kiyohara static int psh3tp_set_enable(struct psh3tp_softc *, int, int);
    118        1.1  kiyohara static int psh3tp_intr(void *);
    119        1.1  kiyohara static void psh3tp_start_polling(void *);
    120        1.1  kiyohara static void psh3tp_stop_polling(struct psh3tp_softc *);
    121        1.1  kiyohara static void psh3tp_callout_wsmouse(void *);
    122        1.1  kiyohara static void psh3tp_wsmouse_input(struct psh3tp_softc *, int, int);
    123        1.1  kiyohara static void psh3tp_get_raw_xy(int *, int *);
    124        1.1  kiyohara 
    125        1.1  kiyohara 
    126        1.1  kiyohara const struct wsmouse_accessops psh3tp_accessops = {
    127        1.1  kiyohara 	psh3tp_wsmouse_enable,
    128        1.1  kiyohara 	psh3tp_wsmouse_ioctl,
    129        1.1  kiyohara 	psh3tp_wsmouse_disable
    130        1.1  kiyohara };
    131        1.1  kiyohara 
    132        1.1  kiyohara static const struct wsmouse_calibcoords psh3tp_default_calib = {
    133        1.1  kiyohara 	0, 0, 639, 239,
    134        1.1  kiyohara 	4,
    135        1.1  kiyohara 	{{ PSH3TP_FB_LEFT,  PSH3TP_FB_TOP,      0,   0 },
    136        1.1  kiyohara 	 { PSH3TP_FB_RIGHT, PSH3TP_FB_TOP,    639,   0 },
    137        1.1  kiyohara 	 { PSH3TP_FB_LEFT,  PSH3TP_FB_BOTTOM,   0, 239 },
    138        1.1  kiyohara 	 { PSH3TP_FB_RIGHT, PSH3TP_FB_BOTTOM, 639, 239 }}
    139        1.1  kiyohara };
    140        1.1  kiyohara 
    141        1.1  kiyohara 
    142  1.11.16.1       mjf CFATTACH_DECL_NEW(psh3tp, sizeof(struct psh3tp_softc),
    143        1.1  kiyohara     psh3tp_match, psh3tp_attach, NULL, NULL);
    144        1.1  kiyohara 
    145        1.1  kiyohara 
    146        1.7  kiyohara /* ARGSUSED */
    147        1.1  kiyohara static int
    148  1.11.16.1       mjf psh3tp_match(device_t parent __unused, struct cfdata *cf, void *aux __unused)
    149        1.1  kiyohara {
    150        1.1  kiyohara 
    151        1.1  kiyohara 	if (!platid_match(&platid, &platid_mask_MACH_HITACHI_PERSONA))
    152        1.7  kiyohara 		return 0;
    153        1.1  kiyohara 
    154        1.1  kiyohara 	if (strcmp(cf->cf_name, "psh3tp") != 0)
    155        1.7  kiyohara 		return 0;
    156        1.1  kiyohara 
    157        1.7  kiyohara 	return 1;
    158        1.1  kiyohara }
    159        1.1  kiyohara 
    160        1.1  kiyohara 
    161        1.1  kiyohara /*
    162        1.1  kiyohara  * Attach the touch panel driver and its wsmouse child.
    163        1.1  kiyohara  *
    164        1.1  kiyohara  * Note that we have to use submatch to distinguish between child because
    165        1.1  kiyohara  * wsmouse_match matches unconditionally.
    166        1.1  kiyohara  */
    167        1.7  kiyohara /* ARGSUSED */
    168        1.1  kiyohara static void
    169  1.11.16.1       mjf psh3tp_attach(device_t parent __unused, device_t self, void *aux __unused)
    170        1.1  kiyohara {
    171        1.7  kiyohara 	struct psh3tp_softc *sc = device_private(self);
    172        1.1  kiyohara 	struct wsmousedev_attach_args wsma;
    173        1.1  kiyohara 
    174        1.7  kiyohara 	aprint_naive("\n");
    175        1.7  kiyohara 	aprint_normal("\n");
    176        1.1  kiyohara 
    177  1.11.16.1       mjf 	sc->sc_dev = self;
    178        1.1  kiyohara 	sc->sc_enabled = 0;
    179        1.1  kiyohara 
    180        1.1  kiyohara 	/* touch-panel as a pointing device */
    181        1.1  kiyohara 	wsma.accessops = &psh3tp_accessops;
    182        1.1  kiyohara 	wsma.accesscookie = sc;
    183        1.1  kiyohara 
    184        1.3  drochner 	sc->sc_wsmousedev = config_found_ia(
    185        1.3  drochner 	    self, "wsmousedev", &wsma, wsmousedevprint);
    186        1.1  kiyohara 	if (sc->sc_wsmousedev == NULL)
    187        1.1  kiyohara 		return;
    188        1.1  kiyohara 
    189        1.1  kiyohara 	/* init calibration, set default parameters */
    190        1.1  kiyohara 	tpcalib_init(&sc->sc_tpcalib);
    191        1.2       uwe 	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    192        1.9  christos 	    (void *)__UNCONST(&psh3tp_default_calib), 0, 0);
    193        1.1  kiyohara 
    194        1.1  kiyohara 	/* used when in polling mode */
    195       1.10        ad 	callout_init(&sc->sc_touch_ch, 0);
    196        1.1  kiyohara 
    197        1.1  kiyohara 	/* establish interrupt handler, but disable until opened */
    198        1.1  kiyohara 	intc_intr_establish(SH7709_INTEVT2_IRQ2,
    199        1.1  kiyohara 	    IST_EDGE, IPL_TTY, psh3tp_intr, sc);
    200        1.1  kiyohara 	intc_intr_disable(SH7709_INTEVT2_IRQ2);
    201        1.1  kiyohara }
    202        1.1  kiyohara 
    203        1.1  kiyohara 
    204        1.1  kiyohara /*
    205        1.1  kiyohara  * Enable touch panel:  we start in interrupt mode.
    206        1.1  kiyohara  * Must be called at spltty().
    207        1.1  kiyohara  */
    208        1.7  kiyohara /* ARGSUSED */
    209        1.1  kiyohara static void
    210        1.7  kiyohara psh3tp_enable(struct psh3tp_softc *sc __unused)
    211        1.1  kiyohara {
    212        1.1  kiyohara 
    213        1.1  kiyohara 	DPRINTFN(2, ("%s: enable\n", sc->sc_dev.dv_xname));
    214        1.1  kiyohara 	intc_intr_enable(SH7709_INTEVT2_IRQ2);
    215        1.1  kiyohara }
    216        1.1  kiyohara 
    217        1.1  kiyohara 
    218        1.1  kiyohara /*
    219        1.1  kiyohara  * Disable touch panel: disable interrupt, cancel pending callout.
    220        1.1  kiyohara  * Must be called at spltty().
    221        1.1  kiyohara  */
    222        1.1  kiyohara static void
    223        1.1  kiyohara psh3tp_disable(struct psh3tp_softc *sc)
    224        1.1  kiyohara {
    225        1.1  kiyohara 
    226        1.1  kiyohara 	DPRINTFN(2, ("%s: disable\n", sc->sc_dev.dv_xname));
    227        1.1  kiyohara 	intc_intr_disable(SH7709_INTEVT2_IRQ2);
    228        1.1  kiyohara 	callout_stop(&sc->sc_touch_ch);
    229        1.1  kiyohara }
    230        1.1  kiyohara 
    231        1.1  kiyohara 
    232        1.1  kiyohara static int
    233        1.1  kiyohara psh3tp_set_enable(struct psh3tp_softc *sc, int on, int child)
    234        1.1  kiyohara {
    235        1.1  kiyohara 	int s = spltty();
    236        1.1  kiyohara 
    237        1.1  kiyohara 	if (on) {
    238        1.1  kiyohara 		if (!sc->sc_enabled)
    239        1.1  kiyohara 			psh3tp_enable(sc);
    240        1.1  kiyohara 		sc->sc_enabled |= child;
    241        1.1  kiyohara 	} else {
    242        1.1  kiyohara 		sc->sc_enabled &= ~child;
    243        1.1  kiyohara 		if (!sc->sc_enabled)
    244        1.1  kiyohara 			psh3tp_disable(sc);
    245        1.1  kiyohara 	}
    246        1.1  kiyohara 
    247        1.1  kiyohara 	splx(s);
    248        1.7  kiyohara 	return 0;
    249        1.1  kiyohara }
    250        1.1  kiyohara 
    251        1.1  kiyohara 
    252        1.1  kiyohara static int
    253        1.1  kiyohara psh3tp_wsmouse_enable(void *self)
    254        1.1  kiyohara {
    255        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    256        1.1  kiyohara 
    257        1.1  kiyohara 	DPRINTFN(1, ("%s: wsmouse enable\n", sc->sc_dev.dv_xname));
    258        1.7  kiyohara 	return psh3tp_set_enable(sc, 1, PSH3TP_WSMOUSE_ENABLED);
    259        1.1  kiyohara }
    260        1.1  kiyohara 
    261        1.1  kiyohara 
    262        1.1  kiyohara static void
    263        1.1  kiyohara psh3tp_wsmouse_disable(void *self)
    264        1.1  kiyohara {
    265        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    266        1.1  kiyohara 
    267        1.1  kiyohara 	DPRINTFN(1, ("%s: wsmouse disable\n", sc->sc_dev.dv_xname));
    268        1.1  kiyohara 	psh3tp_set_enable(sc, 0, PSH3TP_WSMOUSE_ENABLED);
    269        1.1  kiyohara }
    270        1.1  kiyohara 
    271        1.1  kiyohara 
    272        1.1  kiyohara static int
    273        1.1  kiyohara psh3tp_intr(void *self)
    274        1.1  kiyohara {
    275        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    276        1.1  kiyohara 
    277        1.1  kiyohara 	uint8_t irr0;
    278        1.1  kiyohara 	uint8_t phdr, touched;
    279        1.1  kiyohara 	unsigned int steady, tremor_timeout;
    280        1.1  kiyohara 
    281        1.1  kiyohara 	irr0 = _reg_read_1(SH7709_IRR0);
    282        1.1  kiyohara 	if ((irr0 & IRR0_IRQ2) == 0) {
    283        1.1  kiyohara #ifdef DIAGNOSTIC
    284        1.1  kiyohara 		printf("%s: irr0 %02x?\n", sc->sc_dev.dv_xname, irr0);
    285        1.1  kiyohara #endif
    286        1.7  kiyohara 		return 0;
    287        1.1  kiyohara 	}
    288        1.1  kiyohara 
    289        1.1  kiyohara 	if (!sc->sc_enabled) {
    290        1.1  kiyohara 		DPRINTFN(1, ("%s: intr: !sc_enabled\n", sc->sc_dev.dv_xname));
    291        1.1  kiyohara 		intc_intr_disable(SH7709_INTEVT2_IRQ2);
    292        1.1  kiyohara 		goto served;
    293        1.1  kiyohara 	}
    294        1.1  kiyohara 
    295        1.1  kiyohara 	/*
    296        1.1  kiyohara 	 * Number of times the "touched" bit should be read
    297        1.1  kiyohara 	 * consecutively.
    298        1.1  kiyohara 	 */
    299        1.1  kiyohara #define TREMOR_THRESHOLD 0x300
    300        1.1  kiyohara 	steady = 0;
    301        1.1  kiyohara 	tremor_timeout = TREMOR_THRESHOLD * 16;	/* XXX: arbitrary */
    302        1.8   thorpej 	touched = true;		/* we start with "touched" state */
    303        1.1  kiyohara 
    304        1.1  kiyohara 	do {
    305        1.1  kiyohara 		uint8_t state;
    306        1.1  kiyohara 
    307        1.1  kiyohara 		phdr = _reg_read_1(SH7709_PHDR);
    308        1.1  kiyohara 		state = ((phdr & PHDR_TP_PEN_UP) != PHDR_TP_PEN_UP);
    309        1.1  kiyohara 
    310        1.1  kiyohara 		if (state == touched)
    311        1.1  kiyohara 			++steady;
    312        1.1  kiyohara 		else {
    313        1.1  kiyohara 			steady = 0;
    314        1.1  kiyohara 			touched = state;
    315        1.1  kiyohara 		}
    316        1.1  kiyohara 
    317        1.1  kiyohara 		if (--tremor_timeout == 0) {
    318        1.1  kiyohara 			DPRINTF(("%s: tremor timeout!\n", sc->sc_dev.dv_xname));
    319        1.1  kiyohara 			goto served;
    320        1.1  kiyohara 		}
    321        1.1  kiyohara 	} while (steady < TREMOR_THRESHOLD);
    322        1.1  kiyohara 
    323        1.1  kiyohara 	if (touched) {
    324        1.1  kiyohara 		intc_intr_disable(SH7709_INTEVT2_IRQ2);
    325        1.1  kiyohara 
    326        1.1  kiyohara 		/*
    327        1.1  kiyohara 		 * ADC readings are not stable yet, so schedule
    328        1.1  kiyohara 		 * callout instead of accessing ADC from the interrupt
    329        1.1  kiyohara 		 * handler only to immediately delay().
    330        1.1  kiyohara 		 */
    331        1.1  kiyohara 		callout_reset(&sc->sc_touch_ch,
    332        1.1  kiyohara 		    hz/32, psh3tp_start_polling, sc);
    333        1.1  kiyohara 	} else
    334        1.1  kiyohara 		DPRINTFN(1, ("%s: tremor\n", sc->sc_dev.dv_xname));
    335        1.1  kiyohara served:
    336        1.1  kiyohara 	/* clear the interrupt */
    337        1.1  kiyohara 	_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ2);
    338        1.1  kiyohara 
    339        1.7  kiyohara 	return 1;
    340        1.1  kiyohara }
    341        1.1  kiyohara 
    342        1.1  kiyohara 
    343        1.1  kiyohara /*
    344        1.1  kiyohara  * Called from the interrupt handler at spltty() upon first touch.
    345        1.1  kiyohara  * Decide if we are going to report this touch as a mouse click/drag.
    346        1.1  kiyohara  */
    347        1.1  kiyohara static void
    348        1.1  kiyohara psh3tp_start_polling(void *self)
    349        1.1  kiyohara {
    350        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    351        1.1  kiyohara 	uint8_t phdr;
    352        1.1  kiyohara 	int rawx, rawy;
    353        1.1  kiyohara 
    354        1.1  kiyohara 	phdr = _reg_read_1(SH7709_PHDR);
    355        1.1  kiyohara 	if ((phdr & PHDR_TP_PEN_UP) == PHDR_TP_PEN_UP) {
    356        1.1  kiyohara 		DPRINTFN(2, ("%s: start: pen is not down\n",
    357        1.1  kiyohara 		    sc->sc_dev.dv_xname));
    358        1.1  kiyohara 		psh3tp_stop_polling(sc);
    359        1.1  kiyohara 		return;
    360        1.1  kiyohara 	}
    361        1.1  kiyohara 
    362        1.1  kiyohara 	psh3tp_get_raw_xy(&rawx, &rawy);
    363        1.1  kiyohara 	DPRINTFN(2, ("%s: start: %4d %4d -> ",
    364        1.1  kiyohara 	    sc->sc_dev.dv_xname, rawx, rawy));
    365        1.1  kiyohara 
    366        1.1  kiyohara 	if (sc->sc_enabled & PSH3TP_WSMOUSE_ENABLED) {
    367        1.1  kiyohara 		DPRINTFN(2, ("mouse\n"));
    368        1.1  kiyohara 		psh3tp_wsmouse_input(sc, rawx, rawy);
    369        1.1  kiyohara 		callout_reset(&sc->sc_touch_ch,
    370        1.1  kiyohara 		    hz/32, psh3tp_callout_wsmouse, sc);
    371        1.1  kiyohara 	} else {
    372        1.1  kiyohara 		DPRINTFN(2, ("ignore\n"));
    373        1.1  kiyohara 		psh3tp_stop_polling(sc);
    374        1.1  kiyohara 	}
    375        1.1  kiyohara }
    376        1.1  kiyohara 
    377        1.1  kiyohara 
    378        1.1  kiyohara /*
    379        1.1  kiyohara  * Re-enable touch panel interrupt.
    380        1.1  kiyohara  * Called at spltty() when polling code detects pen-up.
    381        1.1  kiyohara  */
    382        1.7  kiyohara /* ARGSUSED */
    383        1.1  kiyohara static void
    384        1.7  kiyohara psh3tp_stop_polling(struct psh3tp_softc *sc __unused)
    385        1.1  kiyohara {
    386        1.1  kiyohara 	uint8_t irr0;
    387        1.1  kiyohara 
    388        1.1  kiyohara 	DPRINTFN(2, ("%s: stop\n", sc->sc_dev.dv_xname));
    389        1.1  kiyohara 
    390        1.1  kiyohara 	/* clear pending interrupt signal before re-enabling the interrupt */
    391        1.1  kiyohara 	irr0 = _reg_read_1(SH7709_IRR0);
    392        1.1  kiyohara 	if ((irr0 & IRR0_IRQ2) != 0)
    393        1.1  kiyohara 		_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ2);
    394        1.1  kiyohara 
    395        1.1  kiyohara 	intc_intr_enable(SH7709_INTEVT2_IRQ2);
    396        1.1  kiyohara }
    397        1.1  kiyohara 
    398        1.1  kiyohara 
    399        1.1  kiyohara /*
    400        1.1  kiyohara  * We are reporting this touch as a mouse click/drag.
    401        1.1  kiyohara  */
    402        1.1  kiyohara static void
    403        1.1  kiyohara psh3tp_callout_wsmouse(void *self)
    404        1.1  kiyohara {
    405        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    406        1.1  kiyohara 	uint8_t phdr;
    407        1.1  kiyohara 	int rawx, rawy;
    408        1.1  kiyohara 	int s;
    409        1.1  kiyohara 
    410        1.1  kiyohara 	s = spltty();
    411        1.1  kiyohara 
    412        1.1  kiyohara 	if (!sc->sc_enabled) {
    413        1.1  kiyohara 		DPRINTFN(1, ("%s: wsmouse callout: !sc_enabled\n",
    414        1.1  kiyohara 		    sc->sc_dev.dv_xname));
    415        1.1  kiyohara 		splx(s);
    416        1.1  kiyohara 		return;
    417        1.1  kiyohara 	}
    418        1.1  kiyohara 
    419        1.1  kiyohara 	phdr = _reg_read_1(SH7709_PHDR);
    420        1.1  kiyohara 	if ((phdr & PHDR_TP_PEN_UP) != PHDR_TP_PEN_UP) {
    421        1.1  kiyohara 		psh3tp_get_raw_xy(&rawx, &rawy);
    422        1.1  kiyohara 		psh3tp_wsmouse_input(sc, rawx, rawy); /* mouse dragged */
    423        1.1  kiyohara 		callout_schedule(&sc->sc_touch_ch, hz/32);
    424        1.1  kiyohara 	} else {
    425        1.1  kiyohara 		wsmouse_input( /* button up */
    426        1.6    plunky 		    sc->sc_wsmousedev, 0, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
    427        1.1  kiyohara 		psh3tp_stop_polling(sc);
    428        1.1  kiyohara 	}
    429        1.1  kiyohara 	splx(s);
    430        1.1  kiyohara }
    431        1.1  kiyohara 
    432        1.1  kiyohara 
    433        1.1  kiyohara /*
    434        1.1  kiyohara  * Report mouse click/drag.
    435        1.1  kiyohara  */
    436        1.1  kiyohara static void
    437        1.1  kiyohara psh3tp_wsmouse_input(struct psh3tp_softc *sc, int rawx, int rawy)
    438        1.1  kiyohara {
    439        1.1  kiyohara 	int x, y;
    440        1.1  kiyohara 
    441        1.1  kiyohara 	tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y);
    442        1.1  kiyohara 
    443        1.1  kiyohara 	DPRINTFN(3, ("%s: %4d %4d -> %3d %3d\n",
    444        1.1  kiyohara 	     sc->sc_dev.dv_xname, rawx, rawy, x, y));
    445        1.1  kiyohara 
    446        1.1  kiyohara 	wsmouse_input(sc->sc_wsmousedev,
    447        1.1  kiyohara 	    1,	/* button */
    448        1.6    plunky 	    x, y, 0, 0,
    449        1.1  kiyohara 	    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
    450        1.1  kiyohara }
    451        1.1  kiyohara 
    452        1.1  kiyohara 
    453        1.1  kiyohara /*
    454        1.1  kiyohara  * Read raw X/Y coordinates from the ADC.
    455        1.1  kiyohara  */
    456        1.1  kiyohara static void
    457        1.1  kiyohara psh3tp_get_raw_xy(int *rawxp, int *rawyp)
    458        1.1  kiyohara {
    459        1.1  kiyohara 	uint8_t scpdr;
    460        1.1  kiyohara 
    461        1.1  kiyohara 	/* X axis */
    462        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    463        1.1  kiyohara 	scpdr &= ~SCPDR_TP_SCAN_DISABLE;
    464        1.1  kiyohara 	scpdr |= (SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_X);
    465        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    466        1.1  kiyohara 	delay(40);
    467        1.1  kiyohara 
    468        1.1  kiyohara 	*rawxp = adc_sample_channel(ADC_CHANNEL_TP_X);
    469        1.1  kiyohara 
    470        1.1  kiyohara 	/* Y axis */
    471        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    472        1.1  kiyohara 	scpdr &=  ~SCPDR_TP_SCAN_X;
    473        1.1  kiyohara 	scpdr |= (SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_Y);
    474        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    475        1.1  kiyohara 	delay(40);
    476        1.1  kiyohara 
    477        1.1  kiyohara 	*rawyp = adc_sample_channel(ADC_CHANNEL_TP_Y);
    478        1.1  kiyohara 
    479        1.1  kiyohara 	/* restore SCPDR */
    480        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    481        1.1  kiyohara 	scpdr &= ~(SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_Y);
    482        1.1  kiyohara 	scpdr |= SCPDR_TP_SCAN_DISABLE;
    483        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    484        1.1  kiyohara }
    485        1.1  kiyohara 
    486        1.1  kiyohara 
    487        1.1  kiyohara static int
    488        1.9  christos psh3tp_wsmouse_ioctl(void *self, u_long cmd, void *data, int flag,
    489        1.7  kiyohara 		     struct lwp *l)
    490        1.1  kiyohara {
    491        1.1  kiyohara 	struct psh3tp_softc *sc = (struct psh3tp_softc *)self;
    492        1.1  kiyohara 
    493        1.7  kiyohara 	return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
    494        1.1  kiyohara }
    495