j6x0tp.c revision 1.19 1 /* $NetBSD: j6x0tp.c,v 1.19 2007/07/11 22:15:41 uwe Exp $ */
2
3 /*
4 * Copyright (c) 2003 Valeriy E. Ushakov
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: j6x0tp.c,v 1.19 2007/07/11 22:15:41 uwe Exp $");
32
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/device.h>
36 #include <sys/malloc.h>
37 #include <sys/systm.h>
38 #include <sys/callout.h>
39
40 #include "opt_j6x0tp.h"
41
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/wscons/wsmousevar.h>
44 #include <dev/wscons/wskbdvar.h>
45 #include <dev/wscons/wsksymvar.h>
46 #include <dev/wscons/wsksymdef.h>
47 #include <dev/hpc/hpctpanelvar.h>
48
49 #include <machine/platid.h>
50 #include <machine/platid_mask.h>
51
52 #include <machine/intr.h>
53
54 #include <sh3/exception.h>
55 #include <sh3/intcreg.h>
56 #include <sh3/pfcreg.h>
57 #include <sh3/adcreg.h>
58
59 #include <sh3/dev/adcvar.h>
60
61
62 #define J6X0TP_DEBUG 1
63 #if 0 /* XXX: disabled in favor of local version that uses printf_nolog */
64 #define DPRINTF_ENABLE
65 #define DPRINTF_DEBUG j6x0tp_debug
66 #define DPRINTF_LEVEL 0
67 #include <machine/debug.h>
68 #else
69 #ifdef J6X0TP_DEBUG
70 volatile int j6x0tp_debug = 0;
71 #define DPRINTF_PRINTF printf_nolog
72 #define DPRINTF(arg) if (j6x0tp_debug) DPRINTF_PRINTF arg
73 #define DPRINTFN(n, arg) if (j6x0tp_debug > (n)) DPRINTF_PRINTF arg
74 #else
75 #define DPRINTF(arg) ((void)0)
76 #define DPRINTFN(n, arg) ((void)0)
77 #endif
78 #endif
79
80
81 /*
82 * PFC bits pertinent to Jornada 6x0 touchpanel
83 */
84 #define PHDR_TP_PEN_DOWN 0x08
85
86 #define SCPDR_TP_SCAN_ENABLE 0x20
87 #define SCPDR_TP_SCAN_Y 0x02
88 #define SCPDR_TP_SCAN_X 0x01
89
90 /*
91 * A/D converter channels to get x/y from
92 */
93 #define ADC_CHANNEL_TP_Y 1
94 #define ADC_CHANNEL_TP_X 2
95
96 /*
97 * Default (read: my device :) raw X/Y values for framebuffer edges.
98 * XXX: defopt these?
99 */
100 #define J6X0TP_FB_LEFT 38
101 #define J6X0TP_FB_RIGHT 950
102 #define J6X0TP_FB_TOP 80
103 #define J6X0TP_FB_BOTTOM 900
104
105 /*
106 * Bottom of the n'th hard icon (n = 1..4)
107 */
108 #define J6X0TP_HARD_ICON_MAX_Y(n) \
109 (J6X0TP_FB_TOP + ((J6X0TP_FB_BOTTOM - J6X0TP_FB_TOP) / 4) * (n))
110
111
112 struct j6x0tp_softc {
113 struct device sc_dev;
114
115 #define J6X0TP_WSMOUSE_ENABLED 0x01
116 #define J6X0TP_WSKBD_ENABLED 0x02
117 int sc_enabled;
118
119 int sc_hard_icon;
120
121 struct callout sc_touch_ch;
122
123 struct device *sc_wsmousedev;
124 struct device *sc_wskbddev;
125
126 struct tpcalib_softc sc_tpcalib; /* calibration info for wsmouse */
127 };
128
129
130 /* config machinery */
131 static int j6x0tp_match(struct device *, struct cfdata *, void *);
132 static void j6x0tp_attach(struct device *, struct device *, void *);
133
134 /* wsmouse accessops */
135 static int j6x0tp_wsmouse_enable(void *);
136 static int j6x0tp_wsmouse_ioctl(void *, u_long, void *, int,
137 struct lwp *);
138 static void j6x0tp_wsmouse_disable(void *);
139
140 /* wskbd accessops */
141 static int j6x0tp_wskbd_enable(void *, int);
142 static void j6x0tp_wskbd_set_leds(void *, int);
143 static int j6x0tp_wskbd_ioctl(void *, u_long, void *, int,
144 struct lwp *);
145
146 /* power hook */
147 static void j6x0tp_powerhook(int, void *);
148
149 /* internal driver routines */
150 static void j6x0tp_enable(struct j6x0tp_softc *);
151 static void j6x0tp_disable(struct j6x0tp_softc *);
152 static int j6x0tp_enable_child(struct j6x0tp_softc *, int, int);
153 static int j6x0tp_intr(void *);
154 static void j6x0tp_start_polling(void *);
155 static void j6x0tp_stop_polling(struct j6x0tp_softc *);
156 static void j6x0tp_callout_wsmouse(void *);
157 static void j6x0tp_callout_wskbd(void *);
158 static void j6x0tp_wsmouse_input(struct j6x0tp_softc *, int, int);
159 static void j6x0tp_get_raw_xy(int *, int *);
160 static int j6x0tp_get_hard_icon(int, int);
161
162
163 static const struct wsmouse_accessops j6x0tp_accessops = {
164 j6x0tp_wsmouse_enable,
165 j6x0tp_wsmouse_ioctl,
166 j6x0tp_wsmouse_disable
167 };
168
169 static const struct wsmouse_calibcoords j6x0tp_default_calib = {
170 0, 0, 639, 239,
171 4,
172 {{ J6X0TP_FB_LEFT, J6X0TP_FB_TOP, 0, 0 },
173 { J6X0TP_FB_RIGHT, J6X0TP_FB_TOP, 639, 0 },
174 { J6X0TP_FB_LEFT, J6X0TP_FB_BOTTOM, 0, 239 },
175 { J6X0TP_FB_RIGHT, J6X0TP_FB_BOTTOM, 639, 239 }}
176 };
177
178 static const struct wskbd_accessops j6x0tp_wskbd_accessops = {
179 j6x0tp_wskbd_enable,
180 j6x0tp_wskbd_set_leds,
181 j6x0tp_wskbd_ioctl
182 };
183
184
185 #ifndef J6X0TP_SETTINGS_ICON_KEYSYM
186 #define J6X0TP_SETTINGS_ICON_KEYSYM KS_Home
187 #endif
188 #ifndef J6X0TP_PGUP_ICON_KEYSYM
189 #define J6X0TP_PGUP_ICON_KEYSYM KS_Prior
190 #endif
191 #ifndef J6X0TP_PGDN_ICON_KEYSYM
192 #define J6X0TP_PGDN_ICON_KEYSYM KS_Next
193 #endif
194 #ifndef J6X0TP_SWITCH_ICON_KEYSYM
195 #define J6X0TP_SWITCH_ICON_KEYSYM KS_End
196 #endif
197
198 static const keysym_t j6x0tp_wskbd_keydesc[] = {
199 KS_KEYCODE(1), J6X0TP_SETTINGS_ICON_KEYSYM,
200 KS_KEYCODE(2), J6X0TP_PGUP_ICON_KEYSYM,
201 KS_KEYCODE(3), J6X0TP_PGDN_ICON_KEYSYM,
202 KS_KEYCODE(4), J6X0TP_SWITCH_ICON_KEYSYM
203 };
204
205 static const struct wscons_keydesc j6x0tp_wskbd_keydesctab[] = {
206 { KB_US, 0,
207 sizeof(j6x0tp_wskbd_keydesc)/sizeof(keysym_t),
208 j6x0tp_wskbd_keydesc
209 },
210 {0, 0, 0, 0}
211 };
212
213 static const struct wskbd_mapdata j6x0tp_wskbd_keymapdata = {
214 j6x0tp_wskbd_keydesctab, KB_US
215 };
216
217
218 CFATTACH_DECL(j6x0tp, sizeof(struct j6x0tp_softc),
219 j6x0tp_match, j6x0tp_attach, NULL, NULL);
220
221
222 static int
223 j6x0tp_match(struct device *parent, struct cfdata *cf, void *aux)
224 {
225
226 /*
227 * XXX: platid_mask_MACH_HP_LX also matches 360LX. It's not
228 * confirmed whether touch panel in 360LX is connected this
229 * way. We may need to regroup platid masks.
230 */
231 if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)
232 && !platid_match(&platid, &platid_mask_MACH_HP_LX))
233 return (0);
234
235 if (strcmp(cf->cf_name, "j6x0tp") != 0)
236 return (0);
237
238 return (1);
239 }
240
241
242 static void
243 j6x0tp_attach(struct device *parent, struct device *self, void *aux)
244 {
245 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
246 struct wsmousedev_attach_args wsma;
247 struct wskbddev_attach_args wska;
248
249 printf("\n");
250
251 sc->sc_enabled = 0;
252 sc->sc_hard_icon = 0;
253
254 /*
255 * Hook for dopowerhooks(9). We don't implement detach, so
256 * don't bother saving a cookie to disablish the power hook.
257 */
258 (void)powerhook_establish(device_xname(&sc->sc_dev),
259 j6x0tp_powerhook, sc);
260
261 /* touch-panel as a pointing device */
262 wsma.accessops = &j6x0tp_accessops;
263 wsma.accesscookie = sc;
264
265 sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &wsma,
266 wsmousedevprint);
267 if (sc->sc_wsmousedev == NULL)
268 return;
269
270 /* on-screen "hard icons" as a keyboard device */
271 wska.console = 0;
272 wska.keymap = &j6x0tp_wskbd_keymapdata;
273 wska.accessops = &j6x0tp_wskbd_accessops;
274 wska.accesscookie = sc;
275
276 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wska,
277 wskbddevprint);
278
279 /* init calibration, set default parameters */
280 tpcalib_init(&sc->sc_tpcalib);
281 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
282 (void *)__UNCONST(&j6x0tp_default_calib), 0, 0);
283
284 /* used when in polling mode */
285 callout_init(&sc->sc_touch_ch, 0);
286
287 /* establish interrupt handler, but disable until opened */
288 intc_intr_establish(SH7709_INTEVT2_IRQ3, IST_EDGE, IPL_TTY,
289 j6x0tp_intr, sc);
290 intc_intr_disable(SH7709_INTEVT2_IRQ3);
291 }
292
293
294 static void
295 j6x0tp_powerhook(int why, void *cookie)
296 {
297 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)cookie;
298
299 printf("%s: powerhook(%d)\n", device_xname(&sc->sc_dev), why);
300
301 if (!sc->sc_enabled)
302 return;
303
304 if (why == PWR_SUSPEND) {
305 j6x0tp_disable(sc);
306 }
307 else if (why == PWR_RESUME) {
308 j6x0tp_enable(sc);
309 }
310 }
311
312
313 /*
314 * Enable touch panel: we start in interrupt mode.
315 * Must be called as spltty().
316 */
317 static void
318 j6x0tp_enable(struct j6x0tp_softc *sc)
319 {
320
321 DPRINTFN(2, ("%s: enable\n", device_xname(&sc->sc_dev)));
322 intc_intr_enable(SH7709_INTEVT2_IRQ3);
323 }
324
325
326 /*
327 * Disable touch panel: disable interrupt, cancel pending callout.
328 * Must be called as spltty().
329 */
330 static void
331 j6x0tp_disable(struct j6x0tp_softc *sc)
332 {
333
334 DPRINTFN(2, ("%s: disable\n", device_xname(&sc->sc_dev)));
335 intc_intr_disable(SH7709_INTEVT2_IRQ3);
336 callout_stop(&sc->sc_touch_ch);
337 }
338
339
340 static int
341 j6x0tp_enable_child(struct j6x0tp_softc *sc, int child, int on)
342 {
343 int s = spltty();
344
345 if (on) {
346 if (!sc->sc_enabled)
347 j6x0tp_enable(sc);
348 sc->sc_enabled |= child;
349 } else {
350 sc->sc_enabled &= ~child;
351 if (!sc->sc_enabled)
352 j6x0tp_disable(sc);
353 }
354
355 splx(s);
356 return (0);
357 }
358
359
360 static int
361 j6x0tp_wsmouse_enable(void *self)
362 {
363 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
364
365 DPRINTFN(1, ("%s: wsmouse enable\n", device_xname(&sc->sc_dev)));
366 return (j6x0tp_enable_child(sc, J6X0TP_WSMOUSE_ENABLED, 1));
367 }
368
369
370 static void
371 j6x0tp_wsmouse_disable(void *self)
372 {
373 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
374
375 DPRINTFN(1, ("%s: wsmouse disable\n", device_xname(&sc->sc_dev)));
376 j6x0tp_enable_child(sc, J6X0TP_WSMOUSE_ENABLED, 0);
377 }
378
379
380 static int
381 j6x0tp_wskbd_enable(void *self, int on)
382 {
383 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
384
385 DPRINTFN(1, ("%s: wskbd %sable\n", device_xname(&sc->sc_dev),
386 on ? "en" : "dis"));
387 return (j6x0tp_enable_child(sc, J6X0TP_WSKBD_ENABLED, on));
388 }
389
390
391 static int
392 j6x0tp_intr(void *self)
393 {
394 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
395
396 uint8_t irr0;
397 uint8_t phdr, touched;
398 unsigned int steady, tremor_timeout;
399
400 irr0 = _reg_read_1(SH7709_IRR0);
401 if ((irr0 & IRR0_IRQ3) == 0) {
402 #ifdef DIAGNOSTIC
403 printf("%s: irr0 %02x?\n", device_xname(&sc->sc_dev), irr0);
404 #endif
405 return (0);
406 }
407
408 if (!sc->sc_enabled) {
409 DPRINTFN(1, ("%s: intr: !sc_enabled\n",
410 device_xname(&sc->sc_dev)));
411 intc_intr_disable(SH7709_INTEVT2_IRQ3);
412 goto served;
413 }
414
415
416 /*
417 * Number of times the "touched" bit should be read
418 * consecutively.
419 */
420 # define TREMOR_THRESHOLD 0x300
421
422 steady = 0;
423 tremor_timeout = TREMOR_THRESHOLD * 16; /* XXX: arbitrary */
424 touched = PHDR_TP_PEN_DOWN; /* we start with "touched" state */
425
426 do {
427 phdr = _reg_read_1(SH7709_PHDR);
428
429 if ((phdr & PHDR_TP_PEN_DOWN) == touched)
430 ++steady;
431 else {
432 steady = 0;
433 touched = phdr & PHDR_TP_PEN_DOWN;
434 }
435
436 if (--tremor_timeout == 0) {
437 DPRINTF(("%s: tremor timeout!\n",
438 device_xname(&sc->sc_dev)));
439 goto served;
440 }
441 } while (steady < TREMOR_THRESHOLD);
442
443 if (touched) {
444 intc_intr_disable(SH7709_INTEVT2_IRQ3);
445
446 /*
447 * ADC readings are not stable yet, so schedule
448 * callout instead of accessing ADC from the interrupt
449 * handler only to immediately delay().
450 */
451 callout_reset(&sc->sc_touch_ch, hz/32,
452 j6x0tp_start_polling, sc);
453 } else
454 DPRINTFN(1, ("%s: tremor\n", device_xname(&sc->sc_dev)));
455 served:
456 /* clear the interrupt (XXX: protect access?) */
457 _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ3);
458
459 return (1);
460 }
461
462
463 /*
464 * Called from the interrupt handler at spltty() upon first touch.
465 * Decide if we are going to report this touch as a mouse click/drag
466 * or as a key press.
467 */
468 static void
469 j6x0tp_start_polling(void *self)
470 {
471 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
472 uint8_t phdr;
473 int do_mouse, do_kbd;
474 int rawx, rawy;
475 int icon;
476
477 phdr = _reg_read_1(SH7709_PHDR);
478 if ((phdr & PHDR_TP_PEN_DOWN) == 0) {
479 DPRINTFN(2, ("%s: start: pen is not down\n",
480 device_xname(&sc->sc_dev)));
481 j6x0tp_stop_polling(sc);
482 }
483
484 j6x0tp_get_raw_xy(&rawx, &rawy);
485 DPRINTFN(2, ("%s: start: %4d %4d -> ",
486 device_xname(&sc->sc_dev), rawx, rawy));
487
488 do_mouse = sc->sc_enabled & J6X0TP_WSMOUSE_ENABLED;
489 #ifdef J6X0TP_WSMOUSE_EXCLUSIVE
490 if (do_mouse)
491 do_kbd = 0;
492 else
493 #endif
494 do_kbd = sc->sc_enabled & J6X0TP_WSKBD_ENABLED;
495
496 icon = 0;
497 if (do_kbd)
498 icon = j6x0tp_get_hard_icon(rawx, rawy);
499
500 if (icon != 0) {
501 DPRINTFN(2, ("icon %d\n", icon));
502 sc->sc_hard_icon = icon;
503 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, icon);
504 callout_reset(&sc->sc_touch_ch, hz/32,
505 j6x0tp_callout_wskbd, sc);
506 } else if (do_mouse) {
507 DPRINTFN(2, ("mouse\n"));
508 j6x0tp_wsmouse_input(sc, rawx, rawy);
509 callout_reset(&sc->sc_touch_ch, hz/32,
510 j6x0tp_callout_wsmouse, sc);
511 } else {
512 DPRINTFN(2, ("ignore\n"));
513 j6x0tp_stop_polling(sc);
514 }
515 }
516
517
518 /*
519 * Re-enable touch panel interrupt.
520 * Called as spltty() when polling code detects pen-up.
521 */
522 static void
523 j6x0tp_stop_polling(struct j6x0tp_softc *sc)
524 {
525 uint8_t irr0;
526
527 DPRINTFN(2, ("%s: stop\n", device_xname(&sc->sc_dev)));
528
529 /* clear pending interrupt signal before re-enabling the interrupt */
530 irr0 = _reg_read_1(SH7709_IRR0);
531 if ((irr0 & IRR0_IRQ3) != 0)
532 _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ3);
533
534 intc_intr_enable(SH7709_INTEVT2_IRQ3);
535 }
536
537
538 /*
539 * We are reporting this touch as a keyboard event.
540 * Poll touch screen waiting for pen-up.
541 */
542 static void
543 j6x0tp_callout_wskbd(void *self)
544 {
545 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
546 uint8_t phdr;
547 int s;
548
549 s = spltty();
550
551 if (!sc->sc_enabled) {
552 DPRINTFN(1, ("%s: wskbd callout: !sc_enabled\n",
553 device_xname(&sc->sc_dev)));
554 splx(s);
555 return;
556 }
557
558 phdr = _reg_read_1(SH7709_PHDR);
559 if ((phdr & PHDR_TP_PEN_DOWN) != 0) {
560 /*
561 * Pen is still down, continue polling. Wskbd's
562 * auto-repeat takes care of repeating the key.
563 */
564 callout_schedule(&sc->sc_touch_ch, hz/32);
565 } else {
566 wskbd_input(sc->sc_wskbddev,
567 WSCONS_EVENT_KEY_UP, sc->sc_hard_icon);
568 j6x0tp_stop_polling(sc);
569 }
570 splx(s);
571 }
572
573
574 /*
575 * We are reporting this touch as a mouse click/drag.
576 */
577 static void
578 j6x0tp_callout_wsmouse(void *self)
579 {
580 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
581 uint8_t phdr;
582 int rawx, rawy;
583 int s;
584
585 s = spltty();
586
587 if (!sc->sc_enabled) {
588 DPRINTFN(1, ("%s: wsmouse callout: !sc_enabled\n",
589 device_xname(&sc->sc_dev)));
590 splx(s);
591 return;
592 }
593
594 phdr = _reg_read_1(SH7709_PHDR);
595 if ((phdr & PHDR_TP_PEN_DOWN) != 0) {
596 j6x0tp_get_raw_xy(&rawx, &rawy);
597 j6x0tp_wsmouse_input(sc, rawx, rawy); /* mouse dragged */
598 callout_schedule(&sc->sc_touch_ch, hz/32);
599 } else {
600 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0, /* button up */
601 WSMOUSE_INPUT_DELTA);
602 j6x0tp_stop_polling(sc);
603 }
604 splx(s);
605 }
606
607
608 /*
609 * Report mouse click/drag.
610 */
611 static void
612 j6x0tp_wsmouse_input(struct j6x0tp_softc *sc, int rawx, int rawy)
613 {
614 int x, y;
615
616 tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y);
617
618 DPRINTFN(3, ("%s: %4d %4d -> %3d %3d\n",
619 device_xname(&sc->sc_dev), rawx, rawy, x, y));
620
621 wsmouse_input(sc->sc_wsmousedev,
622 1, /* button */
623 x, y, 0, 0,
624 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
625 }
626
627
628 /*
629 * Read raw X/Y coordinates from the ADC.
630 * XXX: protect accesses to SCPDR?
631 */
632 static void
633 j6x0tp_get_raw_xy(int *rawxp, int *rawyp)
634 {
635 uint8_t scpdr;
636
637 /* Y axis */
638 scpdr = _reg_read_1(SH7709_SCPDR);
639 scpdr |= SCPDR_TP_SCAN_ENABLE;
640 scpdr &= ~SCPDR_TP_SCAN_Y; /* pull low to scan */
641 _reg_write_1(SH7709_SCPDR, scpdr);
642 delay(10);
643
644 *rawyp = adc_sample_channel(ADC_CHANNEL_TP_Y);
645
646 /* X axis */
647 scpdr = _reg_read_1(SH7709_SCPDR);
648 scpdr |= SCPDR_TP_SCAN_Y;
649 scpdr &= ~SCPDR_TP_SCAN_X; /* pull low to scan */
650 _reg_write_1(SH7709_SCPDR, scpdr);
651 delay(10);
652
653 *rawxp = adc_sample_channel(ADC_CHANNEL_TP_X);
654
655 /* restore SCPDR */
656 scpdr = _reg_read_1(SH7709_SCPDR);
657 scpdr |= SCPDR_TP_SCAN_X;
658 scpdr &= ~SCPDR_TP_SCAN_ENABLE;
659 _reg_write_1(SH7709_SCPDR, scpdr);
660 }
661
662
663 /*
664 * Check if the (rawx, rawy) is inside one of the 4 hard icons.
665 * Return the icon number 1..4, or 0 if not inside an icon.
666 */
667 static int
668 j6x0tp_get_hard_icon(int rawx, int rawy)
669 {
670 if (rawx <= J6X0TP_FB_RIGHT)
671 return (0);
672
673 if (rawy < J6X0TP_HARD_ICON_MAX_Y(1))
674 return (1);
675 else if (rawy < J6X0TP_HARD_ICON_MAX_Y(2))
676 return (2);
677 else if (rawy < J6X0TP_HARD_ICON_MAX_Y(3))
678 return (3);
679 else
680 return (4);
681 }
682
683
684 static int
685 j6x0tp_wsmouse_ioctl(void *self, u_long cmd, void *data, int flag,
686 struct lwp *l)
687 {
688 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self;
689
690 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
691 }
692
693
694 static int
695 j6x0tp_wskbd_ioctl(void *self, u_long cmd, void *data, int flag,
696 struct lwp *l)
697 {
698 /* struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; */
699
700 switch (cmd) {
701 case WSKBDIO_GTYPE:
702 *(int *)data = WSKBD_TYPE_HPC_BTN; /* may be use new type? */
703 return (0);
704
705 case WSKBDIO_GETLEDS:
706 *(int *)data = 0;
707 return (0);
708
709 default:
710 return (EPASSTHROUGH);
711 }
712 }
713
714
715 static void
716 j6x0tp_wskbd_set_leds(void *self, int leds)
717 {
718
719 /* nothing to do*/
720 return;
721 }
722