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
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 #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 */
90 static int vrpiumatch __P((struct device *, struct cfdata *, void *));
91 static void vrpiuattach __P((struct device *, struct device *, void *));
92
93 static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
94 static u_short vrpiu_read __P((struct vrpiu_softc *, int));
95
96 static int vrpiu_intr __P((void *));
97 static void vrpiu_tp_intr __P((struct vrpiu_softc *));
98 static void vrpiu_ad_intr __P((struct vrpiu_softc *));
99 #ifdef DEBUG
100 static void vrpiu_dump_cntreg __P((unsigned int cmd));
101 #endif
102
103 static int vrpiu_tp_enable __P((void *));
104 static int vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
105 static void vrpiu_tp_disable __P((void *));
106 static void vrpiu_tp_up __P((struct vrpiu_softc *));
107 static void vrpiu_tp_timeout __P((void *));
108 int vrpiu_ad_enable __P((void *));
109 void vrpiu_ad_disable __P((void *));
110 static void vrpiu_start_powerstate __P((void *));
111 static void vrpiu_calc_powerstate __P((struct vrpiu_softc *));
112 static void vrpiu_power __P((int, void *));
113 static u_int scan_interval __P((u_int data));
114
115 /* mra is defined in mra.c */
116 int 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 */
122 struct cfattach vrpiu_ca = {
123 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
124 };
125
126 const struct wsmouse_accessops vrpiu_accessops = {
127 vrpiu_tp_enable,
128 vrpiu_tp_ioctl,
129 vrpiu_tp_disable,
130 };
131
132 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
133
134 /*
135 * function definitions
136 */
137 static inline void
138 vrpiu_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
146 static inline u_short
147 vrpiu_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
154 static int
155 vrpiumatch(parent, cf, aux)
156 struct device *parent;
157 struct cfdata *cf;
158 void *aux;
159 {
160 return 1;
161 }
162
163 static void
164 vrpiuattach(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 */
277 static u_int
278 scan_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
296 int
297 vrpiu_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
346 void
347 vrpiu_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
368 int
369 vrpiu_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
420 void
421 vrpiu_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
442 int
443 vrpiu_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 */
502 void
503 vrpiu_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 */
541 void
542 vrpiu_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
673 void
674 vrpiu_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 */
693 void
694 vrpiu_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 */
713 int
714 vrpiu_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
725 void
726 vrpiu_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
744 void
745 vrpiu_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
771 static void
772 vrpiu_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
790 void
791 vrpiu_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