vrpiu.c revision 1.9 1 /* $NetBSD: vrpiu.c,v 1.9 2001/01/20 12:24:22 takemura 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 <hpcmips/hpcmips/machdep.h>
51 #include <hpcmips/dev/tpcalibvar.h>
52
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
63 int 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
78 #define TP_INTR (PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
79 #define AD_INTR (PIUINT_PADADPINTR)
80
81 /*
82 * data types
83 */
84 /* struct vrpiu_softc is defined in vrpiuvar.h */
85
86 /*
87 * function prototypes
88 */
89 static int vrpiumatch __P((struct device *, struct cfdata *, void *));
90 static void vrpiuattach __P((struct device *, struct device *, void *));
91
92 static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
93 static u_short vrpiu_read __P((struct vrpiu_softc *, int));
94
95 static int vrpiu_intr __P((void *));
96 static void vrpiu_tp_intr __P((struct vrpiu_softc *));
97 static void vrpiu_ad_intr __P((struct vrpiu_softc *));
98 #ifdef DEBUG
99 static void vrpiu_dump_cntreg __P((unsigned int cmd));
100 #endif
101
102 static int vrpiu_tp_enable __P((void *));
103 static int vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
104 static void vrpiu_tp_disable __P((void *));
105 int vrpiu_ad_enable __P((void *));
106 void vrpiu_ad_disable __P((void *));
107 static void vrpiu_start_powerstate __P((void *));
108 static void vrpiu_calc_powerstate __P((struct vrpiu_softc *));
109 static void vrpiu_power __P((int, void *));
110 static u_int scan_interval __P((u_int data));
111
112 /* mra is defined in mra.c */
113 int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
114 int n, int scale, int *a, int *b, int *c));
115
116 /*
117 * static or global variables
118 */
119 struct cfattach vrpiu_ca = {
120 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
121 };
122
123 const struct wsmouse_accessops vrpiu_accessops = {
124 vrpiu_tp_enable,
125 vrpiu_tp_ioctl,
126 vrpiu_tp_disable,
127 };
128
129 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
130
131 /*
132 * function definitions
133 */
134 static inline void
135 vrpiu_write(sc, port, val)
136 struct vrpiu_softc *sc;
137 int port;
138 unsigned short val;
139 {
140 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
141 }
142
143 static inline u_short
144 vrpiu_read(sc, port)
145 struct vrpiu_softc *sc;
146 int port;
147 {
148 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
149 }
150
151 static int
152 vrpiumatch(parent, cf, aux)
153 struct device *parent;
154 struct cfdata *cf;
155 void *aux;
156 {
157 return 1;
158 }
159
160 static void
161 vrpiuattach(parent, self, aux)
162 struct device *parent;
163 struct device *self;
164 void *aux;
165 {
166 struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
167 struct vrip_attach_args *va = aux;
168 struct wsmousedev_attach_args wsmaa;
169
170 bus_space_tag_t iot = va->va_iot;
171 bus_space_handle_t ioh;
172
173 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
174 printf(": can't map bus space\n");
175 return;
176 }
177
178 sc->sc_iot = iot;
179 sc->sc_ioh = ioh;
180 sc->sc_vrip = va->va_vc;
181
182 sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
183
184 /*
185 * disable device until vrpiu_enable called
186 */
187 sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
188
189 tpcalib_init(&sc->sc_tpcalib);
190 #if 1
191 /*
192 * XXX, calibrate parameters
193 */
194 {
195 int i;
196 static const struct {
197 platid_mask_t *mask;
198 struct wsmouse_calibcoords coords;
199 } calibrations[] = {
200 { &platid_mask_MACH_NEC_MCR_700A,
201 { 0, 0, 799, 599,
202 4,
203 { { 115, 80, 0, 0 },
204 { 115, 966, 0, 599 },
205 { 912, 80, 799, 0 },
206 { 912, 966, 799, 599 } } } },
207
208 { NULL, /* samples got on my MC-R500 */
209 { 0, 0, 639, 239,
210 5,
211 { { 502, 486, 320, 120 },
212 { 55, 109, 0, 0 },
213 { 54, 913, 0, 239 },
214 { 973, 924, 639, 239 },
215 { 975, 123, 639, 0 } } } },
216 };
217 for (i = 0; ; i++) {
218 if (calibrations[i].mask == NULL
219 || platid_match(&platid, calibrations[i].mask))
220 break;
221 }
222 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
223 (caddr_t)&calibrations[i].coords, 0, 0);
224 }
225 #endif
226
227 /* install interrupt handler and enable interrupt */
228 if (!(sc->sc_handler =
229 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
230 vrpiu_intr, sc))) {
231 printf (": can't map interrupt line.\n");
232 return;
233 }
234
235 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */
236 vrpiu_tp_disable(sc);
237
238 printf("\n");
239
240 wsmaa.accessops = &vrpiu_accessops;
241 wsmaa.accesscookie = sc;
242
243 /*
244 * attach the wsmouse
245 */
246 sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
247
248 /*
249 * power management events
250 */
251 sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
252
253 /*
254 * init A/D port polling.
255 */
256 sc->sc_battery.n_values = 3;
257 sc->sc_battery.value[0] = -1;
258 sc->sc_battery.value[1] = -1;
259 sc->sc_battery.value[2] = -1;
260 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
261 callout_init(&sc->sc_adpoll);
262 callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
263 }
264
265 /*
266 * calculate interval value
267 * input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
268 * output: value for PIUSIVL_REG
269 */
270 static u_int
271 scan_interval(u_int data)
272 {
273 int scale;
274
275 if (data < WSMOUSE_RES_MIN)
276 data = WSMOUSE_RES_MIN;
277
278 if (WSMOUSE_RES_MAX < data)
279 data = WSMOUSE_RES_MAX;
280
281 scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
282 data += WSMOUSE_RES_MIN;
283
284 return PIUSIVL_SCANINTVAL_MIN +
285 (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
286 (scale - data) / scale;
287 }
288
289 int
290 vrpiu_ad_enable(v)
291 void *v;
292 {
293 struct vrpiu_softc *sc = v;
294 int s;
295 unsigned int cnt;
296
297 DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
298 __FILE__, __LINE__, sc->sc_interval));
299 if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
300 return EBUSY;
301
302 /* supply clock to PIU */
303 __vrcmu_supply(CMUMSKPIU, 1);
304
305 /* set scan interval */
306 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
307
308 s = spltty();
309
310 /* clear interrupt status */
311 vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
312
313 /* Disable -> Standby */
314 cnt = PIUCNT_PIUPWR |
315 PIUCNT_PIUMODE_COORDINATE |
316 PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
317 vrpiu_write(sc, PIUCNT_REG_W, cnt);
318
319 /* Level2 interrupt register setting */
320 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
321
322 /* save pen status, touch or release */
323 cnt = vrpiu_read(sc, PIUCNT_REG_W);
324
325 /*
326 * Enable scan sequencer operation
327 * Standby -> WaitPenTouch
328 */
329 cnt |= PIUCNT_PIUSEQEN;
330 vrpiu_write(sc, PIUCNT_REG_W, cnt);
331
332 sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
333
334 splx(s);
335
336 return 0;
337 }
338
339 void
340 vrpiu_ad_disable(v)
341 void *v;
342 {
343 struct vrpiu_softc *sc = v;
344
345 DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
346
347 /* Set level2 interrupt register to mask interrupts */
348 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
349
350 sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
351
352 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
353 /* Disable scan sequencer operation and power off */
354 vrpiu_write(sc, PIUCNT_REG_W, 0);
355
356 /* mask clock to PIU */
357 __vrcmu_supply(CMUMSKPIU, 1);
358 }
359 }
360
361 int
362 vrpiu_tp_enable(v)
363 void *v;
364 {
365 struct vrpiu_softc *sc = v;
366 int s;
367 unsigned int cnt;
368
369 DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
370 __FILE__, __LINE__, sc->sc_interval));
371 if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
372 return EBUSY;
373
374 /* supply clock to PIU */
375 __vrcmu_supply(CMUMSKPIU, 1);
376
377 /* set scan interval */
378 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
379
380 s = spltty();
381
382 /* clear interrupt status */
383 vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
384
385 /* Disable -> Standby */
386 cnt = PIUCNT_PIUPWR |
387 PIUCNT_PIUMODE_COORDINATE |
388 PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
389 vrpiu_write(sc, PIUCNT_REG_W, cnt);
390
391 /* Level2 interrupt register setting */
392 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
393
394 /* save pen status, touch or release */
395 cnt = vrpiu_read(sc, PIUCNT_REG_W);
396
397 /*
398 * Enable scan sequencer operation
399 * Standby -> WaitPenTouch
400 */
401 cnt |= PIUCNT_PIUSEQEN;
402 vrpiu_write(sc, PIUCNT_REG_W, cnt);
403
404 /* transit status DISABLE -> TOUCH or RELEASE */
405 sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
406 VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
407
408 splx(s);
409
410 return 0;
411 }
412
413 void
414 vrpiu_tp_disable(v)
415 void *v;
416 {
417 struct vrpiu_softc *sc = v;
418
419 DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
420
421 /* Set level2 interrupt register to mask interrupts */
422 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
423
424 sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
425
426 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
427 /* Disable scan sequencer operation and power off */
428 vrpiu_write(sc, PIUCNT_REG_W, 0);
429
430 /* mask clock to PIU */
431 __vrcmu_supply(CMUMSKPIU, 1);
432 }
433 }
434
435 int
436 vrpiu_tp_ioctl(v, cmd, data, flag, p)
437 void *v;
438 u_long cmd;
439 caddr_t data;
440 int flag;
441 struct proc *p;
442 {
443 struct vrpiu_softc *sc = v;
444
445 DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
446
447 switch (cmd) {
448 case WSMOUSEIO_GTYPE:
449 *(u_int *)data = WSMOUSE_TYPE_TPANEL;
450 break;
451
452 case WSMOUSEIO_SRES:
453 {
454 int tp_enable;
455 int ad_enable;
456
457 tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
458 ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
459
460 if (tp_enable)
461 vrpiu_tp_disable(sc);
462 if (ad_enable)
463 vrpiu_ad_disable(sc);
464
465 sc->sc_interval = scan_interval(*(u_int *)data);
466 DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
467 __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
468
469 if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
470 sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
471
472 if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
473 sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
474
475 if (tp_enable)
476 vrpiu_tp_enable(sc);
477 if (ad_enable)
478 vrpiu_ad_enable(sc);
479 }
480 break;
481
482 case WSMOUSEIO_SCALIBCOORDS:
483 case WSMOUSEIO_GCALIBCOORDS:
484 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
485
486 default:
487 return (-1);
488 }
489 return (0);
490 }
491
492 /*
493 * PIU AD interrupt handler.
494 */
495 void
496 vrpiu_ad_intr(sc)
497 struct vrpiu_softc *sc;
498 {
499 unsigned int i;
500 unsigned int intrstat;
501
502 intrstat = vrpiu_read(sc, PIUINT_REG_W);
503
504 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
505 /*
506 * the device isn't enabled. just clear interrupt.
507 */
508 vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
509 return;
510 }
511
512 if (intrstat & PIUINT_PADADPINTR) {
513 sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
514 sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
515 sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
516 }
517
518 if (intrstat & PIUINT_PADADPINTR) {
519 for (i = 0; i < 3; i++) {
520 if (sc->sc_battery.value[i] & PIUAB_VALID)
521 sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
522 else
523 sc->sc_battery.value[i] = 0;
524 }
525 vrpiu_calc_powerstate(sc);
526 }
527 vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
528
529 return;
530 }
531 /*
532 * PIU TP interrupt handler.
533 */
534 void
535 vrpiu_tp_intr(sc)
536 struct vrpiu_softc *sc;
537 {
538 unsigned int cnt, i;
539 unsigned int intrstat, page;
540 int tpx0, tpx1, tpy0, tpy1;
541 int x, y, xraw, yraw;
542
543 intrstat = vrpiu_read(sc, PIUINT_REG_W);
544
545 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
546 /*
547 * the device isn't enabled. just clear interrupt.
548 */
549 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
550 return;
551 }
552
553 page = (intrstat & PIUINT_OVP) ? 1 : 0;
554 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
555 tpx0 = vrpiu_read(sc, PIUPB(page, 0));
556 tpx1 = vrpiu_read(sc, PIUPB(page, 1));
557 tpy0 = vrpiu_read(sc, PIUPB(page, 2));
558 tpy1 = vrpiu_read(sc, PIUPB(page, 3));
559 }
560
561 if (intrstat & PIUINT_PADDLOSTINTR) {
562 page = page ? 0 : 1;
563 for (i = 0; i < 4; i++)
564 vrpiu_read(sc, PIUPB(page, i));
565 }
566
567 cnt = vrpiu_read(sc, PIUCNT_REG_W);
568 #ifdef DEBUG
569 if (vrpiu_debug)
570 vrpiu_dump_cntreg(cnt);
571 #endif
572
573 /* clear interrupt status */
574 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
575
576 #if 0
577 DPRINTF(("vrpiu_intr: OVP=%d", page));
578 if (intrstat & PIUINT_PADCMDINTR)
579 DPRINTF((" CMD"));
580 if (intrstat & PIUINT_PADADPINTR)
581 DPRINTF((" A/D"));
582 if (intrstat & PIUINT_PADPAGE1INTR)
583 DPRINTF((" PAGE1"));
584 if (intrstat & PIUINT_PADPAGE0INTR)
585 DPRINTF((" PAGE0"));
586 if (intrstat & PIUINT_PADDLOSTINTR)
587 DPRINTF((" DLOST"));
588 if (intrstat & PIUINT_PENCHGINTR)
589 DPRINTF((" PENCHG"));
590 DPRINTF(("\n"));
591 #endif
592 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
593 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
594 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
595 printf("vrpiu: internal error, data is not valid!\n");
596 } else {
597 tpx0 &= PIUPB_PADDATA_MASK;
598 tpx1 &= PIUPB_PADDATA_MASK;
599 tpy0 &= PIUPB_PADDATA_MASK;
600 tpy1 &= PIUPB_PADDATA_MASK;
601 #define ISVALID(n, c, m) ((c) - (m) < (n) && (n) < (c) + (m))
602 if (ISVALID(tpx0 + tpx1, 1024, 200) &&
603 ISVALID(tpx0 + tpx1, 1024, 200)) {
604 #if 0
605 DPRINTF(("%04x %04x %04x %04x\n",
606 tpx0, tpx1, tpy0, tpy1));
607 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
608 tpx0 + tpx1, tpy0 + tpy1));
609 #endif
610 xraw = tpy1 * 1024 / (tpy0 + tpy1);
611 yraw = tpx1 * 1024 / (tpx0 + tpx1);
612 DPRINTF(("%3d %3d", xraw, yraw));
613
614 tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
615
616 DPRINTF(("->%4d %4d", x, y));
617 wsmouse_input(sc->sc_wsmousedev,
618 (cnt & PIUCNT_PENSTC) ? 1 : 0,
619 x, /* x */
620 y, /* y */
621 0, /* z */
622 WSMOUSE_INPUT_ABSOLUTE_X |
623 WSMOUSE_INPUT_ABSOLUTE_Y);
624 DPRINTF(("\n"));
625 }
626 }
627 }
628
629 if (cnt & PIUCNT_PENSTC) {
630 if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
631 /*
632 * pen touch
633 */
634 DPRINTF(("PEN TOUCH\n"));
635 sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
636 /*
637 * We should not report button down event while
638 * we don't know where it occur.
639 */
640 }
641 } else {
642 if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
643 /*
644 * pen release
645 */
646 DPRINTF(("RELEASE\n"));
647 sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
648 /* button 0 UP */
649 wsmouse_input(sc->sc_wsmousedev,
650 0,
651 0, 0, 0, 0);
652 }
653 }
654
655 if (intrstat & PIUINT_PADDLOSTINTR) {
656 cnt |= PIUCNT_PIUSEQEN;
657 vrpiu_write(sc, PIUCNT_REG_W, cnt);
658 }
659
660 return;
661 }
662
663 /*
664 * PIU interrupt handler.
665 */
666 int
667 vrpiu_intr(arg)
668 void *arg;
669 {
670 struct vrpiu_softc *sc = arg;
671
672 vrpiu_ad_intr(sc);
673 vrpiu_tp_intr(sc);
674
675 return 0;
676 }
677
678 void
679 vrpiu_start_powerstate(v)
680 void *v;
681 {
682 int mask;
683 struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
684
685 vrpiu_ad_enable(sc);
686 mask = vrpiu_read(sc, PIUAMSK_REG_W);
687 mask &= 0xff8f; /* XXX */
688 vrpiu_write(sc, PIUAMSK_REG_W, mask);
689 vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
690 /*
691 * restart next A/D polling
692 */
693 callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
694 vrpiu_start_powerstate, sc);
695 }
696
697 void
698 vrpiu_calc_powerstate(sc)
699 struct vrpiu_softc *sc;
700 {
701 extern void vrgiu_diff_io __P((void));
702 vrpiu_ad_disable(sc);
703 VPRINTF(("vrpiu:AD: %d, %d, %d\n",
704 sc->sc_battery.value[0],
705 sc->sc_battery.value[1],
706 sc->sc_battery.value[2]));
707 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
708 #ifdef notyet
709 config_hook_call(CONFIG_HOOK_SET,
710 CONFIG_HOOK_BATTERYVAL,
711 (void *)&sc->sc_battery);
712 #endif /* notyet */
713 /*
714 * restart next A/D polling if change polling timming.
715 */
716 if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
717 callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
718 vrpiu_start_powerstate, sc);
719 if (bootverbose)
720 vrgiu_diff_io();
721
722 }
723
724 static void
725 vrpiu_power(why, arg)
726 int why;
727 void *arg;
728 {
729 struct vrpiu_softc *sc = arg;
730
731 switch (why) {
732 case PWR_STANDBY:
733 case PWR_SUSPEND:
734 break;
735 case PWR_RESUME:
736 callout_reset(&sc->sc_adpoll, hz,
737 vrpiu_start_powerstate, sc);
738 break;
739 }
740 }
741
742 #ifdef DEBUG
743 void
744 vrpiu_dump_cntreg(cnt)
745 unsigned int cnt;
746 {
747 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
748 printf(" state=");
749 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
750 printf("CmdScan");
751 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
752 printf("IntervalNextScan");
753 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
754 printf("PenDataScan");
755 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
756 printf("WaitPenTouch");
757 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
758 printf("???");
759 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
760 printf("ADPortScan");
761 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
762 printf("Standby");
763 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
764 printf("Disable");
765 if (cnt & PIUCNT_PADATSTOP)
766 printf(" AutoStop");
767 if (cnt & PIUCNT_PADATSTART)
768 printf(" AutoStart");
769 if (cnt & PIUCNT_PADSCANSTOP)
770 printf(" Stop");
771 if (cnt & PIUCNT_PADSCANSTART)
772 printf(" Start");
773 if (cnt & PIUCNT_PADSCANTYPE)
774 printf(" ScanPressure");
775 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
776 printf(" A/D");
777 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
778 printf(" Coordinate");
779 if (cnt & PIUCNT_PIUSEQEN)
780 printf(" SeqEn");
781 if ((cnt & PIUCNT_PIUPWR) == 0)
782 printf(" PowerOff");
783 if ((cnt & PIUCNT_PADRST) == 0)
784 printf(" Reset");
785 printf("\n");
786 }
787 #endif
788