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