Home | History | Annotate | Line # | Download | only in dev
psh3tp.c revision 1.15.74.1
      1  1.15.74.1   thorpej /*	$NetBSD: psh3tp.c,v 1.15.74.1 2021/03/23 07:14:48 thorpej 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.12  kiyohara 	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.12  kiyohara 	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.12  kiyohara static int psh3tp_match(device_t, struct cfdata *, void *);
    107       1.12  kiyohara 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.12  kiyohara 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.12  kiyohara 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.12  kiyohara 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.12  kiyohara 	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.15.74.1   thorpej 	sc->sc_wsmousedev = config_found(
    185  1.15.74.1   thorpej 	    self, &wsma, wsmousedevprint, CFARG_EOL);
    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.13  kiyohara 
    202       1.13  kiyohara  	if (!pmf_device_register(self, NULL, NULL))
    203       1.13  kiyohara  		aprint_error_dev(self, "unable to establish power handler\n");
    204        1.1  kiyohara }
    205        1.1  kiyohara 
    206        1.1  kiyohara 
    207        1.1  kiyohara /*
    208        1.1  kiyohara  * Enable touch panel:  we start in interrupt mode.
    209        1.1  kiyohara  * Must be called at spltty().
    210        1.1  kiyohara  */
    211        1.7  kiyohara /* ARGSUSED */
    212        1.1  kiyohara static void
    213        1.7  kiyohara psh3tp_enable(struct psh3tp_softc *sc __unused)
    214        1.1  kiyohara {
    215        1.1  kiyohara 
    216       1.15       chs 	DPRINTFN(2, ("%s: enable\n", device_xname(sc->sc_dev)));
    217        1.1  kiyohara 	intc_intr_enable(SH7709_INTEVT2_IRQ2);
    218        1.1  kiyohara }
    219        1.1  kiyohara 
    220        1.1  kiyohara 
    221        1.1  kiyohara /*
    222        1.1  kiyohara  * Disable touch panel: disable interrupt, cancel pending callout.
    223        1.1  kiyohara  * Must be called at spltty().
    224        1.1  kiyohara  */
    225        1.1  kiyohara static void
    226        1.1  kiyohara psh3tp_disable(struct psh3tp_softc *sc)
    227        1.1  kiyohara {
    228        1.1  kiyohara 
    229       1.15       chs 	DPRINTFN(2, ("%s: disable\n", device_xname(sc->sc_dev)));
    230        1.1  kiyohara 	intc_intr_disable(SH7709_INTEVT2_IRQ2);
    231        1.1  kiyohara 	callout_stop(&sc->sc_touch_ch);
    232        1.1  kiyohara }
    233        1.1  kiyohara 
    234        1.1  kiyohara 
    235        1.1  kiyohara static int
    236        1.1  kiyohara psh3tp_set_enable(struct psh3tp_softc *sc, int on, int child)
    237        1.1  kiyohara {
    238        1.1  kiyohara 	int s = spltty();
    239        1.1  kiyohara 
    240        1.1  kiyohara 	if (on) {
    241        1.1  kiyohara 		if (!sc->sc_enabled)
    242        1.1  kiyohara 			psh3tp_enable(sc);
    243        1.1  kiyohara 		sc->sc_enabled |= child;
    244        1.1  kiyohara 	} else {
    245        1.1  kiyohara 		sc->sc_enabled &= ~child;
    246        1.1  kiyohara 		if (!sc->sc_enabled)
    247        1.1  kiyohara 			psh3tp_disable(sc);
    248        1.1  kiyohara 	}
    249        1.1  kiyohara 
    250        1.1  kiyohara 	splx(s);
    251        1.7  kiyohara 	return 0;
    252        1.1  kiyohara }
    253        1.1  kiyohara 
    254        1.1  kiyohara 
    255        1.1  kiyohara static int
    256       1.14   tsutsui psh3tp_wsmouse_enable(void *cookie)
    257        1.1  kiyohara {
    258       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)cookie;
    259        1.1  kiyohara 
    260       1.15       chs 	DPRINTFN(1, ("%s: wsmouse enable\n", device_xname(sc->sc_dev)));
    261        1.7  kiyohara 	return psh3tp_set_enable(sc, 1, PSH3TP_WSMOUSE_ENABLED);
    262        1.1  kiyohara }
    263        1.1  kiyohara 
    264        1.1  kiyohara 
    265        1.1  kiyohara static void
    266       1.14   tsutsui psh3tp_wsmouse_disable(void *cookie)
    267        1.1  kiyohara {
    268       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)cookie;
    269        1.1  kiyohara 
    270       1.15       chs 	DPRINTFN(1, ("%s: wsmouse disable\n", device_xname(sc->sc_dev)));
    271        1.1  kiyohara 	psh3tp_set_enable(sc, 0, PSH3TP_WSMOUSE_ENABLED);
    272        1.1  kiyohara }
    273        1.1  kiyohara 
    274        1.1  kiyohara 
    275        1.1  kiyohara static int
    276       1.14   tsutsui psh3tp_intr(void *arg)
    277        1.1  kiyohara {
    278       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)arg;
    279        1.1  kiyohara 
    280        1.1  kiyohara 	uint8_t irr0;
    281        1.1  kiyohara 	uint8_t phdr, touched;
    282        1.1  kiyohara 	unsigned int steady, tremor_timeout;
    283        1.1  kiyohara 
    284        1.1  kiyohara 	irr0 = _reg_read_1(SH7709_IRR0);
    285        1.1  kiyohara 	if ((irr0 & IRR0_IRQ2) == 0) {
    286        1.1  kiyohara #ifdef DIAGNOSTIC
    287       1.15       chs 		printf("%s: irr0 %02x?\n", device_xname(sc->sc_dev), irr0);
    288        1.1  kiyohara #endif
    289        1.7  kiyohara 		return 0;
    290        1.1  kiyohara 	}
    291        1.1  kiyohara 
    292        1.1  kiyohara 	if (!sc->sc_enabled) {
    293       1.15       chs 		DPRINTFN(1, ("%s: intr: !sc_enabled\n", device_xname(sc->sc_dev)));
    294        1.1  kiyohara 		intc_intr_disable(SH7709_INTEVT2_IRQ2);
    295        1.1  kiyohara 		goto served;
    296        1.1  kiyohara 	}
    297        1.1  kiyohara 
    298        1.1  kiyohara 	/*
    299        1.1  kiyohara 	 * Number of times the "touched" bit should be read
    300        1.1  kiyohara 	 * consecutively.
    301        1.1  kiyohara 	 */
    302        1.1  kiyohara #define TREMOR_THRESHOLD 0x300
    303        1.1  kiyohara 	steady = 0;
    304        1.1  kiyohara 	tremor_timeout = TREMOR_THRESHOLD * 16;	/* XXX: arbitrary */
    305        1.8   thorpej 	touched = true;		/* we start with "touched" state */
    306        1.1  kiyohara 
    307        1.1  kiyohara 	do {
    308        1.1  kiyohara 		uint8_t state;
    309        1.1  kiyohara 
    310        1.1  kiyohara 		phdr = _reg_read_1(SH7709_PHDR);
    311        1.1  kiyohara 		state = ((phdr & PHDR_TP_PEN_UP) != PHDR_TP_PEN_UP);
    312        1.1  kiyohara 
    313        1.1  kiyohara 		if (state == touched)
    314        1.1  kiyohara 			++steady;
    315        1.1  kiyohara 		else {
    316        1.1  kiyohara 			steady = 0;
    317        1.1  kiyohara 			touched = state;
    318        1.1  kiyohara 		}
    319        1.1  kiyohara 
    320        1.1  kiyohara 		if (--tremor_timeout == 0) {
    321       1.15       chs 			DPRINTF(("%s: tremor timeout!\n",
    322       1.15       chs 			    device_xname(sc->sc_dev)));
    323        1.1  kiyohara 			goto served;
    324        1.1  kiyohara 		}
    325        1.1  kiyohara 	} while (steady < TREMOR_THRESHOLD);
    326        1.1  kiyohara 
    327        1.1  kiyohara 	if (touched) {
    328        1.1  kiyohara 		intc_intr_disable(SH7709_INTEVT2_IRQ2);
    329        1.1  kiyohara 
    330        1.1  kiyohara 		/*
    331        1.1  kiyohara 		 * ADC readings are not stable yet, so schedule
    332        1.1  kiyohara 		 * callout instead of accessing ADC from the interrupt
    333        1.1  kiyohara 		 * handler only to immediately delay().
    334        1.1  kiyohara 		 */
    335        1.1  kiyohara 		callout_reset(&sc->sc_touch_ch,
    336        1.1  kiyohara 		    hz/32, psh3tp_start_polling, sc);
    337        1.1  kiyohara 	} else
    338       1.15       chs 		DPRINTFN(1, ("%s: tremor\n", device_xname(sc->sc_dev)));
    339        1.1  kiyohara served:
    340        1.1  kiyohara 	/* clear the interrupt */
    341        1.1  kiyohara 	_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ2);
    342        1.1  kiyohara 
    343        1.7  kiyohara 	return 1;
    344        1.1  kiyohara }
    345        1.1  kiyohara 
    346        1.1  kiyohara 
    347        1.1  kiyohara /*
    348        1.1  kiyohara  * Called from the interrupt handler at spltty() upon first touch.
    349        1.1  kiyohara  * Decide if we are going to report this touch as a mouse click/drag.
    350        1.1  kiyohara  */
    351        1.1  kiyohara static void
    352       1.14   tsutsui psh3tp_start_polling(void *arg)
    353        1.1  kiyohara {
    354       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)arg;
    355        1.1  kiyohara 	uint8_t phdr;
    356        1.1  kiyohara 	int rawx, rawy;
    357        1.1  kiyohara 
    358        1.1  kiyohara 	phdr = _reg_read_1(SH7709_PHDR);
    359        1.1  kiyohara 	if ((phdr & PHDR_TP_PEN_UP) == PHDR_TP_PEN_UP) {
    360        1.1  kiyohara 		DPRINTFN(2, ("%s: start: pen is not down\n",
    361       1.15       chs 		    device_xname(sc->sc_dev)));
    362        1.1  kiyohara 		psh3tp_stop_polling(sc);
    363        1.1  kiyohara 		return;
    364        1.1  kiyohara 	}
    365        1.1  kiyohara 
    366        1.1  kiyohara 	psh3tp_get_raw_xy(&rawx, &rawy);
    367        1.1  kiyohara 	DPRINTFN(2, ("%s: start: %4d %4d -> ",
    368       1.15       chs 	    device_xname(sc->sc_dev), rawx, rawy));
    369        1.1  kiyohara 
    370        1.1  kiyohara 	if (sc->sc_enabled & PSH3TP_WSMOUSE_ENABLED) {
    371        1.1  kiyohara 		DPRINTFN(2, ("mouse\n"));
    372        1.1  kiyohara 		psh3tp_wsmouse_input(sc, rawx, rawy);
    373        1.1  kiyohara 		callout_reset(&sc->sc_touch_ch,
    374        1.1  kiyohara 		    hz/32, psh3tp_callout_wsmouse, sc);
    375        1.1  kiyohara 	} else {
    376        1.1  kiyohara 		DPRINTFN(2, ("ignore\n"));
    377        1.1  kiyohara 		psh3tp_stop_polling(sc);
    378        1.1  kiyohara 	}
    379        1.1  kiyohara }
    380        1.1  kiyohara 
    381        1.1  kiyohara 
    382        1.1  kiyohara /*
    383        1.1  kiyohara  * Re-enable touch panel interrupt.
    384        1.1  kiyohara  * Called at spltty() when polling code detects pen-up.
    385        1.1  kiyohara  */
    386        1.7  kiyohara /* ARGSUSED */
    387        1.1  kiyohara static void
    388        1.7  kiyohara psh3tp_stop_polling(struct psh3tp_softc *sc __unused)
    389        1.1  kiyohara {
    390        1.1  kiyohara 	uint8_t irr0;
    391        1.1  kiyohara 
    392       1.15       chs 	DPRINTFN(2, ("%s: stop\n", device_xname(sc->sc_dev)));
    393        1.1  kiyohara 
    394        1.1  kiyohara 	/* clear pending interrupt signal before re-enabling the interrupt */
    395        1.1  kiyohara 	irr0 = _reg_read_1(SH7709_IRR0);
    396        1.1  kiyohara 	if ((irr0 & IRR0_IRQ2) != 0)
    397        1.1  kiyohara 		_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ2);
    398        1.1  kiyohara 
    399        1.1  kiyohara 	intc_intr_enable(SH7709_INTEVT2_IRQ2);
    400        1.1  kiyohara }
    401        1.1  kiyohara 
    402        1.1  kiyohara 
    403        1.1  kiyohara /*
    404        1.1  kiyohara  * We are reporting this touch as a mouse click/drag.
    405        1.1  kiyohara  */
    406        1.1  kiyohara static void
    407       1.14   tsutsui psh3tp_callout_wsmouse(void *arg)
    408        1.1  kiyohara {
    409       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)arg;
    410        1.1  kiyohara 	uint8_t phdr;
    411        1.1  kiyohara 	int rawx, rawy;
    412        1.1  kiyohara 	int s;
    413        1.1  kiyohara 
    414        1.1  kiyohara 	s = spltty();
    415        1.1  kiyohara 
    416        1.1  kiyohara 	if (!sc->sc_enabled) {
    417        1.1  kiyohara 		DPRINTFN(1, ("%s: wsmouse callout: !sc_enabled\n",
    418       1.15       chs 		    device_xname(sc->sc_dev)));
    419        1.1  kiyohara 		splx(s);
    420        1.1  kiyohara 		return;
    421        1.1  kiyohara 	}
    422        1.1  kiyohara 
    423        1.1  kiyohara 	phdr = _reg_read_1(SH7709_PHDR);
    424        1.1  kiyohara 	if ((phdr & PHDR_TP_PEN_UP) != PHDR_TP_PEN_UP) {
    425        1.1  kiyohara 		psh3tp_get_raw_xy(&rawx, &rawy);
    426        1.1  kiyohara 		psh3tp_wsmouse_input(sc, rawx, rawy); /* mouse dragged */
    427        1.1  kiyohara 		callout_schedule(&sc->sc_touch_ch, hz/32);
    428        1.1  kiyohara 	} else {
    429        1.1  kiyohara 		wsmouse_input( /* button up */
    430        1.6    plunky 		    sc->sc_wsmousedev, 0, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
    431        1.1  kiyohara 		psh3tp_stop_polling(sc);
    432        1.1  kiyohara 	}
    433        1.1  kiyohara 	splx(s);
    434        1.1  kiyohara }
    435        1.1  kiyohara 
    436        1.1  kiyohara 
    437        1.1  kiyohara /*
    438        1.1  kiyohara  * Report mouse click/drag.
    439        1.1  kiyohara  */
    440        1.1  kiyohara static void
    441        1.1  kiyohara psh3tp_wsmouse_input(struct psh3tp_softc *sc, int rawx, int rawy)
    442        1.1  kiyohara {
    443        1.1  kiyohara 	int x, y;
    444        1.1  kiyohara 
    445        1.1  kiyohara 	tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y);
    446        1.1  kiyohara 
    447        1.1  kiyohara 	DPRINTFN(3, ("%s: %4d %4d -> %3d %3d\n",
    448       1.15       chs 	     device_xname(sc->sc_dev), rawx, rawy, x, y));
    449        1.1  kiyohara 
    450        1.1  kiyohara 	wsmouse_input(sc->sc_wsmousedev,
    451        1.1  kiyohara 	    1,	/* button */
    452        1.6    plunky 	    x, y, 0, 0,
    453        1.1  kiyohara 	    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
    454        1.1  kiyohara }
    455        1.1  kiyohara 
    456        1.1  kiyohara 
    457        1.1  kiyohara /*
    458        1.1  kiyohara  * Read raw X/Y coordinates from the ADC.
    459        1.1  kiyohara  */
    460        1.1  kiyohara static void
    461        1.1  kiyohara psh3tp_get_raw_xy(int *rawxp, int *rawyp)
    462        1.1  kiyohara {
    463        1.1  kiyohara 	uint8_t scpdr;
    464        1.1  kiyohara 
    465        1.1  kiyohara 	/* X axis */
    466        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    467        1.1  kiyohara 	scpdr &= ~SCPDR_TP_SCAN_DISABLE;
    468        1.1  kiyohara 	scpdr |= (SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_X);
    469        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    470        1.1  kiyohara 	delay(40);
    471        1.1  kiyohara 
    472        1.1  kiyohara 	*rawxp = adc_sample_channel(ADC_CHANNEL_TP_X);
    473        1.1  kiyohara 
    474        1.1  kiyohara 	/* Y axis */
    475        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    476        1.1  kiyohara 	scpdr &=  ~SCPDR_TP_SCAN_X;
    477        1.1  kiyohara 	scpdr |= (SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_Y);
    478        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    479        1.1  kiyohara 	delay(40);
    480        1.1  kiyohara 
    481        1.1  kiyohara 	*rawyp = adc_sample_channel(ADC_CHANNEL_TP_Y);
    482        1.1  kiyohara 
    483        1.1  kiyohara 	/* restore SCPDR */
    484        1.1  kiyohara 	scpdr = _reg_read_1(SH7709_SCPDR);
    485        1.1  kiyohara 	scpdr &= ~(SCPDR_TP_SCAN_ENABLE | SCPDR_TP_SCAN_Y);
    486        1.1  kiyohara 	scpdr |= SCPDR_TP_SCAN_DISABLE;
    487        1.1  kiyohara 	_reg_write_1(SH7709_SCPDR, scpdr);
    488        1.1  kiyohara }
    489        1.1  kiyohara 
    490        1.1  kiyohara 
    491        1.1  kiyohara static int
    492       1.14   tsutsui psh3tp_wsmouse_ioctl(void *cookie, u_long cmd, void *data, int flag,
    493        1.7  kiyohara 		     struct lwp *l)
    494        1.1  kiyohara {
    495       1.14   tsutsui 	struct psh3tp_softc *sc = (struct psh3tp_softc *)cookie;
    496        1.1  kiyohara 
    497        1.7  kiyohara 	return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
    498        1.1  kiyohara }
    499