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
67 int 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 */
98 static int vrpiumatch(struct device *, struct cfdata *, void *);
99 static void vrpiuattach(struct device *, struct device *, void *);
100
101 static void vrpiu_write(struct vrpiu_softc *, int, unsigned short);
102 static u_short vrpiu_read(struct vrpiu_softc *, int);
103
104 static int vrpiu_intr(void *);
105 static void vrpiu_tp_intr(struct vrpiu_softc *);
106 static void vrpiu_ad_intr(struct vrpiu_softc *);
107 #ifdef DEBUG
108 static void vrpiu_dump_cntreg(unsigned int);
109 #endif
110
111 static int vrpiu_tp_enable(void *);
112 static int vrpiu_tp_ioctl(void *, u_long, caddr_t, int, struct proc *);
113 static void vrpiu_tp_disable(void *);
114 static void vrpiu_tp_up(struct vrpiu_softc *);
115 static void vrpiu_tp_timeout(void *);
116 int vrpiu_ad_enable(void *);
117 void vrpiu_ad_disable(void *);
118 static void vrpiu_start_powerstate(void *);
119 static void vrpiu_calc_powerstate(struct vrpiu_softc *);
120 static void vrpiu_send_battery_event(struct vrpiu_softc *);
121 static void vrpiu_power(int, void *);
122 static u_int scan_interval(u_int data);
123
124 /* mra is defined in mra.c */
125 int 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 */
131 struct cfattach vrpiu_ca = {
132 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
133 };
134
135 const struct wsmouse_accessops vrpiu_accessops = {
136 vrpiu_tp_enable,
137 vrpiu_tp_ioctl,
138 vrpiu_tp_disable,
139 };
140
141 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
142
143 /*
144 * function definitions
145 */
146 static inline void
147 vrpiu_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
153 static inline u_short
154 vrpiu_read(struct vrpiu_softc *sc, int port)
155 {
156
157 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port));
158 }
159
160 static int
161 vrpiumatch(struct device *parent, struct cfdata *cf, void *aux)
162 {
163
164 return (1);
165 }
166
167 static void
168 vrpiuattach(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 */
296 static u_int
297 scan_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
315 int
316 vrpiu_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
364 void
365 vrpiu_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
385 int
386 vrpiu_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
436 void
437 vrpiu_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
457 int
458 vrpiu_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 */
512 void
513 vrpiu_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 */
553 void
554 vrpiu_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
686 void
687 vrpiu_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 */
705 void
706 vrpiu_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 */
724 int
725 vrpiu_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
735 void
736 vrpiu_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
753 void
754 vrpiu_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
775 static void
776 vrpiu_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
791 static void
792 vrpiu_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
859 void
860 vrpiu_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