vrpiu.c revision 1.12
1/*	$NetBSD: vrpiu.c,v 1.12 2001/06/10 12:37:43 sato Exp $	*/
2
3/*
4 * Copyright (c) 1999 Shin Takemura All rights reserved.
5 * Copyright (c) 2000 SATO Kazumi, All rights reserved.
6 * Copyright (c) 1999,2000 PocketBSD Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31/*
32 * A/D polling part written by SATO Kazumi.
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/device.h>
38#include <sys/kernel.h>
39#include <sys/callout.h>
40#include <sys/boot_flag.h>
41
42#include <dev/wscons/wsconsio.h>
43#include <dev/wscons/wsmousevar.h>
44
45#include <machine/bus.h>
46#include <machine/platid.h>
47#include <machine/platid_mask.h>
48#include <machine/config_hook.h>
49
50#include <dev/hpc/tpcalibvar.h>
51
52#include <hpcmips/hpcmips/machdep.h>
53#include <hpcmips/vr/vripvar.h>
54#include <hpcmips/vr/cmureg.h>
55#include <hpcmips/vr/vrpiuvar.h>
56#include <hpcmips/vr/vrpiureg.h>
57
58/*
59 * contant and macro definitions
60 */
61#define VRPIUDEBUG
62#ifdef VRPIUDEBUG
63int	vrpiu_debug = 0;
64#define	DPRINTF(arg) if (vrpiu_debug) printf arg;
65#define	VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
66#else
67#define	DPRINTF(arg)
68#define	VPRINTF(arg) if (bootverbose) printf arg;
69#endif
70
71#ifndef VRPIU_AD_POLL_INTERVAL
72#define VRPIU_AD_POLL_INTERVAL	60	/* interval is 60 sec */
73#endif /* VRPIU_AD_POLL_INTERTVAL */
74
75#define	PIUSIVL_SCANINTVAL_MIN	333			/* 10msec	*/
76#define	PIUSIVL_SCANINTVAL_MAX	PIUSIVL_SCANINTVAL_MASK	/* 60msec	*/
77#define VRPIU_TP_SCAN_TIMEOUT	(hz/10)		/* timeout is 100msec	*/
78
79#define TP_INTR	(PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
80#define AD_INTR	(PIUINT_PADADPINTR)
81
82/*
83 * data types
84 */
85/* struct vrpiu_softc is defined in vrpiuvar.h */
86
87/*
88 * function prototypes
89 */
90static int	vrpiumatch __P((struct device *, struct cfdata *, void *));
91static void	vrpiuattach __P((struct device *, struct device *, void *));
92
93static void	vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
94static u_short	vrpiu_read __P((struct vrpiu_softc *, int));
95
96static int	vrpiu_intr __P((void *));
97static void	vrpiu_tp_intr __P((struct vrpiu_softc *));
98static void	vrpiu_ad_intr __P((struct vrpiu_softc *));
99#ifdef DEBUG
100static void	vrpiu_dump_cntreg __P((unsigned int cmd));
101#endif
102
103static int	vrpiu_tp_enable __P((void *));
104static int	vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
105static void	vrpiu_tp_disable __P((void *));
106static void	vrpiu_tp_up __P((struct vrpiu_softc *));
107static void	vrpiu_tp_timeout __P((void *));
108int		vrpiu_ad_enable __P((void *));
109void		vrpiu_ad_disable __P((void *));
110static void	vrpiu_start_powerstate __P((void *));
111static void	vrpiu_calc_powerstate __P((struct vrpiu_softc *));
112static void	vrpiu_power __P((int, void *));
113static u_int	scan_interval __P((u_int data));
114
115/* mra is defined in mra.c */
116int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
117			 int n, int scale, int *a, int *b, int *c));
118
119/*
120 * static or global variables
121 */
122struct cfattach vrpiu_ca = {
123	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
124};
125
126const struct wsmouse_accessops vrpiu_accessops = {
127	vrpiu_tp_enable,
128	vrpiu_tp_ioctl,
129	vrpiu_tp_disable,
130};
131
132int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
133
134/*
135 * function definitions
136 */
137static inline void
138vrpiu_write(sc, port, val)
139	struct vrpiu_softc *sc;
140	int port;
141	unsigned short val;
142{
143	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
144}
145
146static inline u_short
147vrpiu_read(sc, port)
148	struct vrpiu_softc *sc;
149	int port;
150{
151	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
152}
153
154static int
155vrpiumatch(parent, cf, aux)
156	struct device *parent;
157	struct cfdata *cf;
158	void *aux;
159{
160	return 1;
161}
162
163static void
164vrpiuattach(parent, self, aux)
165	struct device *parent;
166	struct device *self;
167	void *aux;
168{
169	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
170	struct vrip_attach_args *va = aux;
171	struct wsmousedev_attach_args wsmaa;
172
173	bus_space_tag_t iot = va->va_iot;
174	bus_space_handle_t ioh;
175
176	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
177	    printf(": can't map bus space\n");
178	    return;
179	}
180
181	sc->sc_iot = iot;
182	sc->sc_ioh = ioh;
183	sc->sc_vrip = va->va_vc;
184
185	sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
186
187	/*
188	 * disable device until vrpiu_enable called
189	 */
190	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
191
192	/* initialize touch panel timeout structure	*/
193	callout_init(&sc->sc_tptimeout);
194
195	/* initialize calibration context	*/
196	tpcalib_init(&sc->sc_tpcalib);
197#if 1
198	/*
199	 * XXX, calibrate parameters
200	 */
201	{
202	    int i;
203	    static const struct {
204		platid_mask_t *mask;
205		struct wsmouse_calibcoords coords;
206	    } calibrations[] = {
207		{ &platid_mask_MACH_NEC_MCR_700,
208		  { 0, 0, 799, 599,
209		    4,
210		    { { 115,  80,   0,   0 },
211		      { 115, 966,   0, 599 },
212		      { 912,  80, 799,   0 },
213		      { 912, 966, 799, 599 } } } },
214
215		{ &platid_mask_MACH_NEC_MCR_700A,
216		  { 0, 0, 799, 599,
217		    4,
218		    { { 115,  80,   0,   0 },
219		      { 115, 966,   0, 599 },
220		      { 912,  80, 799,   0 },
221		      { 912, 966, 799, 599 } } } },
222
223		{ &platid_mask_MACH_NEC_MCR_730,
224		  { 0, 0, 799, 599,
225		    4,
226		    { { 115,  80,   0,   0 },
227		      { 115, 966,   0, 599 },
228		      { 912,  80, 799,   0 },
229		      { 912, 966, 799, 599 } } } },
230
231		{ NULL,		/* samples got on my MC-R500 */
232		  { 0, 0, 639, 239,
233		    5,
234		    { { 502, 486, 320, 120 },
235		      {  55, 109,   0,   0 },
236		      {  54, 913,   0, 239 },
237		      { 973, 924, 639, 239 },
238		      { 975, 123, 639,   0 } } } },
239	    };
240	    for (i = 0; ; i++) {
241		if (calibrations[i].mask == NULL
242		    || platid_match(&platid, calibrations[i].mask))
243		    break;
244	    }
245	    tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
246			  (caddr_t)&calibrations[i].coords, 0, 0);
247	}
248#endif
249
250	/* install interrupt handler and enable interrupt */
251	if (!(sc->sc_handler =
252	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
253				vrpiu_intr, sc))) {
254	    printf (": can't map interrupt line.\n");
255	    return;
256	}
257
258	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
259	vrpiu_tp_disable(sc);
260
261	printf("\n");
262
263	wsmaa.accessops = &vrpiu_accessops;
264	wsmaa.accesscookie = sc;
265
266	/*
267	 * attach the wsmouse
268	 */
269	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
270
271	/*
272	 * power management events
273	 */
274	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
275
276	/*
277	 * init A/D port polling.
278	 */
279	sc->sc_battery.n_values = 3;
280	sc->sc_battery.value[0] = -1;
281	sc->sc_battery.value[1] = -1;
282	sc->sc_battery.value[2] = -1;
283	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
284	callout_init(&sc->sc_adpoll);
285	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
286}
287
288/*
289 * calculate interval value
290 *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
291 * output: value for PIUSIVL_REG
292 */
293static u_int
294scan_interval(u_int data)
295{
296	int scale;
297
298	if (data < WSMOUSE_RES_MIN)
299	    data = WSMOUSE_RES_MIN;
300
301	if (WSMOUSE_RES_MAX < data)
302	    data = WSMOUSE_RES_MAX;
303
304	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
305	data += WSMOUSE_RES_MIN;
306
307	return PIUSIVL_SCANINTVAL_MIN +
308	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
309	    (scale - data) / scale;
310}
311
312int
313vrpiu_ad_enable(v)
314	void *v;
315{
316	struct vrpiu_softc *sc = v;
317	int s;
318	unsigned int cnt;
319
320	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
321		 __FILE__, __LINE__, sc->sc_interval));
322	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
323	    return EBUSY;
324
325	/* supply clock to PIU */
326	__vrcmu_supply(CMUMSKPIU, 1);
327
328	/* set scan interval */
329	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
330
331	s = spltty();
332
333	/* clear interrupt status */
334	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
335
336	/* Disable -> Standby */
337	cnt = PIUCNT_PIUPWR |
338		PIUCNT_PIUMODE_COORDINATE |
339		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
340	vrpiu_write(sc, PIUCNT_REG_W, cnt);
341
342	/* Level2 interrupt register setting */
343	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
344
345	/* save pen status, touch or release */
346	cnt = vrpiu_read(sc, PIUCNT_REG_W);
347
348	/*
349	 * Enable scan sequencer operation
350	 * Standby -> WaitPenTouch
351	 */
352	cnt |= PIUCNT_PIUSEQEN;
353	vrpiu_write(sc, PIUCNT_REG_W, cnt);
354
355	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
356
357	splx(s);
358
359	return 0;
360}
361
362void
363vrpiu_ad_disable(v)
364	void *v;
365{
366	struct vrpiu_softc *sc = v;
367
368	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
369
370	/* Set level2 interrupt register to mask interrupts */
371	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
372
373	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
374
375	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
376	    /* Disable scan sequencer operation and power off */
377	    vrpiu_write(sc, PIUCNT_REG_W, 0);
378
379	    /* mask clock to PIU */
380	    __vrcmu_supply(CMUMSKPIU, 1);
381	}
382}
383
384int
385vrpiu_tp_enable(v)
386	void *v;
387{
388	struct vrpiu_softc *sc = v;
389	int s;
390	unsigned int cnt;
391
392	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
393		 __FILE__, __LINE__, sc->sc_interval));
394	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
395	    return EBUSY;
396
397	/* supply clock to PIU */
398	__vrcmu_supply(CMUMSKPIU, 1);
399
400	/* set scan interval */
401	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
402
403	s = spltty();
404
405	/* clear interrupt status */
406	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
407
408	/* Disable -> Standby */
409	cnt = PIUCNT_PIUPWR |
410		PIUCNT_PIUMODE_COORDINATE |
411		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
412	vrpiu_write(sc, PIUCNT_REG_W, cnt);
413
414	/* Level2 interrupt register setting */
415	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
416
417	/* save pen status, touch or release */
418	cnt = vrpiu_read(sc, PIUCNT_REG_W);
419
420	/*
421	 * Enable scan sequencer operation
422	 * Standby -> WaitPenTouch
423	 */
424	cnt |= PIUCNT_PIUSEQEN;
425	vrpiu_write(sc, PIUCNT_REG_W, cnt);
426
427	/* transit status DISABLE -> TOUCH or RELEASE */
428	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
429		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
430
431	splx(s);
432
433	return 0;
434}
435
436void
437vrpiu_tp_disable(v)
438	void *v;
439{
440	struct vrpiu_softc *sc = v;
441
442	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
443
444	/* Set level2 interrupt register to mask interrupts */
445	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
446
447	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
448
449	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
450	    /* Disable scan sequencer operation and power off */
451	    vrpiu_write(sc, PIUCNT_REG_W, 0);
452
453	    /* mask clock to PIU */
454	    __vrcmu_supply(CMUMSKPIU, 1);
455	}
456}
457
458int
459vrpiu_tp_ioctl(v, cmd, data, flag, p)
460	void *v;
461	u_long cmd;
462	caddr_t data;
463	int flag;
464	struct proc *p;
465{
466	struct vrpiu_softc *sc = v;
467
468	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
469
470	switch (cmd) {
471	case WSMOUSEIO_GTYPE:
472	    *(u_int *)data = WSMOUSE_TYPE_TPANEL;
473	    break;
474
475	case WSMOUSEIO_SRES:
476	    {
477		int tp_enable;
478		int ad_enable;
479
480		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
481		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
482
483		if (tp_enable)
484		    vrpiu_tp_disable(sc);
485		if (ad_enable)
486		    vrpiu_ad_disable(sc);
487
488		sc->sc_interval = scan_interval(*(u_int *)data);
489		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
490		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
491
492		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
493		    sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
494
495		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
496		    sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
497
498		if (tp_enable)
499		    vrpiu_tp_enable(sc);
500		if (ad_enable)
501		     vrpiu_ad_enable(sc);
502	    }
503	    break;
504
505	case WSMOUSEIO_SCALIBCOORDS:
506	case WSMOUSEIO_GCALIBCOORDS:
507            return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
508
509	default:
510	    return (-1);
511	}
512	return (0);
513}
514
515/*
516 * PIU AD interrupt handler.
517 */
518void
519vrpiu_ad_intr(sc)
520	struct vrpiu_softc *sc;
521{
522	unsigned int i;
523	unsigned int intrstat;
524
525	intrstat = vrpiu_read(sc, PIUINT_REG_W);
526
527	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
528	    /*
529	     * the device isn't enabled. just clear interrupt.
530	     */
531	    vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
532	    return;
533	}
534
535	if (intrstat & PIUINT_PADADPINTR) {
536	    sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
537	    sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
538	    sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
539	}
540
541	if (intrstat & PIUINT_PADADPINTR) {
542	    for (i = 0; i < 3; i++) {
543		if (sc->sc_battery.value[i] & PIUAB_VALID)
544		    sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
545		else
546		    sc->sc_battery.value[i] = 0;
547	    }
548	    vrpiu_calc_powerstate(sc);
549	}
550	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
551
552	return;
553}
554/*
555 * PIU TP interrupt handler.
556 */
557void
558vrpiu_tp_intr(sc)
559	struct vrpiu_softc *sc;
560{
561	unsigned int cnt, i;
562	unsigned int intrstat, page;
563	int tpx0, tpx1, tpy0, tpy1;
564	int x, y, xraw, yraw;
565
566	intrstat = vrpiu_read(sc, PIUINT_REG_W);
567
568	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
569	    /*
570	     * the device isn't enabled. just clear interrupt.
571	     */
572	    vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
573	    return;
574	}
575
576	page = (intrstat & PIUINT_OVP) ? 1 : 0;
577	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
578	    tpx0 = vrpiu_read(sc, PIUPB(page, 0));
579	    tpx1 = vrpiu_read(sc, PIUPB(page, 1));
580	    tpy0 = vrpiu_read(sc, PIUPB(page, 2));
581	    tpy1 = vrpiu_read(sc, PIUPB(page, 3));
582	}
583
584	if (intrstat & PIUINT_PADDLOSTINTR) {
585	    page = page ? 0 : 1;
586	    for (i = 0; i < 4; i++)
587		vrpiu_read(sc, PIUPB(page, i));
588	}
589
590	cnt = vrpiu_read(sc, PIUCNT_REG_W);
591#ifdef DEBUG
592	if (vrpiu_debug)
593	    vrpiu_dump_cntreg(cnt);
594#endif
595
596	/* clear interrupt status */
597	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
598
599#if 0
600	DPRINTF(("vrpiu_intr: OVP=%d", page));
601	if (intrstat & PIUINT_PADCMDINTR)
602	    DPRINTF((" CMD"));
603	if (intrstat & PIUINT_PADADPINTR)
604	    DPRINTF((" A/D"));
605	if (intrstat & PIUINT_PADPAGE1INTR)
606	    DPRINTF((" PAGE1"));
607	if (intrstat & PIUINT_PADPAGE0INTR)
608	    DPRINTF((" PAGE0"));
609	if (intrstat & PIUINT_PADDLOSTINTR)
610	    DPRINTF((" DLOST"));
611	if (intrstat & PIUINT_PENCHGINTR)
612	    DPRINTF((" PENCHG"));
613	DPRINTF(("\n"));
614#endif
615	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
616	    /*
617	     * just ignore scan data if status isn't Touch.
618	     */
619	    if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
620		/* reset tp scan timeout	*/
621		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
622			      vrpiu_tp_timeout, sc);
623
624		if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
625		    (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
626		    printf("vrpiu: internal error, data is not valid!\n");
627		} else {
628		    tpx0 &= PIUPB_PADDATA_MASK;
629		    tpx1 &= PIUPB_PADDATA_MASK;
630		    tpy0 &= PIUPB_PADDATA_MASK;
631		    tpy1 &= PIUPB_PADDATA_MASK;
632#define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
633		    if (ISVALID(tpx0 + tpx1, 1024, 200) &&
634			ISVALID(tpy0 + tpy1, 1024, 200)) {
635#if 0
636			DPRINTF(("%04x %04x %04x %04x\n",
637				 tpx0, tpx1, tpy0, tpy1));
638			DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
639				 tpx0 + tpx1, tpy0 + tpy1));
640#endif
641			xraw = tpy1 * 1024 / (tpy0 + tpy1);
642			yraw = tpx1 * 1024 / (tpx0 + tpx1);
643			DPRINTF(("%3d %3d", xraw, yraw));
644
645			tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
646
647			DPRINTF(("->%4d %4d", x, y));
648			wsmouse_input(sc->sc_wsmousedev,
649				      1, /* button 0 down */
650				      x, /* x */
651				      y, /* y */
652				      0, /* z */
653				      WSMOUSE_INPUT_ABSOLUTE_X |
654				      WSMOUSE_INPUT_ABSOLUTE_Y);
655			DPRINTF(("\n"));
656		    }
657		}
658	    }
659	}
660
661	if (cnt & PIUCNT_PENSTC) {
662	    if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
663		/*
664		 * pen touch
665		 */
666		DPRINTF(("PEN TOUCH\n"));
667		sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
668		/*
669		 * We should not report button down event while
670		 * we don't know where it occur.
671		 */
672
673		/* set tp scan timeout	*/
674		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
675			      vrpiu_tp_timeout, sc);
676	    }
677	} else {
678	    vrpiu_tp_up(sc);
679	}
680
681	if (intrstat & PIUINT_PADDLOSTINTR) {
682	    cnt |= PIUCNT_PIUSEQEN;
683	    vrpiu_write(sc, PIUCNT_REG_W, cnt);
684	}
685
686	return;
687}
688
689void
690vrpiu_tp_up(sc)
691	struct vrpiu_softc *sc;
692{
693	if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
694	    /*
695	     * pen release
696	     */
697	    DPRINTF(("RELEASE\n"));
698	    sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
699
700	    /* clear tp scan timeout	*/
701	    callout_stop(&sc->sc_tptimeout);
702
703	    /* button 0 UP */
704	    wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
705	}
706}
707
708/* touch panel timeout handler */
709void
710vrpiu_tp_timeout(v)
711	void *v;
712{
713	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
714
715#ifdef VRPIUDEBUG
716	{
717	    unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W);
718	    DPRINTF(("TIMEOUT: stat=%s  reg=%s\n",
719		(sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release",
720		(cnt & PIUCNT_PENSTC)?"touch":"release"));
721	}
722#endif
723	vrpiu_tp_up(sc);
724}
725
726/*
727 * PIU interrupt handler.
728 */
729int
730vrpiu_intr(arg)
731	void *arg;
732{
733        struct vrpiu_softc *sc = arg;
734
735	vrpiu_ad_intr(sc);
736	vrpiu_tp_intr(sc);
737
738	return 0;
739}
740
741void
742vrpiu_start_powerstate(v)
743	void *v;
744{
745	int mask;
746	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
747
748	vrpiu_ad_enable(sc);
749	mask = vrpiu_read(sc, PIUAMSK_REG_W);
750	mask &= 0xff8f; /* XXX */
751	vrpiu_write(sc, PIUAMSK_REG_W, mask);
752	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
753	/*
754	 * restart next A/D polling
755	 */
756	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
757		      vrpiu_start_powerstate, sc);
758}
759
760void
761vrpiu_calc_powerstate(sc)
762	struct vrpiu_softc *sc;
763{
764	extern void vrgiu_diff_io __P((void));
765	vrpiu_ad_disable(sc);
766	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
767		sc->sc_battery.value[0],
768		sc->sc_battery.value[1],
769		sc->sc_battery.value[2]));
770	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
771#ifdef notyet
772	config_hook_call(CONFIG_HOOK_SET,
773			 CONFIG_HOOK_BATTERYVAL,
774			 (void *)&sc->sc_battery);
775#endif /* notyet */
776	/*
777	 * restart next A/D polling if change polling timming.
778	 */
779	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
780	    callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
781			  vrpiu_start_powerstate, sc);
782	if (bootverbose)
783	    vrgiu_diff_io();
784
785}
786
787static void
788vrpiu_power(why, arg)
789	int why;
790	void *arg;
791{
792	struct vrpiu_softc *sc = arg;
793
794	switch (why) {
795	case PWR_STANDBY:
796	case PWR_SUSPEND:
797	    break;
798	case PWR_RESUME:
799	    callout_reset(&sc->sc_adpoll, hz,
800			  vrpiu_start_powerstate, sc);
801	    break;
802	}
803}
804
805#ifdef DEBUG
806void
807vrpiu_dump_cntreg(cnt)
808	unsigned int cnt;
809{
810	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
811	printf(" state=");
812	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
813	    printf("CmdScan");
814	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
815	    printf("IntervalNextScan");
816	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
817	    printf("PenDataScan");
818	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
819	    printf("WaitPenTouch");
820	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
821	    printf("???");
822	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
823	    printf("ADPortScan");
824	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
825	    printf("Standby");
826	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
827	    printf("Disable");
828	if (cnt & PIUCNT_PADATSTOP)
829	    printf(" AutoStop");
830	if (cnt & PIUCNT_PADATSTART)
831	    printf(" AutoStart");
832	if (cnt & PIUCNT_PADSCANSTOP)
833	    printf(" Stop");
834	if (cnt & PIUCNT_PADSCANSTART)
835	    printf(" Start");
836	if (cnt & PIUCNT_PADSCANTYPE)
837	    printf(" ScanPressure");
838	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
839	    printf(" A/D");
840	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
841	    printf(" Coordinate");
842	if (cnt & PIUCNT_PIUSEQEN)
843	    printf(" SeqEn");
844	if ((cnt & PIUCNT_PIUPWR) == 0)
845	    printf(" PowerOff");
846	if ((cnt & PIUCNT_PADRST) == 0)
847	    printf(" Reset");
848	printf("\n");
849}
850#endif
851