vrpiu.c revision 1.17
1/*	$NetBSD: vrpiu.c,v 1.17 2001/09/28 10:25:15 sato Exp $	*/
2
3/*
4 * Copyright (c) 1999-2001 Shin Takemura All rights reserved.
5 * Copyright (c) 2000-2001 SATO Kazumi, All rights reserved.
6 * Copyright (c) 1999-2001 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 <dev/hpc/hpcbatteryvar.h>
53#include <dev/hpc/hpcbatterytable.h>
54
55#include <hpcmips/hpcmips/machdep.h>
56#include <hpcmips/vr/vrcpudef.h>
57#include <hpcmips/vr/vripvar.h>
58#include <hpcmips/vr/cmureg.h>
59#include <hpcmips/vr/vrpiuvar.h>
60#include <hpcmips/vr/vrpiureg.h>
61
62/*
63 * contant and macro definitions
64 */
65#define VRPIUDEBUG
66#ifdef VRPIUDEBUG
67int	vrpiu_debug = 0;
68#define	DPRINTF(arg) if (vrpiu_debug) printf arg;
69#define	VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
70#else
71#define	DPRINTF(arg)
72#define	VPRINTF(arg) if (bootverbose) printf arg;
73#endif
74
75#ifndef VRPIU_NO_ADHOC_BATTERY_EVENT
76#define VRPIU_ADHOC_BATTERY_EVENT	/* currently... */
77#endif /* VRPIU_NO_ADHOC_BATTERY_EVENT */
78
79#ifndef VRPIU_AD_POLL_INTERVAL
80#define VRPIU_AD_POLL_INTERVAL	60	/* interval is 60 sec */
81#endif /* VRPIU_AD_POLL_INTERTVAL */
82
83#define	PIUSIVL_SCANINTVAL_MIN	333			/* 10msec	*/
84#define	PIUSIVL_SCANINTVAL_MAX	PIUSIVL_SCANINTVAL_MASK	/* 60msec	*/
85#define VRPIU_TP_SCAN_TIMEOUT	(hz/10)		/* timeout is 100msec	*/
86
87#define TP_INTR	(PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
88#define AD_INTR	(PIUINT_PADADPINTR)
89
90/*
91 * data types
92 */
93/* struct vrpiu_softc is defined in vrpiuvar.h */
94
95/*
96 * function prototypes
97 */
98static int	vrpiumatch(struct device *, struct cfdata *, void *);
99static void	vrpiuattach(struct device *, struct device *, void *);
100
101static void	vrpiu_write(struct vrpiu_softc *, int, unsigned short);
102static u_short	vrpiu_read(struct vrpiu_softc *, int);
103
104static int	vrpiu_intr(void *);
105static void	vrpiu_tp_intr(struct vrpiu_softc *);
106static void	vrpiu_ad_intr(struct vrpiu_softc *);
107#ifdef DEBUG
108static void	vrpiu_dump_cntreg(unsigned int);
109#endif
110
111static int	vrpiu_tp_enable(void *);
112static int	vrpiu_tp_ioctl(void *, u_long, caddr_t, int, struct proc *);
113static void	vrpiu_tp_disable(void *);
114static void	vrpiu_tp_up(struct vrpiu_softc *);
115static void	vrpiu_tp_timeout(void *);
116int		vrpiu_ad_enable(void *);
117void		vrpiu_ad_disable(void *);
118static void	vrpiu_start_powerstate(void *);
119static void	vrpiu_calc_powerstate(struct vrpiu_softc *);
120static void	vrpiu_send_battery_event(struct vrpiu_softc *);
121static void	vrpiu_power(int, void *);
122static u_int	scan_interval(u_int data);
123
124/* mra is defined in mra.c */
125int mra_Y_AX1_BX2_C(int *y, int ys, int *x1, int x1s, int *x2, int x2s,
126    int n, int scale, int *a, int *b, int *c);
127
128/*
129 * static or global variables
130 */
131struct cfattach vrpiu_ca = {
132	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
133};
134
135const struct wsmouse_accessops vrpiu_accessops = {
136	vrpiu_tp_enable,
137	vrpiu_tp_ioctl,
138	vrpiu_tp_disable,
139};
140
141int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
142
143/*
144 * function definitions
145 */
146static inline void
147vrpiu_write(struct vrpiu_softc *sc, int port, unsigned short val)
148{
149
150	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
151}
152
153static inline u_short
154vrpiu_read(struct vrpiu_softc *sc, int port)
155{
156
157	return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port));
158}
159
160static int
161vrpiumatch(struct device *parent, struct cfdata *cf, void *aux)
162{
163
164	return (1);
165}
166
167static void
168vrpiuattach(struct device *parent, struct device *self, void *aux)
169{
170	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
171	struct vrip_attach_args *va = aux;
172	struct wsmousedev_attach_args wsmaa;
173
174	bus_space_tag_t iot = va->va_iot;
175	bus_space_handle_t ioh;
176	struct platid_data *p;
177
178	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
179		printf(": can't map bus space\n");
180		return;
181	}
182
183	sc->sc_iot = iot;
184	sc->sc_ioh = ioh;
185	sc->sc_vrip = va->va_vc;
186
187	sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
188	if ((p = platid_search_data(&platid, hpcbattery_parameters)) == NULL)
189		sc->sc_battery_spec = NULL;
190	else
191		sc->sc_battery_spec  = p->data;
192
193	/*
194	 * disable device until vrpiu_enable called
195	 */
196	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
197
198	/* initialize touch panel timeout structure	*/
199	callout_init(&sc->sc_tptimeout);
200
201	/* initialize calibration context	*/
202	tpcalib_init(&sc->sc_tpcalib);
203#if 1
204	/*
205	 * XXX, calibrate parameters
206	 */
207	{
208		int i;
209		static const struct {
210			platid_mask_t *mask;
211			struct wsmouse_calibcoords coords;
212		} calibrations[] = {
213			{ &platid_mask_MACH_NEC_MCR_700,
214			  { 0, 0, 799, 599,
215			    4,
216			    { { 115,  80,   0,   0 },
217			      { 115, 966,   0, 599 },
218			      { 912,  80, 799,   0 },
219			      { 912, 966, 799, 599 } } } },
220			{ &platid_mask_MACH_NEC_MCR_700A,
221			  { 0, 0, 799, 599,
222			    4,
223			    { { 115,  80,   0,   0 },
224			      { 115, 966,   0, 599 },
225			      { 912,  80, 799,   0 },
226			      { 912, 966, 799, 599 } } } },
227			{ &platid_mask_MACH_NEC_MCR_730,
228			  { 0, 0, 799, 599,
229			    4,
230			    { { 115,  80,   0,   0 },
231			      { 115, 966,   0, 599 },
232			      { 912,  80, 799,   0 },
233			      { 912, 966, 799, 599 } } } },
234			{ NULL,		/* samples got on my MC-R500 */
235			  { 0, 0, 639, 239,
236			    5,
237			    { { 502, 486, 320, 120 },
238			      {  55, 109,   0,   0 },
239			      {  54, 913,   0, 239 },
240			      { 973, 924, 639, 239 },
241			      { 975, 123, 639,   0 } } } },
242		};
243		for (i = 0; ; i++) {
244			if (calibrations[i].mask == NULL
245			    || platid_match(&platid, calibrations[i].mask))
246				break;
247		}
248		tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
249		    (caddr_t)&calibrations[i].coords, 0, 0);
250	}
251#endif
252
253	/* install interrupt handler and enable interrupt */
254	if (!(sc->sc_handler =
255	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
256		vrpiu_intr, sc))) {
257		printf (": can't map interrupt line.\n");
258		return;
259	}
260
261	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
262	vrpiu_tp_disable(sc);
263
264	printf("\n");
265
266	wsmaa.accessops = &vrpiu_accessops;
267	wsmaa.accesscookie = sc;
268
269	/*
270	 * attach the wsmouse
271	 */
272	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
273
274	/*
275	 * power management events
276	 */
277	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
278
279	/*
280	 * init A/D port polling.
281	 */
282	sc->sc_battery.n_values = 3;
283	sc->sc_battery.value[0] = -1;
284	sc->sc_battery.value[1] = -1;
285	sc->sc_battery.value[2] = -1;
286	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
287	callout_init(&sc->sc_adpoll);
288	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
289}
290
291/*
292 * calculate interval value
293 *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
294 * output: value for PIUSIVL_REG
295 */
296static u_int
297scan_interval(u_int data)
298{
299	int scale;
300
301	if (data < WSMOUSE_RES_MIN)
302		data = WSMOUSE_RES_MIN;
303
304	if (WSMOUSE_RES_MAX < data)
305		data = WSMOUSE_RES_MAX;
306
307	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
308	data += WSMOUSE_RES_MIN;
309
310	return PIUSIVL_SCANINTVAL_MIN +
311	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
312	    (scale - data) / scale;
313}
314
315int
316vrpiu_ad_enable(void *v)
317{
318	struct vrpiu_softc *sc = v;
319	int s;
320	unsigned int cnt;
321
322	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
323	    __FILE__, __LINE__, sc->sc_interval));
324	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
325		return EBUSY;
326
327	/* supply clock to PIU */
328	__vrcmu_supply(CMUMASK_PIU, 1);
329
330	/* set scan interval */
331	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
332
333	s = spltty();
334
335	/* clear interrupt status */
336	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
337
338	/* Disable -> Standby */
339	cnt = PIUCNT_PIUPWR |
340	    PIUCNT_PIUMODE_COORDINATE |
341	    PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
342	vrpiu_write(sc, PIUCNT_REG_W, cnt);
343
344	/* Level2 interrupt register setting */
345	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
346
347	/* save pen status, touch or release */
348	cnt = vrpiu_read(sc, PIUCNT_REG_W);
349
350	/*
351	 * Enable scan sequencer operation
352	 * Standby -> WaitPenTouch
353	 */
354	cnt |= PIUCNT_PIUSEQEN;
355	vrpiu_write(sc, PIUCNT_REG_W, cnt);
356
357	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
358
359	splx(s);
360
361	return 0;
362}
363
364void
365vrpiu_ad_disable(void *v)
366{
367	struct vrpiu_softc *sc = v;
368
369	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
370
371	/* Set level2 interrupt register to mask interrupts */
372	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
373
374	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
375
376	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
377		/* Disable scan sequencer operation and power off */
378		vrpiu_write(sc, PIUCNT_REG_W, 0);
379
380		/* mask clock to PIU */
381		__vrcmu_supply(CMUMASK_PIU, 0);
382	}
383}
384
385int
386vrpiu_tp_enable(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(CMUMASK_PIU, 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(void *v)
438{
439	struct vrpiu_softc *sc = v;
440
441	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
442
443	/* Set level2 interrupt register to mask interrupts */
444	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
445
446	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
447
448	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
449		/* Disable scan sequencer operation and power off */
450		vrpiu_write(sc, PIUCNT_REG_W, 0);
451
452		/* mask clock to PIU */
453		__vrcmu_supply(CMUMASK_PIU, 0);
454	}
455}
456
457int
458vrpiu_tp_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
459{
460	struct vrpiu_softc *sc = v;
461
462	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
463
464	switch (cmd) {
465	case WSMOUSEIO_GTYPE:
466		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
467		break;
468
469	case WSMOUSEIO_SRES:
470	{
471		int tp_enable;
472		int ad_enable;
473
474		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
475		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
476
477		if (tp_enable)
478			vrpiu_tp_disable(sc);
479		if (ad_enable)
480			vrpiu_ad_disable(sc);
481
482		sc->sc_interval = scan_interval(*(u_int *)data);
483		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
484		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
485
486		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
487			sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
488
489		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
490			sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
491
492		if (tp_enable)
493			vrpiu_tp_enable(sc);
494		if (ad_enable)
495			vrpiu_ad_enable(sc);
496	}
497	break;
498
499	case WSMOUSEIO_SCALIBCOORDS:
500	case WSMOUSEIO_GCALIBCOORDS:
501		return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
502
503	default:
504		return (-1);
505	}
506	return (0);
507}
508
509/*
510 * PIU AD interrupt handler.
511 */
512void
513vrpiu_ad_intr(struct vrpiu_softc *sc)
514{
515	unsigned int i;
516	unsigned int intrstat;
517
518	intrstat = vrpiu_read(sc, PIUINT_REG_W);
519
520	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
521		/*
522		 * the device isn't enabled. just clear interrupt.
523		 */
524		vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
525		return;
526	}
527
528	if (intrstat & PIUINT_PADADPINTR) {
529		sc->sc_battery.value[0] = (unsigned int)
530		    vrpiu_read(sc, PIUAB(0));
531		sc->sc_battery.value[1] = (unsigned int)
532		    vrpiu_read(sc, PIUAB(1));
533		sc->sc_battery.value[2] = (unsigned int)
534		    vrpiu_read(sc, PIUAB(2));
535	}
536
537	if (intrstat & PIUINT_PADADPINTR) {
538		for (i = 0; i < 3; i++) {
539			if (sc->sc_battery.value[i] & PIUAB_VALID)
540				sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
541			else
542				sc->sc_battery.value[i] = 0;
543		}
544		vrpiu_calc_powerstate(sc);
545	}
546	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
547
548	return;
549}
550/*
551 * PIU TP interrupt handler.
552 */
553void
554vrpiu_tp_intr(struct vrpiu_softc *sc)
555{
556	unsigned int cnt, i;
557	unsigned int intrstat, page;
558	int tpx0, tpx1, tpy0, tpy1;
559	int x, y, xraw, yraw;
560
561	intrstat = vrpiu_read(sc, PIUINT_REG_W);
562
563	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
564		/*
565		 * the device isn't enabled. just clear interrupt.
566		 */
567		vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
568		return;
569	}
570
571	page = (intrstat & PIUINT_OVP) ? 1 : 0;
572	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
573		tpx0 = vrpiu_read(sc, PIUPB(page, 0));
574		tpx1 = vrpiu_read(sc, PIUPB(page, 1));
575		tpy0 = vrpiu_read(sc, PIUPB(page, 2));
576		tpy1 = vrpiu_read(sc, PIUPB(page, 3));
577	}
578
579	if (intrstat & PIUINT_PADDLOSTINTR) {
580		page = page ? 0 : 1;
581		for (i = 0; i < 4; i++)
582			vrpiu_read(sc, PIUPB(page, i));
583	}
584
585	cnt = vrpiu_read(sc, PIUCNT_REG_W);
586#ifdef DEBUG
587	if (vrpiu_debug)
588		vrpiu_dump_cntreg(cnt);
589#endif
590
591	/* clear interrupt status */
592	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
593
594#if 0
595	DPRINTF(("vrpiu_intr: OVP=%d", page));
596	if (intrstat & PIUINT_PADCMDINTR)
597		DPRINTF((" CMD"));
598	if (intrstat & PIUINT_PADADPINTR)
599		DPRINTF((" A/D"));
600	if (intrstat & PIUINT_PADPAGE1INTR)
601		DPRINTF((" PAGE1"));
602	if (intrstat & PIUINT_PADPAGE0INTR)
603		DPRINTF((" PAGE0"));
604	if (intrstat & PIUINT_PADDLOSTINTR)
605		DPRINTF((" DLOST"));
606	if (intrstat & PIUINT_PENCHGINTR)
607		DPRINTF((" PENCHG"));
608	DPRINTF(("\n"));
609#endif
610	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
611		/*
612		 * just ignore scan data if status isn't Touch.
613		 */
614		if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
615			/* reset tp scan timeout	*/
616			callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
617			    vrpiu_tp_timeout, sc);
618
619			if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
620			    (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
621				printf("vrpiu: internal error,"
622				    " data is not valid!\n");
623			} else {
624				tpx0 &= PIUPB_PADDATA_MASK;
625				tpx1 &= PIUPB_PADDATA_MASK;
626				tpy0 &= PIUPB_PADDATA_MASK;
627				tpy1 &= PIUPB_PADDATA_MASK;
628#define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
629				if (ISVALID(tpx0 + tpx1, 1024, 200) &&
630				    ISVALID(tpy0 + tpy1, 1024, 200)) {
631#if 0
632					DPRINTF(("%04x %04x %04x %04x\n",
633					    tpx0, tpx1, tpy0, tpy1));
634					DPRINTF(("%3d %3d (%4d %4d)->", tpx0,
635					    tpy0, tpx0 + tpx1, tpy0 + tpy1));
636#endif
637					xraw = tpy1 * 1024 / (tpy0 + tpy1);
638					yraw = tpx1 * 1024 / (tpx0 + tpx1);
639					DPRINTF(("%3d %3d", xraw, yraw));
640
641					tpcalib_trans(&sc->sc_tpcalib, xraw,
642					    yraw, &x, &y);
643
644					DPRINTF(("->%4d %4d", x, y));
645					wsmouse_input(sc->sc_wsmousedev,
646					    1, /* button 0 down */
647					    x, /* x */
648					    y, /* y */
649					    0, /* z */
650					    WSMOUSE_INPUT_ABSOLUTE_X |
651					    WSMOUSE_INPUT_ABSOLUTE_Y);
652					DPRINTF(("\n"));
653				}
654			}
655		}
656	}
657
658	if (cnt & PIUCNT_PENSTC) {
659		if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
660			/*
661			 * pen touch
662			 */
663			DPRINTF(("PEN TOUCH\n"));
664			sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
665			/*
666			 * We should not report button down event while
667			 * we don't know where it occur.
668			 */
669
670			/* set tp scan timeout	*/
671			callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
672			    vrpiu_tp_timeout, sc);
673		}
674	} else {
675		vrpiu_tp_up(sc);
676	}
677
678	if (intrstat & PIUINT_PADDLOSTINTR) {
679		cnt |= PIUCNT_PIUSEQEN;
680		vrpiu_write(sc, PIUCNT_REG_W, cnt);
681	}
682
683	return;
684}
685
686void
687vrpiu_tp_up(struct vrpiu_softc *sc)
688{
689	if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
690		/*
691		 * pen release
692		 */
693		DPRINTF(("RELEASE\n"));
694		sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
695
696		/* clear tp scan timeout	*/
697		callout_stop(&sc->sc_tptimeout);
698
699		/* button 0 UP */
700		wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
701	}
702}
703
704/* touch panel timeout handler */
705void
706vrpiu_tp_timeout(void *v)
707{
708	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
709
710#ifdef VRPIUDEBUG
711	{
712		unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W);
713		DPRINTF(("TIMEOUT: stat=%s  reg=%s\n",
714		    (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release",
715		    (cnt & PIUCNT_PENSTC)?"touch":"release"));
716	}
717#endif
718	vrpiu_tp_up(sc);
719}
720
721/*
722 * PIU interrupt handler.
723 */
724int
725vrpiu_intr(void *arg)
726{
727        struct vrpiu_softc *sc = arg;
728
729	vrpiu_ad_intr(sc);
730	vrpiu_tp_intr(sc);
731
732	return 0;
733}
734
735void
736vrpiu_start_powerstate(void *v)
737{
738	int mask;
739	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
740
741	vrpiu_ad_enable(sc);
742	mask = vrpiu_read(sc, PIUAMSK_REG_W);
743	mask &= 0xff8f; /* XXX */
744	vrpiu_write(sc, PIUAMSK_REG_W, mask);
745	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
746	/*
747	 * restart next A/D polling
748	 */
749	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
750	    vrpiu_start_powerstate, sc);
751}
752
753void
754vrpiu_calc_powerstate(struct vrpiu_softc *sc)
755{
756	extern void vrgiu_diff_io(void);
757	vrpiu_ad_disable(sc);
758	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
759	    sc->sc_battery.value[0],
760	    sc->sc_battery.value[1],
761	    sc->sc_battery.value[2]));
762	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
763	vrpiu_send_battery_event(sc);
764	/*
765	 * restart next A/D polling if change polling timming.
766	 */
767	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
768		callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
769		    vrpiu_start_powerstate, sc);
770	if (bootverbose)
771		vrgiu_diff_io();
772
773}
774
775static void
776vrpiu_power(int why, void *arg)
777{
778	struct vrpiu_softc *sc = arg;
779
780	switch (why) {
781	case PWR_STANDBY:
782	case PWR_SUSPEND:
783		break;
784	case PWR_RESUME:
785		callout_reset(&sc->sc_adpoll, hz,
786		    vrpiu_start_powerstate, sc);
787		break;
788	}
789}
790
791static void
792vrpiu_send_battery_event(struct vrpiu_softc *sc)
793{
794#ifdef VRPIU_ADHOC_BATTERY_EVENT
795	static int batteryhigh = 0;
796	static int batterylow = 0;
797	static int critical = 0;
798
799	if (sc->sc_battery_spec == NULL
800	    || sc->sc_battery_spec->main_port == -1)
801		return;
802
803	if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
804	    <= sc->sc_battery_spec->dc_critical) {
805		batteryhigh = 0;
806		config_hook_call(CONFIG_HOOK_PMEVENT,
807		    CONFIG_HOOK_PMEVENT_BATTERY,
808		    (void *)CONFIG_HOOK_BATT_CRITICAL);
809		batterylow = 3;
810		if (critical) {
811			config_hook_call(CONFIG_HOOK_PMEVENT,
812			    CONFIG_HOOK_PMEVENT_SUSPENDREQ,
813			    (void *)0);
814			critical = 0;
815			batterylow = 0;
816		}
817		critical++;
818	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
819	    <= sc->sc_battery_spec->dc_20p) {
820		batteryhigh = 0;
821		if (batterylow == 1)
822			config_hook_call(CONFIG_HOOK_PMEVENT,
823			    CONFIG_HOOK_PMEVENT_BATTERY,
824			    (void *)CONFIG_HOOK_BATT_20P);
825		config_hook_call(CONFIG_HOOK_PMEVENT,
826		    CONFIG_HOOK_PMEVENT_BATTERY,
827		    (void *)CONFIG_HOOK_BATT_LOW);
828		batterylow = 2;
829	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
830	    <= sc->sc_battery_spec->dc_50p) {
831		batteryhigh = 0;
832		if (batterylow == 0) {
833			batterylow = 1;
834			config_hook_call(CONFIG_HOOK_PMEVENT,
835			    CONFIG_HOOK_PMEVENT_BATTERY,
836			    (void *)CONFIG_HOOK_BATT_50P);
837		}
838	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
839	    >= sc->sc_battery_spec->ac_80p) {
840		batterylow = 0;
841		if (batteryhigh == 0) {
842			batteryhigh = 1;
843			config_hook_call(CONFIG_HOOK_PMEVENT,
844			    CONFIG_HOOK_PMEVENT_BATTERY,
845			    (void *)CONFIG_HOOK_BATT_80P);
846			config_hook_call(CONFIG_HOOK_PMEVENT,
847			    CONFIG_HOOK_PMEVENT_BATTERY,
848			    (void *)CONFIG_HOOK_BATT_HIGH);
849		}
850	}
851#else /* VRPIU_ADHOC_BATTERY_EVENT */
852	config_hook_call(CONFIG_HOOK_SET,
853	    CONFIG_HOOK_BATTERYVAL,
854	    (void *)&sc->sc_battery);
855#endif /* VRPIU_ADHOC_BATTERY_EVENT */
856}
857
858#ifdef DEBUG
859void
860vrpiu_dump_cntreg(unsigned int cnt)
861{
862	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
863	printf(" state=");
864	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
865		printf("CmdScan");
866	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
867		printf("IntervalNextScan");
868	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
869		printf("PenDataScan");
870	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
871		printf("WaitPenTouch");
872	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
873		printf("???");
874	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
875		printf("ADPortScan");
876	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
877		printf("Standby");
878	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
879		printf("Disable");
880	if (cnt & PIUCNT_PADATSTOP)
881		printf(" AutoStop");
882	if (cnt & PIUCNT_PADATSTART)
883		printf(" AutoStart");
884	if (cnt & PIUCNT_PADSCANSTOP)
885		printf(" Stop");
886	if (cnt & PIUCNT_PADSCANSTART)
887		printf(" Start");
888	if (cnt & PIUCNT_PADSCANTYPE)
889		printf(" ScanPressure");
890	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
891		printf(" A/D");
892	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
893		printf(" Coordinate");
894	if (cnt & PIUCNT_PIUSEQEN)
895		printf(" SeqEn");
896	if ((cnt & PIUCNT_PIUPWR) == 0)
897		printf(" PowerOff");
898	if ((cnt & PIUCNT_PADRST) == 0)
899		printf(" Reset");
900	printf("\n");
901}
902#endif
903