1 /* $NetBSD: vrpiu.c,v 1.39.10.1 2007/10/03 19:23:26 garbled Exp $ */
4 * Copyright (c) 1999-2003 TAKEMURA Shin All rights reserved.
5 * Copyright (c) 2000-2001 SATO Kazumi, All rights reserved.
6 * Copyright (c) 1999-2001 PocketBSD Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
32 * A/D polling part written by SATO Kazumi.
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: vrpiu.c,v 1.39.10.1 2007/10/03 19:23:26 garbled Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/kernel.h>
42 #include <sys/callout.h>
43 #include <sys/boot_flag.h>
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wsmousevar.h>
48 #include <machine/bus.h>
49 #include <machine/platid.h>
50 #include <machine/platid_mask.h>
51 #include <machine/config_hook.h>
53 #include <dev/hpc/hpctpanelvar.h>
55 #include <dev/hpc/hpcbatteryvar.h>
56 #include <dev/hpc/hpcbatterytable.h>
58 #include <hpcmips/vr/vrcpudef.h>
59 #include <hpcmips/vr/vripif.h>
60 #include <hpcmips/vr/cmureg.h>
61 #include <hpcmips/vr/vrpiuvar.h>
62 #define PIUB_REG_OFFSSET 0
63 #include <hpcmips/vr/vrpiureg.h>
66 * contant and macro definitions
71 #define DPRINTF(arg) if (vrpiu_debug) printf arg;
72 #define VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
75 #define VPRINTF(arg) if (bootverbose) printf arg;
78 #ifndef VRPIU_NO_ADHOC_BATTERY_EVENT
79 #define VRPIU_ADHOC_BATTERY_EVENT /* currently... */
80 #endif /* VRPIU_NO_ADHOC_BATTERY_EVENT */
82 #ifndef VRPIU_AD_POLL_INTERVAL
83 #define VRPIU_AD_POLL_INTERVAL 60 /* interval is 60 sec */
84 #endif /* VRPIU_AD_POLL_INTERTVAL */
86 #define PIUSIVL_SCANINTVAL_MIN 333 /* 10msec */
87 #define PIUSIVL_SCANINTVAL_MAX PIUSIVL_SCANINTVAL_MASK /* 60msec */
88 #define VRPIU_TP_SCAN_TIMEOUT (hz/10) /* timeout is 100msec */
90 #define TP_INTR (PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
91 #define AD_INTR (PIUINT_PADADPINTR)
96 /* struct vrpiu_softc is defined in vrpiuvar.h */
101 static int vrpiumatch(struct device
*, struct cfdata
*, void *);
102 static void vrpiuattach(struct device
*, struct device
*, void *);
103 static void vrc4173piuattach(struct device
*, struct device
*, void *);
104 static void vrpiu_init(struct vrpiu_softc
*, void *);
106 static void vrpiu_write(struct vrpiu_softc
*, int, unsigned short);
107 static u_short
vrpiu_read(struct vrpiu_softc
*, int);
109 static int vrpiu_intr(void *);
110 static void vrpiu_tp_intr(struct vrpiu_softc
*);
111 static void vrpiu_ad_intr(struct vrpiu_softc
*);
113 static void vrpiu_dump_cntreg(unsigned int);
116 static int vrpiu_tp_enable(void *);
117 static int vrpiu_tp_ioctl(void *, u_long
, void *, int, struct lwp
*);
118 static void vrpiu_tp_disable(void *);
119 static void vrpiu_tp_up(struct vrpiu_softc
*);
120 static void vrpiu_tp_timeout(void *);
121 int vrpiu_ad_enable(void *);
122 void vrpiu_ad_disable(void *);
123 static void vrpiu_start_powerstate(void *);
124 static void vrpiu_calc_powerstate(struct vrpiu_softc
*);
125 static void vrpiu_send_battery_event(struct vrpiu_softc
*);
126 static void vrpiu_power(int, void *);
127 static u_int
scan_interval(u_int data
);
129 /* mra is defined in mra.c */
130 int mra_Y_AX1_BX2_C(int *y
, int ys
, int *x1
, int x1s
, int *x2
, int x2s
,
131 int n
, int scale
, int *a
, int *b
, int *c
);
134 * static or global variables
136 CFATTACH_DECL(vrpiu
, sizeof(struct vrpiu_softc
),
137 vrpiumatch
, vrpiuattach
, NULL
, NULL
);
138 CFATTACH_DECL(vrc4173piu
, sizeof(struct vrpiu_softc
),
139 vrpiumatch
, vrc4173piuattach
, NULL
, NULL
);
141 const struct wsmouse_accessops vrpiu_accessops
= {
147 int vrpiu_ad_poll_interval
= VRPIU_AD_POLL_INTERVAL
;
150 * function definitions
153 vrpiu_write(struct vrpiu_softc
*sc
, int port
, unsigned short val
)
156 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, port
, val
);
159 static inline u_short
160 vrpiu_read(struct vrpiu_softc
*sc
, int port
)
163 return (bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, port
));
166 static inline u_short
167 vrpiu_buf_read(struct vrpiu_softc
*sc
, int port
)
170 return (bus_space_read_2(sc
->sc_iot
, sc
->sc_buf_ioh
, port
));
174 vrpiumatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
181 vrpiuattach(struct device
*parent
, struct device
*self
, void *aux
)
183 struct vrpiu_softc
*sc
= (struct vrpiu_softc
*)self
;
185 sc
->sc_ab_paddata_mask
= PIUAB_PADDATA_MASK
;
186 sc
->sc_pb_paddata_mask
= PIUPB_PADDATA_MASK
;
187 sc
->sc_pb_paddata_max
= PIUPB_PADDATA_MAX
;
192 vrc4173piuattach(struct device
*parent
, struct device
*self
, void *aux
)
194 struct vrpiu_softc
*sc
= (struct vrpiu_softc
*)self
;
196 sc
->sc_ab_paddata_mask
= VRC4173PIUAB_PADDATA_MASK
;
197 sc
->sc_pb_paddata_mask
= VRC4173PIUPB_PADDATA_MASK
;
198 sc
->sc_pb_paddata_max
= VRC4173PIUPB_PADDATA_MAX
;
203 vrpiu_init(struct vrpiu_softc
*sc
, void *aux
)
205 struct vrip_attach_args
*va
= aux
;
206 struct wsmousedev_attach_args wsmaa
;
208 bus_space_tag_t iot
= va
->va_iot
;
209 struct platid_data
*p
;
211 if (va
->va_parent_ioh
!= 0)
212 res
= bus_space_subregion(iot
, va
->va_parent_ioh
, va
->va_addr
,
213 va
->va_size
, &sc
->sc_ioh
);
215 res
= bus_space_map(iot
, va
->va_addr
, va
->va_size
, 0,
218 printf(": can't map bus space\n");
221 if (va
->va_parent_ioh
!= 0)
222 res
= bus_space_subregion(iot
, va
->va_parent_ioh
, va
->va_addr2
,
223 va
->va_size2
, &sc
->sc_buf_ioh
);
225 res
= bus_space_map(iot
, va
->va_addr2
, va
->va_size2
, 0,
228 printf(": can't map second bus space\n");
233 sc
->sc_unit
= va
->va_unit
;
234 sc
->sc_vrip
= va
->va_vc
;
236 sc
->sc_interval
= scan_interval(WSMOUSE_RES_DEFAULT
);
237 if ((p
= platid_search_data(&platid
, hpcbattery_parameters
)) == NULL
)
238 sc
->sc_battery_spec
= NULL
;
240 sc
->sc_battery_spec
= p
->data
;
243 * disable device until vrpiu_enable called
245 sc
->sc_tpstat
= VRPIU_TP_STAT_DISABLE
;
247 /* initialize touch panel timeout structure */
248 callout_init(&sc
->sc_tptimeout
, 0);
250 /* initialize calibration context */
251 tpcalib_init(&sc
->sc_tpcalib
);
254 * XXX, calibrate parameters
258 static const struct {
260 struct wsmouse_calibcoords coords
;
262 { &platid_mask_MACH_NEC_MCR_700
,
266 { 115, 966, 0, 599 },
268 { 912, 966, 799, 599 } } } },
269 { &platid_mask_MACH_NEC_MCR_700A
,
273 { 115, 966, 0, 599 },
275 { 912, 966, 799, 599 } } } },
276 { &platid_mask_MACH_NEC_MCR_730
,
280 { 115, 966, 0, 599 },
282 { 912, 966, 799, 599 } } } },
283 { &platid_mask_MACH_NEC_MCR_730A
,
287 { 115, 966, 0, 599 },
289 { 912, 966, 799, 599 } } } },
290 { NULL
, /* samples got on my MC-R500 */
293 { { 502, 486, 320, 120 },
296 { 973, 924, 639, 239 },
297 { 975, 123, 639, 0 } } } },
300 if (calibrations
[i
].mask
== NULL
301 || platid_match(&platid
, calibrations
[i
].mask
))
304 tpcalib_ioctl(&sc
->sc_tpcalib
, WSMOUSEIO_SCALIBCOORDS
,
305 (void *)__UNCONST(&calibrations
[i
].coords
), 0, 0);
309 /* install interrupt handler and enable interrupt */
310 if (!(sc
->sc_handler
=
311 vrip_intr_establish(sc
->sc_vrip
, sc
->sc_unit
, 0, IPL_TTY
,
313 printf (": can't map interrupt line.\n");
317 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */
318 vrpiu_tp_disable(sc
);
322 wsmaa
.accessops
= &vrpiu_accessops
;
323 wsmaa
.accesscookie
= sc
;
328 sc
->sc_wsmousedev
= config_found(&sc
->sc_dev
, &wsmaa
, wsmousedevprint
);
331 * power management events
333 sc
->sc_power_hook
= powerhook_establish(sc
->sc_dev
.dv_xname
,
335 if (sc
->sc_power_hook
== NULL
)
336 aprint_error("%s: WARNING: couldn't establish powerhook\n",
337 sc
->sc_dev
.dv_xname
);
340 * init A/D port polling.
342 sc
->sc_battery
.n_values
= 3;
343 sc
->sc_battery
.value
[0] = -1;
344 sc
->sc_battery
.value
[1] = -1;
345 sc
->sc_battery
.value
[2] = -1;
346 sc
->sc_battery
.nextpoll
= hz
*vrpiu_ad_poll_interval
;
347 callout_init(&sc
->sc_adpoll
, 0);
348 callout_reset(&sc
->sc_adpoll
, hz
, vrpiu_start_powerstate
, sc
);
352 * calculate interval value
353 * input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
354 * output: value for PIUSIVL_REG
357 scan_interval(u_int data
)
361 if (data
< WSMOUSE_RES_MIN
)
362 data
= WSMOUSE_RES_MIN
;
364 if (WSMOUSE_RES_MAX
< data
)
365 data
= WSMOUSE_RES_MAX
;
367 scale
= WSMOUSE_RES_MAX
- WSMOUSE_RES_MIN
;
368 data
+= WSMOUSE_RES_MIN
;
370 return PIUSIVL_SCANINTVAL_MIN
+
371 (PIUSIVL_SCANINTVAL_MAX
- PIUSIVL_SCANINTVAL_MIN
) *
372 (scale
- data
) / scale
;
376 vrpiu_ad_enable(void *v
)
378 struct vrpiu_softc
*sc
= v
;
382 DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
383 __FILE__
, __LINE__
, sc
->sc_interval
));
384 if (sc
->sc_adstat
!= VRPIU_AD_STAT_DISABLE
)
387 /* supply clock to PIU */
388 vrip_power(sc
->sc_vrip
, sc
->sc_unit
, 1);
390 /* set scan interval */
391 vrpiu_write(sc
, PIUSIVL_REG_W
, sc
->sc_interval
);
395 /* clear interrupt status */
396 vrpiu_write(sc
, PIUINT_REG_W
, AD_INTR
);
398 /* Disable -> Standby */
399 cnt
= PIUCNT_PIUPWR
|
400 PIUCNT_PIUMODE_COORDINATE
|
401 PIUCNT_PADATSTART
| PIUCNT_PADATSTOP
;
402 vrpiu_write(sc
, PIUCNT_REG_W
, cnt
);
404 /* Level2 interrupt register setting */
405 vrip_intr_setmask2(sc
->sc_vrip
, sc
->sc_handler
, AD_INTR
, 1);
407 /* save pen status, touch or release */
408 cnt
= vrpiu_read(sc
, PIUCNT_REG_W
);
411 * Enable scan sequencer operation
412 * Standby -> WaitPenTouch
414 cnt
|= PIUCNT_PIUSEQEN
;
415 vrpiu_write(sc
, PIUCNT_REG_W
, cnt
);
417 sc
->sc_adstat
= VRPIU_AD_STAT_ENABLE
;
425 vrpiu_ad_disable(void *v
)
427 struct vrpiu_softc
*sc
= v
;
429 DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__
, __LINE__
));
431 /* Set level2 interrupt register to mask interrupts */
432 vrip_intr_setmask2(sc
->sc_vrip
, sc
->sc_handler
, AD_INTR
, 0);
434 sc
->sc_adstat
= VRPIU_AD_STAT_DISABLE
;
436 if (sc
->sc_tpstat
== VRPIU_TP_STAT_DISABLE
){
437 /* Disable scan sequencer operation and power off */
438 vrpiu_write(sc
, PIUCNT_REG_W
, 0);
440 /* mask clock to PIU */
441 vrip_power(sc
->sc_vrip
, sc
->sc_unit
, 0);
446 vrpiu_tp_enable(void *v
)
448 struct vrpiu_softc
*sc
= v
;
452 DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
453 __FILE__
, __LINE__
, sc
->sc_interval
));
454 if (sc
->sc_tpstat
!= VRPIU_TP_STAT_DISABLE
)
457 /* supply clock to PIU */
458 vrip_power(sc
->sc_vrip
, sc
->sc_unit
, 1);
460 /* set scan interval */
461 vrpiu_write(sc
, PIUSIVL_REG_W
, sc
->sc_interval
);
465 /* clear interrupt status */
466 vrpiu_write(sc
, PIUINT_REG_W
, TP_INTR
);
468 /* Disable -> Standby */
469 cnt
= PIUCNT_PIUPWR
|
470 PIUCNT_PIUMODE_COORDINATE
|
471 PIUCNT_PADATSTART
| PIUCNT_PADATSTOP
;
472 vrpiu_write(sc
, PIUCNT_REG_W
, cnt
);
474 /* Level2 interrupt register setting */
475 vrip_intr_setmask2(sc
->sc_vrip
, sc
->sc_handler
, TP_INTR
, 1);
477 /* save pen status, touch or release */
478 cnt
= vrpiu_read(sc
, PIUCNT_REG_W
);
481 * Enable scan sequencer operation
482 * Standby -> WaitPenTouch
484 cnt
|= PIUCNT_PIUSEQEN
;
485 vrpiu_write(sc
, PIUCNT_REG_W
, cnt
);
487 /* transit status DISABLE -> TOUCH or RELEASE */
488 sc
->sc_tpstat
= (cnt
& PIUCNT_PENSTC
) ?
489 VRPIU_TP_STAT_TOUCH
: VRPIU_TP_STAT_RELEASE
;
497 vrpiu_tp_disable(void *v
)
499 struct vrpiu_softc
*sc
= v
;
501 DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__
, __LINE__
));
503 /* Set level2 interrupt register to mask interrupts */
504 vrip_intr_setmask2(sc
->sc_vrip
, sc
->sc_handler
, TP_INTR
, 0);
506 sc
->sc_tpstat
= VRPIU_TP_STAT_DISABLE
;
508 if (sc
->sc_adstat
== VRPIU_AD_STAT_DISABLE
){
509 /* Disable scan sequencer operation and power off */
510 vrpiu_write(sc
, PIUCNT_REG_W
, 0);
512 /* mask clock to PIU */
513 vrip_power(sc
->sc_vrip
, sc
->sc_unit
, 0);
518 vrpiu_tp_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
520 struct vrpiu_softc
*sc
= v
;
522 DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__
, __LINE__
, cmd
));
530 tp_enable
= (sc
->sc_tpstat
!= VRPIU_TP_STAT_DISABLE
);
531 ad_enable
= (sc
->sc_adstat
!= VRPIU_AD_STAT_DISABLE
);
534 vrpiu_tp_disable(sc
);
536 vrpiu_ad_disable(sc
);
538 sc
->sc_interval
= scan_interval(*(u_int
*)data
);
539 DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
540 __FILE__
, __LINE__
, *(u_int
*)data
, sc
->sc_interval
));
542 if (sc
->sc_interval
< PIUSIVL_SCANINTVAL_MIN
)
543 sc
->sc_interval
= PIUSIVL_SCANINTVAL_MIN
;
545 if (PIUSIVL_SCANINTVAL_MAX
< sc
->sc_interval
)
546 sc
->sc_interval
= PIUSIVL_SCANINTVAL_MAX
;
556 return hpc_tpanel_ioctl(&sc
->sc_tpcalib
, cmd
, data
, flag
, l
);
562 * PIU AD interrupt handler.
565 vrpiu_ad_intr(struct vrpiu_softc
*sc
)
568 unsigned int intrstat
;
570 intrstat
= vrpiu_read(sc
, PIUINT_REG_W
);
572 if (sc
->sc_adstat
== VRPIU_AD_STAT_DISABLE
) {
574 * the device isn't enabled. just clear interrupt.
576 vrpiu_write(sc
, PIUINT_REG_W
, AD_INTR
);
580 if (intrstat
& PIUINT_PADADPINTR
) {
581 sc
->sc_battery
.value
[0] = (unsigned int)
582 vrpiu_buf_read(sc
, PIUAB(0));
583 sc
->sc_battery
.value
[1] = (unsigned int)
584 vrpiu_buf_read(sc
, PIUAB(1));
585 sc
->sc_battery
.value
[2] = (unsigned int)
586 vrpiu_buf_read(sc
, PIUAB(2));
589 if (intrstat
& PIUINT_PADADPINTR
) {
590 for (i
= 0; i
< 3; i
++) {
591 if (sc
->sc_battery
.value
[i
] & PIUAB_VALID
)
592 sc
->sc_battery
.value
[i
] &=
593 sc
->sc_ab_paddata_mask
;
595 sc
->sc_battery
.value
[i
] = 0;
597 vrpiu_calc_powerstate(sc
);
599 vrpiu_write(sc
, PIUINT_REG_W
, AD_INTR
);
604 * PIU TP interrupt handler.
607 vrpiu_tp_intr(struct vrpiu_softc
*sc
)
610 unsigned int intrstat
, page
;
611 int tpx0
, tpx1
, tpy0
, tpy1
;
612 int x
, y
, xraw
, yraw
;
614 tpx0
= tpx1
= tpy0
= tpy1
= 0; /* XXX: gcc -Wuninitialized */
616 intrstat
= vrpiu_read(sc
, PIUINT_REG_W
);
618 if (sc
->sc_tpstat
== VRPIU_TP_STAT_DISABLE
) {
620 * the device isn't enabled. just clear interrupt.
622 vrpiu_write(sc
, PIUINT_REG_W
, intrstat
& TP_INTR
);
626 page
= (intrstat
& PIUINT_OVP
) ? 1 : 0;
627 if (intrstat
& (PIUINT_PADPAGE0INTR
| PIUINT_PADPAGE1INTR
)) {
628 tpx0
= vrpiu_buf_read(sc
, PIUPB(page
, 0));
629 tpx1
= vrpiu_buf_read(sc
, PIUPB(page
, 1));
630 tpy0
= vrpiu_buf_read(sc
, PIUPB(page
, 2));
631 tpy1
= vrpiu_buf_read(sc
, PIUPB(page
, 3));
634 if (intrstat
& PIUINT_PADDLOSTINTR
) {
636 for (i
= 0; i
< 4; i
++)
637 vrpiu_buf_read(sc
, PIUPB(page
, i
));
640 cnt
= vrpiu_read(sc
, PIUCNT_REG_W
);
643 vrpiu_dump_cntreg(cnt
);
646 /* clear interrupt status */
647 vrpiu_write(sc
, PIUINT_REG_W
, intrstat
& TP_INTR
);
650 DPRINTF(("vrpiu_intr: OVP=%d", page
));
651 if (intrstat
& PIUINT_PADCMDINTR
)
653 if (intrstat
& PIUINT_PADADPINTR
)
655 if (intrstat
& PIUINT_PADPAGE1INTR
)
657 if (intrstat
& PIUINT_PADPAGE0INTR
)
659 if (intrstat
& PIUINT_PADDLOSTINTR
)
661 if (intrstat
& PIUINT_PENCHGINTR
)
662 DPRINTF((" PENCHG"));
665 if (intrstat
& (PIUINT_PADPAGE0INTR
| PIUINT_PADPAGE1INTR
)) {
667 * just ignore scan data if status isn't Touch.
669 if (sc
->sc_tpstat
== VRPIU_TP_STAT_TOUCH
) {
670 /* reset tp scan timeout */
671 callout_reset(&sc
->sc_tptimeout
, VRPIU_TP_SCAN_TIMEOUT
,
672 vrpiu_tp_timeout
, sc
);
674 if (!((tpx0
& PIUPB_VALID
) && (tpx1
& PIUPB_VALID
) &&
675 (tpy0
& PIUPB_VALID
) && (tpy1
& PIUPB_VALID
))) {
676 printf("vrpiu: internal error,"
677 " data is not valid!\n");
679 tpx0
&= sc
->sc_pb_paddata_mask
;
680 tpx1
&= sc
->sc_pb_paddata_mask
;
681 tpy0
&= sc
->sc_pb_paddata_mask
;
682 tpy1
&= sc
->sc_pb_paddata_mask
;
683 #define ISVALID(n, c) ((c) - (c)/5 < (n) && (n) < (c) + (c)/5)
684 if (ISVALID(tpx0
+ tpx1
, sc
->sc_pb_paddata_max
) &&
685 ISVALID(tpy0
+ tpy1
, sc
->sc_pb_paddata_max
)) {
687 DPRINTF(("%04x %04x %04x %04x\n",
688 tpx0
, tpx1
, tpy0
, tpy1
));
689 DPRINTF(("%3d %3d (%4d %4d)->", tpx0
,
690 tpy0
, tpx0
+ tpx1
, tpy0
+ tpy1
));
692 xraw
= tpy1
* sc
->sc_pb_paddata_max
/ (tpy0
+ tpy1
);
693 yraw
= tpx1
* sc
->sc_pb_paddata_max
/ (tpx0
+ tpx1
);
694 DPRINTF(("%3d %3d", xraw
, yraw
));
696 tpcalib_trans(&sc
->sc_tpcalib
, xraw
,
699 DPRINTF(("->%4d %4d", x
, y
));
700 wsmouse_input(sc
->sc_wsmousedev
,
701 1, /* button 0 down */
706 WSMOUSE_INPUT_ABSOLUTE_X
|
707 WSMOUSE_INPUT_ABSOLUTE_Y
);
714 if (cnt
& PIUCNT_PENSTC
) {
715 if (sc
->sc_tpstat
== VRPIU_TP_STAT_RELEASE
) {
719 DPRINTF(("PEN TOUCH\n"));
720 sc
->sc_tpstat
= VRPIU_TP_STAT_TOUCH
;
722 * We should not report button down event while
723 * we don't know where it occur.
726 /* set tp scan timeout */
727 callout_reset(&sc
->sc_tptimeout
, VRPIU_TP_SCAN_TIMEOUT
,
728 vrpiu_tp_timeout
, sc
);
734 if (intrstat
& PIUINT_PADDLOSTINTR
) {
735 cnt
|= PIUCNT_PIUSEQEN
;
736 vrpiu_write(sc
, PIUCNT_REG_W
, cnt
);
743 vrpiu_tp_up(struct vrpiu_softc
*sc
)
745 if (sc
->sc_tpstat
== VRPIU_TP_STAT_TOUCH
) {
749 DPRINTF(("RELEASE\n"));
750 sc
->sc_tpstat
= VRPIU_TP_STAT_RELEASE
;
752 /* clear tp scan timeout */
753 callout_stop(&sc
->sc_tptimeout
);
756 wsmouse_input(sc
->sc_wsmousedev
, 0, 0, 0, 0, 0, 0);
760 /* touch panel timeout handler */
762 vrpiu_tp_timeout(void *v
)
764 struct vrpiu_softc
*sc
= (struct vrpiu_softc
*)v
;
768 unsigned int cnt
= vrpiu_read(sc
, PIUCNT_REG_W
);
769 DPRINTF(("TIMEOUT: stat=%s reg=%s\n",
770 (sc
->sc_tpstat
== VRPIU_TP_STAT_TOUCH
)?"touch":"release",
771 (cnt
& PIUCNT_PENSTC
)?"touch":"release"));
778 * PIU interrupt handler.
781 vrpiu_intr(void *arg
)
783 struct vrpiu_softc
*sc
= arg
;
792 vrpiu_start_powerstate(void *v
)
795 struct vrpiu_softc
*sc
= (struct vrpiu_softc
*)v
;
798 mask
= vrpiu_read(sc
, PIUAMSK_REG_W
);
799 mask
&= 0xff8f; /* XXX */
800 vrpiu_write(sc
, PIUAMSK_REG_W
, mask
);
801 vrpiu_write(sc
, PIUASCN_REG_W
, PIUACN_ADPSSTART
);
803 * restart next A/D polling
805 callout_reset(&sc
->sc_adpoll
, hz
*vrpiu_ad_poll_interval
,
806 vrpiu_start_powerstate
, sc
);
810 vrpiu_calc_powerstate(struct vrpiu_softc
*sc
)
812 extern void vrgiu_diff_io(void);
813 vrpiu_ad_disable(sc
);
814 VPRINTF(("vrpiu:AD: %d, %d, %d\n",
815 sc
->sc_battery
.value
[0],
816 sc
->sc_battery
.value
[1],
817 sc
->sc_battery
.value
[2]));
818 sc
->sc_battery
.nextpoll
= hz
*vrpiu_ad_poll_interval
;
819 vrpiu_send_battery_event(sc
);
821 * restart next A/D polling if change polling timming.
823 if (sc
->sc_battery
.nextpoll
!= hz
*vrpiu_ad_poll_interval
)
824 callout_reset(&sc
->sc_adpoll
, sc
->sc_battery
.nextpoll
,
825 vrpiu_start_powerstate
, sc
);
832 vrpiu_power(int why
, void *arg
)
834 struct vrpiu_softc
*sc
= arg
;
841 callout_reset(&sc
->sc_adpoll
, hz
,
842 vrpiu_start_powerstate
, sc
);
848 vrpiu_send_battery_event(struct vrpiu_softc
*sc
)
850 #ifdef VRPIU_ADHOC_BATTERY_EVENT
851 static int batteryhigh
= 0;
852 static int batterylow
= 0;
853 static int critical
= 0;
855 if (sc
->sc_battery_spec
== NULL
856 || sc
->sc_battery_spec
->main_port
== -1)
859 if (sc
->sc_battery
.value
[sc
->sc_battery_spec
->main_port
]
860 <= sc
->sc_battery_spec
->dc_critical
) {
862 config_hook_call(CONFIG_HOOK_PMEVENT
,
863 CONFIG_HOOK_PMEVENT_BATTERY
,
864 (void *)CONFIG_HOOK_BATT_CRITICAL
);
867 config_hook_call(CONFIG_HOOK_PMEVENT
,
868 CONFIG_HOOK_PMEVENT_SUSPENDREQ
,
874 } else if (sc
->sc_battery
.value
[sc
->sc_battery_spec
->main_port
]
875 <= sc
->sc_battery_spec
->dc_20p
) {
878 config_hook_call(CONFIG_HOOK_PMEVENT
,
879 CONFIG_HOOK_PMEVENT_BATTERY
,
880 (void *)CONFIG_HOOK_BATT_20P
);
881 config_hook_call(CONFIG_HOOK_PMEVENT
,
882 CONFIG_HOOK_PMEVENT_BATTERY
,
883 (void *)CONFIG_HOOK_BATT_LOW
);
885 } else if (sc
->sc_battery
.value
[sc
->sc_battery_spec
->main_port
]
886 <= sc
->sc_battery_spec
->dc_50p
) {
888 if (batterylow
== 0) {
890 config_hook_call(CONFIG_HOOK_PMEVENT
,
891 CONFIG_HOOK_PMEVENT_BATTERY
,
892 (void *)CONFIG_HOOK_BATT_50P
);
894 } else if (sc
->sc_battery
.value
[sc
->sc_battery_spec
->main_port
]
895 >= sc
->sc_battery_spec
->ac_80p
) {
897 if (batteryhigh
== 0) {
899 config_hook_call(CONFIG_HOOK_PMEVENT
,
900 CONFIG_HOOK_PMEVENT_BATTERY
,
901 (void *)CONFIG_HOOK_BATT_80P
);
902 config_hook_call(CONFIG_HOOK_PMEVENT
,
903 CONFIG_HOOK_PMEVENT_BATTERY
,
904 (void *)CONFIG_HOOK_BATT_HIGH
);
907 #else /* VRPIU_ADHOC_BATTERY_EVENT */
908 config_hook_call(CONFIG_HOOK_SET
,
909 CONFIG_HOOK_BATTERYVAL
,
910 (void *)&sc
->sc_battery
);
911 #endif /* VRPIU_ADHOC_BATTERY_EVENT */
916 vrpiu_dump_cntreg(unsigned int cnt
)
918 printf("%s", (cnt
& PIUCNT_PENSTC
) ? "Touch" : "Release");
920 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_CmdScan
)
922 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_IntervalNextScan
)
923 printf("IntervalNextScan");
924 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_PenDataScan
)
925 printf("PenDataScan");
926 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_WaitPenTouch
)
927 printf("WaitPenTouch");
928 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_RFU
)
930 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_ADPortScan
)
931 printf("ADPortScan");
932 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_Standby
)
934 if ((cnt
& PIUCNT_PADSTATE_MASK
) == PIUCNT_PADSTATE_Disable
)
936 if (cnt
& PIUCNT_PADATSTOP
)
938 if (cnt
& PIUCNT_PADATSTART
)
939 printf(" AutoStart");
940 if (cnt
& PIUCNT_PADSCANSTOP
)
942 if (cnt
& PIUCNT_PADSCANSTART
)
944 if (cnt
& PIUCNT_PADSCANTYPE
)
945 printf(" ScanPressure");
946 if ((cnt
& PIUCNT_PIUMODE_MASK
) == PIUCNT_PIUMODE_ADCONVERTER
)
948 if ((cnt
& PIUCNT_PIUMODE_MASK
) == PIUCNT_PIUMODE_COORDINATE
)
949 printf(" Coordinate");
950 if (cnt
& PIUCNT_PIUSEQEN
)
952 if ((cnt
& PIUCNT_PIUPWR
) == 0)
954 if ((cnt
& PIUCNT_PADRST
) == 0)