vrpiu.c revision 1.3 1 /* $NetBSD: vrpiu.c,v 1.3 2000/01/10 14:08:03 takemura Exp $ */
2
3 /*
4 * Copyright (c) 1999 Shin Takemura All rights reserved.
5 * Copyright (c) 1999 PocketBSD Project. 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/device.h>
33 #include <sys/kernel.h>
34
35 #include <dev/wscons/wsconsio.h>
36 #include <dev/wscons/wsmousevar.h>
37
38 #include <machine/bus.h>
39
40 #include <hpcmips/dev/tpcalibvar.h>
41 #include <hpcmips/vr/vripvar.h>
42 #include <hpcmips/vr/cmureg.h>
43 #include <hpcmips/vr/vrpiuvar.h>
44 #include <hpcmips/vr/vrpiureg.h>
45
46 /*
47 * contant and macro definitions
48 */
49 #define VRPIUDEBUG
50 #ifdef VRPIUDEBUG
51 int vrpiu_debug = 0;
52 #define DPRINTF(arg) if (vrpiu_debug) printf arg;
53 #else
54 #define DPRINTF(arg)
55 #endif
56
57 /*
58 * data types
59 */
60 /* struct vrpiu_softc is defined in vrpiuvar.h */
61
62 /*
63 * function prototypes
64 */
65 static int vrpiumatch __P((struct device *, struct cfdata *, void *));
66 static void vrpiuattach __P((struct device *, struct device *, void *));
67
68 static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
69 static u_short vrpiu_read __P((struct vrpiu_softc *, int));
70
71 static int vrpiu_intr __P((void *));
72 #ifdef DEBUG
73 static void vrpiu_dump_cntreg __P((unsigned int cmd));
74 #endif
75
76 static int vrpiu_enable __P((void *));
77 static int vrpiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
78 static void vrpiu_disable __P((void *));
79
80 /* mra is defined in mra.c */
81 int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
82 int n, int scale, int *a, int *b, int *c));
83
84 /*
85 * static or global variables
86 */
87 struct cfattach vrpiu_ca = {
88 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
89 };
90
91 const struct wsmouse_accessops vrpiu_accessops = {
92 vrpiu_enable,
93 vrpiu_ioctl,
94 vrpiu_disable,
95 };
96
97 /*
98 * function definitions
99 */
100 static inline void
101 vrpiu_write(sc, port, val)
102 struct vrpiu_softc *sc;
103 int port;
104 unsigned short val;
105 {
106 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
107 }
108
109 static inline u_short
110 vrpiu_read(sc, port)
111 struct vrpiu_softc *sc;
112 int port;
113 {
114 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
115 }
116
117 static int
118 vrpiumatch(parent, cf, aux)
119 struct device *parent;
120 struct cfdata *cf;
121 void *aux;
122 {
123 return 1;
124 }
125
126 static void
127 vrpiuattach(parent, self, aux)
128 struct device *parent;
129 struct device *self;
130 void *aux;
131 {
132 struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
133 struct vrip_attach_args *va = aux;
134 struct wsmousedev_attach_args wsmaa;
135
136 bus_space_tag_t iot = va->va_iot;
137 bus_space_handle_t ioh;
138
139 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
140 printf(": can't map bus space\n");
141 return;
142 }
143
144 sc->sc_iot = iot;
145 sc->sc_ioh = ioh;
146 sc->sc_vrip = va->va_vc;
147
148 /*
149 * disable device until vrpiu_enable called
150 */
151 sc->sc_stat = VRPIU_STAT_DISABLE;
152
153 tpcalib_init(&sc->sc_tpcalib);
154 #if 1
155 /*
156 * XXX, calibrate parameters
157 */
158 {
159 static struct wsmouse_calibcoords D = {
160 /* samples got on my MC-R500 */
161 0, 0, 639, 239,
162 5,
163 { { 502, 486, 320, 120 },
164 { 55, 109, 0, 0 },
165 { 54, 913, 0, 239 },
166 { 973, 924, 639, 239 },
167 { 975, 123, 639, 0 } }
168 };
169 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
170 (caddr_t)&D, 0, 0);
171 }
172 #endif
173
174 /* install interrupt handler and enable interrupt */
175 if (!(sc->sc_handler =
176 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
177 vrpiu_intr, sc))) {
178 printf (": can't map interrupt line.\n");
179 return;
180 }
181
182 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */
183 vrpiu_disable(sc);
184
185 printf("\n");
186
187 wsmaa.accessops = &vrpiu_accessops;
188 wsmaa.accesscookie = sc;
189
190 /*
191 * attach the wsmouse
192 */
193 sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
194 }
195
196 int
197 vrpiu_enable(v)
198 void *v;
199 {
200 struct vrpiu_softc *sc = v;
201 int s;
202 unsigned int cnt;
203
204 DPRINTF(("%s(%d): vrpiu_enable()\n", __FILE__, __LINE__));
205 if (sc->sc_stat != VRPIU_STAT_DISABLE)
206 return EBUSY;
207
208 /* supply clock to PIU */
209 __vrcmu_supply(CMUMSKPIU, 1);
210
211 /* Scan interval 0x7FF is maximum value */
212 vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF);
213
214 s = spltty();
215
216 /* clear interrupt status */
217 vrpiu_write(sc, PIUINT_REG_W, PIUINT_ALLINTR);
218
219 /* Disable -> Standby */
220 cnt = PIUCNT_PIUPWR |
221 PIUCNT_PIUMODE_COORDINATE |
222 PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
223 vrpiu_write(sc, PIUCNT_REG_W, cnt);
224
225 /* save pen status, touch or release */
226 cnt = vrpiu_read(sc, PIUCNT_REG_W);
227
228 /* Level2 interrupt register setting */
229 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 1);
230
231 /*
232 * Enable scan sequencer operation
233 * Standby -> WaitPenTouch
234 */
235 cnt |= PIUCNT_PIUSEQEN;
236 vrpiu_write(sc, PIUCNT_REG_W, cnt);
237
238 /* transit status DISABLE -> TOUCH or RELEASE */
239 sc->sc_stat = (cnt & PIUCNT_PENSTC) ?
240 VRPIU_STAT_TOUCH : VRPIU_STAT_RELEASE;
241
242 splx(s);
243
244 return 0;
245 }
246
247 void
248 vrpiu_disable(v)
249 void *v;
250 {
251 struct vrpiu_softc *sc = v;
252
253 DPRINTF(("%s(%d): vrpiu_disable()\n", __FILE__, __LINE__));
254
255 /* Set level2 interrupt register to mask interrupts */
256 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 0);
257
258 sc->sc_stat = VRPIU_STAT_DISABLE;
259
260 /* Disable scan sequencer operation and power off */
261 vrpiu_write(sc, PIUCNT_REG_W, 0);
262
263 /* mask clock to PIU */
264 __vrcmu_supply(CMUMSKPIU, 1);
265 }
266
267 int
268 vrpiu_ioctl(v, cmd, data, flag, p)
269 void *v;
270 u_long cmd;
271 caddr_t data;
272 int flag;
273 struct proc *p;
274 {
275 struct vrpiu_softc *sc = v;
276
277 DPRINTF(("%s(%d): vrpiu_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
278
279 switch (cmd) {
280 case WSMOUSEIO_GTYPE:
281 *(u_int *)data = WSMOUSE_TYPE_TPANEL;
282 break;
283
284 case WSMOUSEIO_SRES:
285 printf("%s(%d): WSMOUSRIO_SRES is not supported",
286 __FILE__, __LINE__);
287 break;
288
289 case WSMOUSEIO_SCALIBCOORDS:
290 case WSMOUSEIO_GCALIBCOORDS:
291 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
292
293 default:
294 return (-1);
295 }
296 return (0);
297 }
298
299 /*
300 * PIU interrupt handler.
301 */
302 int
303 vrpiu_intr(arg)
304 void *arg;
305 {
306 struct vrpiu_softc *sc = arg;
307 unsigned int cnt, i;
308 unsigned int intrstat, page;
309 int tpx0, tpx1, tpy0, tpy1;
310 int x, y, xraw, yraw;
311
312 intrstat = vrpiu_read(sc, PIUINT_REG_W);
313
314 if (sc->sc_stat == VRPIU_STAT_DISABLE) {
315 /*
316 * the device isn't enabled. just clear interrupt.
317 */
318 vrpiu_write(sc, PIUINT_REG_W, intrstat);
319 return (0);
320 }
321
322 page = (intrstat & PIUINT_OVP) ? 1 : 0;
323 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
324 tpx0 = vrpiu_read(sc, PIUPB(page, 0));
325 tpx1 = vrpiu_read(sc, PIUPB(page, 1));
326 tpy0 = vrpiu_read(sc, PIUPB(page, 2));
327 tpy1 = vrpiu_read(sc, PIUPB(page, 3));
328 }
329
330 if (intrstat & PIUINT_PADDLOSTINTR) {
331 page = page ? 0 : 1;
332 for (i = 0; i < 4; i++)
333 vrpiu_read(sc, PIUPB(page, i));
334 }
335
336 cnt = vrpiu_read(sc, PIUCNT_REG_W);
337 #ifdef DEBUG
338 if (vrpiu_debug)
339 vrpiu_dump_cntreg(cnt);
340 #endif
341
342 /* clear interrupt status */
343 vrpiu_write(sc, PIUINT_REG_W, intrstat);
344
345 #if 0
346 DPRINTF(("vrpiu_intr: OVP=%d", page));
347 if (intrstat & PIUINT_PADCMDINTR)
348 DPRINTF((" CMD"));
349 if (intrstat & PIUINT_PADADPINTR)
350 DPRINTF((" A/D"));
351 if (intrstat & PIUINT_PADPAGE1INTR)
352 DPRINTF((" PAGE1"));
353 if (intrstat & PIUINT_PADPAGE0INTR)
354 DPRINTF((" PAGE0"));
355 if (intrstat & PIUINT_PADDLOSTINTR)
356 DPRINTF((" DLOST"));
357 if (intrstat & PIUINT_PENCHGINTR)
358 DPRINTF((" PENCHG"));
359 DPRINTF(("\n"));
360 #endif
361 if (cnt & PIUCNT_PENSTC) {
362 if (sc->sc_stat == VRPIU_STAT_RELEASE) {
363 /*
364 * pen touch
365 */
366 DPRINTF(("PEN TOUCH\n"));
367 sc->sc_stat = VRPIU_STAT_TOUCH;
368 /* button 0 DOWN */
369 wsmouse_input(sc->sc_wsmousedev,
370 (1 << 0),
371 0, 0, 0, 0);
372 }
373 } else {
374 if (sc->sc_stat == VRPIU_STAT_TOUCH) {
375 /*
376 * pen release
377 */
378 DPRINTF(("RELEASE\n"));
379 sc->sc_stat = VRPIU_STAT_RELEASE;
380 /* button 0 UP */
381 wsmouse_input(sc->sc_wsmousedev,
382 0,
383 0, 0, 0, 0);
384 }
385 }
386
387 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
388 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
389 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
390 printf("vrpiu: internal error, data is not valid!\n");
391 } else {
392 tpx0 &= PIUPB_PADDATA_MASK;
393 tpx1 &= PIUPB_PADDATA_MASK;
394 tpy0 &= PIUPB_PADDATA_MASK;
395 tpy1 &= PIUPB_PADDATA_MASK;
396 #define ISVALID(n, c, m) ((c) - (m) < (n) && (n) < (c) + (m))
397 if (ISVALID(tpx0 + tpx1, 1024, 200) &&
398 ISVALID(tpx0 + tpx1, 1024, 200)) {
399 #if 0
400 DPRINTF(("%04x %04x %04x %04x\n",
401 tpx0, tpx1, tpy0, tpy1));
402 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
403 tpx0 + tpx1, tpy0 + tpy1);
404 #endif
405 xraw = tpy1 * 1024 / (tpy0 + tpy1);
406 yraw = tpx1 * 1024 / (tpx0 + tpx1);
407 DPRINTF(("%3d %3d", xraw, yraw));
408
409 tpcalib_trans(&sc->sc_tpcalib,
410 xraw, yraw, &x, &y);
411
412 DPRINTF(("->%4d %4d", x, y));
413 wsmouse_input(sc->sc_wsmousedev,
414 (cnt & PIUCNT_PENSTC) ? 1 : 0,
415 x, /* x */
416 y, /* y */
417 0, /* z */
418 WSMOUSE_INPUT_ABSOLUTE_X |
419 WSMOUSE_INPUT_ABSOLUTE_Y);
420 DPRINTF(("\n"));
421 }
422 }
423 }
424
425 if (intrstat & PIUINT_PADDLOSTINTR) {
426 cnt |= PIUCNT_PIUSEQEN;
427 vrpiu_write(sc, PIUCNT_REG_W, cnt);
428 }
429
430 return 0;
431 }
432
433 #ifdef DEBUG
434 void
435 vrpiu_dump_cntreg(cnt)
436 unsigned int cnt;
437 {
438 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
439 printf(" state=");
440 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
441 printf("CmdScan");
442 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
443 printf("IntervalNextScan");
444 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
445 printf("PenDataScan");
446 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
447 printf("WaitPenTouch");
448 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
449 printf("???");
450 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
451 printf("ADPortScan");
452 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
453 printf("Standby");
454 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
455 printf("Disable");
456 if (cnt & PIUCNT_PADATSTOP)
457 printf(" AutoStop");
458 if (cnt & PIUCNT_PADATSTART)
459 printf(" AutoStart");
460 if (cnt & PIUCNT_PADSCANSTOP)
461 printf(" Stop");
462 if (cnt & PIUCNT_PADSCANSTART)
463 printf(" Start");
464 if (cnt & PIUCNT_PADSCANTYPE)
465 printf(" ScanPressure");
466 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
467 printf(" A/D");
468 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
469 printf(" Coordinate");
470 if (cnt & PIUCNT_PIUSEQEN)
471 printf(" SeqEn");
472 if ((cnt & PIUCNT_PIUPWR) == 0)
473 printf(" PowerOff");
474 if ((cnt & PIUCNT_PADRST) == 0)
475 printf(" Reset");
476 printf("\n");
477 }
478 #endif
479