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