vrpiu.c revision 1.11
1/*	$NetBSD: vrpiu.c,v 1.11 2001/02/22 18:38:05 uch 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_700A,
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		{ NULL,		/* samples got on my MC-R500 */
216		  { 0, 0, 639, 239,
217		    5,
218		    { { 502, 486, 320, 120 },
219		      {  55, 109,   0,   0 },
220		      {  54, 913,   0, 239 },
221		      { 973, 924, 639, 239 },
222		      { 975, 123, 639,   0 } } } },
223	    };
224	    for (i = 0; ; i++) {
225		if (calibrations[i].mask == NULL
226		    || platid_match(&platid, calibrations[i].mask))
227		    break;
228	    }
229	    tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
230			  (caddr_t)&calibrations[i].coords, 0, 0);
231	}
232#endif
233
234	/* install interrupt handler and enable interrupt */
235	if (!(sc->sc_handler =
236	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
237				vrpiu_intr, sc))) {
238	    printf (": can't map interrupt line.\n");
239	    return;
240	}
241
242	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
243	vrpiu_tp_disable(sc);
244
245	printf("\n");
246
247	wsmaa.accessops = &vrpiu_accessops;
248	wsmaa.accesscookie = sc;
249
250	/*
251	 * attach the wsmouse
252	 */
253	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
254
255	/*
256	 * power management events
257	 */
258	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
259
260	/*
261	 * init A/D port polling.
262	 */
263	sc->sc_battery.n_values = 3;
264	sc->sc_battery.value[0] = -1;
265	sc->sc_battery.value[1] = -1;
266	sc->sc_battery.value[2] = -1;
267	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
268	callout_init(&sc->sc_adpoll);
269	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
270}
271
272/*
273 * calculate interval value
274 *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
275 * output: value for PIUSIVL_REG
276 */
277static u_int
278scan_interval(u_int data)
279{
280	int scale;
281
282	if (data < WSMOUSE_RES_MIN)
283	    data = WSMOUSE_RES_MIN;
284
285	if (WSMOUSE_RES_MAX < data)
286	    data = WSMOUSE_RES_MAX;
287
288	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
289	data += WSMOUSE_RES_MIN;
290
291	return PIUSIVL_SCANINTVAL_MIN +
292	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
293	    (scale - data) / scale;
294}
295
296int
297vrpiu_ad_enable(v)
298	void *v;
299{
300	struct vrpiu_softc *sc = v;
301	int s;
302	unsigned int cnt;
303
304	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
305		 __FILE__, __LINE__, sc->sc_interval));
306	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
307	    return EBUSY;
308
309	/* supply clock to PIU */
310	__vrcmu_supply(CMUMSKPIU, 1);
311
312	/* set scan interval */
313	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
314
315	s = spltty();
316
317	/* clear interrupt status */
318	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
319
320	/* Disable -> Standby */
321	cnt = PIUCNT_PIUPWR |
322		PIUCNT_PIUMODE_COORDINATE |
323		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
324	vrpiu_write(sc, PIUCNT_REG_W, cnt);
325
326	/* Level2 interrupt register setting */
327	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
328
329	/* save pen status, touch or release */
330	cnt = vrpiu_read(sc, PIUCNT_REG_W);
331
332	/*
333	 * Enable scan sequencer operation
334	 * Standby -> WaitPenTouch
335	 */
336	cnt |= PIUCNT_PIUSEQEN;
337	vrpiu_write(sc, PIUCNT_REG_W, cnt);
338
339	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
340
341	splx(s);
342
343	return 0;
344}
345
346void
347vrpiu_ad_disable(v)
348	void *v;
349{
350	struct vrpiu_softc *sc = v;
351
352	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
353
354	/* Set level2 interrupt register to mask interrupts */
355	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
356
357	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
358
359	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
360	    /* Disable scan sequencer operation and power off */
361	    vrpiu_write(sc, PIUCNT_REG_W, 0);
362
363	    /* mask clock to PIU */
364	    __vrcmu_supply(CMUMSKPIU, 1);
365	}
366}
367
368int
369vrpiu_tp_enable(v)
370	void *v;
371{
372	struct vrpiu_softc *sc = v;
373	int s;
374	unsigned int cnt;
375
376	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
377		 __FILE__, __LINE__, sc->sc_interval));
378	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
379	    return EBUSY;
380
381	/* supply clock to PIU */
382	__vrcmu_supply(CMUMSKPIU, 1);
383
384	/* set scan interval */
385	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
386
387	s = spltty();
388
389	/* clear interrupt status */
390	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
391
392	/* Disable -> Standby */
393	cnt = PIUCNT_PIUPWR |
394		PIUCNT_PIUMODE_COORDINATE |
395		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
396	vrpiu_write(sc, PIUCNT_REG_W, cnt);
397
398	/* Level2 interrupt register setting */
399	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
400
401	/* save pen status, touch or release */
402	cnt = vrpiu_read(sc, PIUCNT_REG_W);
403
404	/*
405	 * Enable scan sequencer operation
406	 * Standby -> WaitPenTouch
407	 */
408	cnt |= PIUCNT_PIUSEQEN;
409	vrpiu_write(sc, PIUCNT_REG_W, cnt);
410
411	/* transit status DISABLE -> TOUCH or RELEASE */
412	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
413		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
414
415	splx(s);
416
417	return 0;
418}
419
420void
421vrpiu_tp_disable(v)
422	void *v;
423{
424	struct vrpiu_softc *sc = v;
425
426	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
427
428	/* Set level2 interrupt register to mask interrupts */
429	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
430
431	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
432
433	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
434	    /* Disable scan sequencer operation and power off */
435	    vrpiu_write(sc, PIUCNT_REG_W, 0);
436
437	    /* mask clock to PIU */
438	    __vrcmu_supply(CMUMSKPIU, 1);
439	}
440}
441
442int
443vrpiu_tp_ioctl(v, cmd, data, flag, p)
444	void *v;
445	u_long cmd;
446	caddr_t data;
447	int flag;
448	struct proc *p;
449{
450	struct vrpiu_softc *sc = v;
451
452	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
453
454	switch (cmd) {
455	case WSMOUSEIO_GTYPE:
456	    *(u_int *)data = WSMOUSE_TYPE_TPANEL;
457	    break;
458
459	case WSMOUSEIO_SRES:
460	    {
461		int tp_enable;
462		int ad_enable;
463
464		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
465		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
466
467		if (tp_enable)
468		    vrpiu_tp_disable(sc);
469		if (ad_enable)
470		    vrpiu_ad_disable(sc);
471
472		sc->sc_interval = scan_interval(*(u_int *)data);
473		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
474		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
475
476		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
477		    sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
478
479		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
480		    sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
481
482		if (tp_enable)
483		    vrpiu_tp_enable(sc);
484		if (ad_enable)
485		     vrpiu_ad_enable(sc);
486	    }
487	    break;
488
489	case WSMOUSEIO_SCALIBCOORDS:
490	case WSMOUSEIO_GCALIBCOORDS:
491            return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
492
493	default:
494	    return (-1);
495	}
496	return (0);
497}
498
499/*
500 * PIU AD interrupt handler.
501 */
502void
503vrpiu_ad_intr(sc)
504	struct vrpiu_softc *sc;
505{
506	unsigned int i;
507	unsigned int intrstat;
508
509	intrstat = vrpiu_read(sc, PIUINT_REG_W);
510
511	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
512	    /*
513	     * the device isn't enabled. just clear interrupt.
514	     */
515	    vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
516	    return;
517	}
518
519	if (intrstat & PIUINT_PADADPINTR) {
520	    sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
521	    sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
522	    sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
523	}
524
525	if (intrstat & PIUINT_PADADPINTR) {
526	    for (i = 0; i < 3; i++) {
527		if (sc->sc_battery.value[i] & PIUAB_VALID)
528		    sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
529		else
530		    sc->sc_battery.value[i] = 0;
531	    }
532	    vrpiu_calc_powerstate(sc);
533	}
534	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
535
536	return;
537}
538/*
539 * PIU TP interrupt handler.
540 */
541void
542vrpiu_tp_intr(sc)
543	struct vrpiu_softc *sc;
544{
545	unsigned int cnt, i;
546	unsigned int intrstat, page;
547	int tpx0, tpx1, tpy0, tpy1;
548	int x, y, xraw, yraw;
549
550	intrstat = vrpiu_read(sc, PIUINT_REG_W);
551
552	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
553	    /*
554	     * the device isn't enabled. just clear interrupt.
555	     */
556	    vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
557	    return;
558	}
559
560	page = (intrstat & PIUINT_OVP) ? 1 : 0;
561	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
562	    tpx0 = vrpiu_read(sc, PIUPB(page, 0));
563	    tpx1 = vrpiu_read(sc, PIUPB(page, 1));
564	    tpy0 = vrpiu_read(sc, PIUPB(page, 2));
565	    tpy1 = vrpiu_read(sc, PIUPB(page, 3));
566	}
567
568	if (intrstat & PIUINT_PADDLOSTINTR) {
569	    page = page ? 0 : 1;
570	    for (i = 0; i < 4; i++)
571		vrpiu_read(sc, PIUPB(page, i));
572	}
573
574	cnt = vrpiu_read(sc, PIUCNT_REG_W);
575#ifdef DEBUG
576	if (vrpiu_debug)
577	    vrpiu_dump_cntreg(cnt);
578#endif
579
580	/* clear interrupt status */
581	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
582
583#if 0
584	DPRINTF(("vrpiu_intr: OVP=%d", page));
585	if (intrstat & PIUINT_PADCMDINTR)
586	    DPRINTF((" CMD"));
587	if (intrstat & PIUINT_PADADPINTR)
588	    DPRINTF((" A/D"));
589	if (intrstat & PIUINT_PADPAGE1INTR)
590	    DPRINTF((" PAGE1"));
591	if (intrstat & PIUINT_PADPAGE0INTR)
592	    DPRINTF((" PAGE0"));
593	if (intrstat & PIUINT_PADDLOSTINTR)
594	    DPRINTF((" DLOST"));
595	if (intrstat & PIUINT_PENCHGINTR)
596	    DPRINTF((" PENCHG"));
597	DPRINTF(("\n"));
598#endif
599	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
600	    /*
601	     * just ignore scan data if status isn't Touch.
602	     */
603	    if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
604		/* reset tp scan timeout	*/
605		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
606			      vrpiu_tp_timeout, sc);
607
608		if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
609		    (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
610		    printf("vrpiu: internal error, data is not valid!\n");
611		} else {
612		    tpx0 &= PIUPB_PADDATA_MASK;
613		    tpx1 &= PIUPB_PADDATA_MASK;
614		    tpy0 &= PIUPB_PADDATA_MASK;
615		    tpy1 &= PIUPB_PADDATA_MASK;
616#define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
617		    if (ISVALID(tpx0 + tpx1, 1024, 200) &&
618			ISVALID(tpy0 + tpy1, 1024, 200)) {
619#if 0
620			DPRINTF(("%04x %04x %04x %04x\n",
621				 tpx0, tpx1, tpy0, tpy1));
622			DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
623				 tpx0 + tpx1, tpy0 + tpy1));
624#endif
625			xraw = tpy1 * 1024 / (tpy0 + tpy1);
626			yraw = tpx1 * 1024 / (tpx0 + tpx1);
627			DPRINTF(("%3d %3d", xraw, yraw));
628
629			tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
630
631			DPRINTF(("->%4d %4d", x, y));
632			wsmouse_input(sc->sc_wsmousedev,
633				      1, /* button 0 down */
634				      x, /* x */
635				      y, /* y */
636				      0, /* z */
637				      WSMOUSE_INPUT_ABSOLUTE_X |
638				      WSMOUSE_INPUT_ABSOLUTE_Y);
639			DPRINTF(("\n"));
640		    }
641		}
642	    }
643	}
644
645	if (cnt & PIUCNT_PENSTC) {
646	    if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
647		/*
648		 * pen touch
649		 */
650		DPRINTF(("PEN TOUCH\n"));
651		sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
652		/*
653		 * We should not report button down event while
654		 * we don't know where it occur.
655		 */
656
657		/* set tp scan timeout	*/
658		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
659			      vrpiu_tp_timeout, sc);
660	    }
661	} else {
662	    vrpiu_tp_up(sc);
663	}
664
665	if (intrstat & PIUINT_PADDLOSTINTR) {
666	    cnt |= PIUCNT_PIUSEQEN;
667	    vrpiu_write(sc, PIUCNT_REG_W, cnt);
668	}
669
670	return;
671}
672
673void
674vrpiu_tp_up(sc)
675	struct vrpiu_softc *sc;
676{
677	if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
678	    /*
679	     * pen release
680	     */
681	    DPRINTF(("RELEASE\n"));
682	    sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
683
684	    /* clear tp scan timeout	*/
685	    callout_stop(&sc->sc_tptimeout);
686
687	    /* button 0 UP */
688	    wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
689	}
690}
691
692/* touch panel timeout handler */
693void
694vrpiu_tp_timeout(v)
695	void *v;
696{
697	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
698
699#ifdef VRPIUDEBUG
700	{
701	    unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W);
702	    DPRINTF(("TIMEOUT: stat=%s  reg=%s\n",
703		(sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release",
704		(cnt & PIUCNT_PENSTC)?"touch":"release"));
705	}
706#endif
707	vrpiu_tp_up(sc);
708}
709
710/*
711 * PIU interrupt handler.
712 */
713int
714vrpiu_intr(arg)
715	void *arg;
716{
717        struct vrpiu_softc *sc = arg;
718
719	vrpiu_ad_intr(sc);
720	vrpiu_tp_intr(sc);
721
722	return 0;
723}
724
725void
726vrpiu_start_powerstate(v)
727	void *v;
728{
729	int mask;
730	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
731
732	vrpiu_ad_enable(sc);
733	mask = vrpiu_read(sc, PIUAMSK_REG_W);
734	mask &= 0xff8f; /* XXX */
735	vrpiu_write(sc, PIUAMSK_REG_W, mask);
736	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
737	/*
738	 * restart next A/D polling
739	 */
740	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
741		      vrpiu_start_powerstate, sc);
742}
743
744void
745vrpiu_calc_powerstate(sc)
746	struct vrpiu_softc *sc;
747{
748	extern void vrgiu_diff_io __P((void));
749	vrpiu_ad_disable(sc);
750	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
751		sc->sc_battery.value[0],
752		sc->sc_battery.value[1],
753		sc->sc_battery.value[2]));
754	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
755#ifdef notyet
756	config_hook_call(CONFIG_HOOK_SET,
757			 CONFIG_HOOK_BATTERYVAL,
758			 (void *)&sc->sc_battery);
759#endif /* notyet */
760	/*
761	 * restart next A/D polling if change polling timming.
762	 */
763	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
764	    callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
765			  vrpiu_start_powerstate, sc);
766	if (bootverbose)
767	    vrgiu_diff_io();
768
769}
770
771static void
772vrpiu_power(why, arg)
773	int why;
774	void *arg;
775{
776	struct vrpiu_softc *sc = arg;
777
778	switch (why) {
779	case PWR_STANDBY:
780	case PWR_SUSPEND:
781	    break;
782	case PWR_RESUME:
783	    callout_reset(&sc->sc_adpoll, hz,
784			  vrpiu_start_powerstate, sc);
785	    break;
786	}
787}
788
789#ifdef DEBUG
790void
791vrpiu_dump_cntreg(cnt)
792	unsigned int cnt;
793{
794	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
795	printf(" state=");
796	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
797	    printf("CmdScan");
798	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
799	    printf("IntervalNextScan");
800	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
801	    printf("PenDataScan");
802	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
803	    printf("WaitPenTouch");
804	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
805	    printf("???");
806	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
807	    printf("ADPortScan");
808	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
809	    printf("Standby");
810	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
811	    printf("Disable");
812	if (cnt & PIUCNT_PADATSTOP)
813	    printf(" AutoStop");
814	if (cnt & PIUCNT_PADATSTART)
815	    printf(" AutoStart");
816	if (cnt & PIUCNT_PADSCANSTOP)
817	    printf(" Stop");
818	if (cnt & PIUCNT_PADSCANSTART)
819	    printf(" Start");
820	if (cnt & PIUCNT_PADSCANTYPE)
821	    printf(" ScanPressure");
822	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
823	    printf(" A/D");
824	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
825	    printf(" Coordinate");
826	if (cnt & PIUCNT_PIUSEQEN)
827	    printf(" SeqEn");
828	if ((cnt & PIUCNT_PIUPWR) == 0)
829	    printf(" PowerOff");
830	if ((cnt & PIUCNT_PADRST) == 0)
831	    printf(" Reset");
832	printf("\n");
833}
834#endif
835