xref: /netbsd-src/sys/arch/hpcmips/dev/ucbtp.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: ucbtp.c,v 1.4 2000/05/22 17:17:45 uch Exp $ */
2 
3 /*-
4  * Copyright (c) 2000 UCHIYAMA Yasushi.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end
31  *	Touch panel part.
32  */
33 #define UCBTPDEBUG
34 
35 #include "opt_tx39_debug.h"
36 #include "opt_use_poll.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 
42 #include <machine/bus.h>
43 #include <machine/intr.h>
44 #include <machine/bootinfo.h> /* bootinfo */
45 
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsmousevar.h>
48 
49 #include <hpcmips/dev/tpcalibvar.h>
50 
51 #include <hpcmips/tx/tx39var.h>
52 #include <hpcmips/tx/tx39sibvar.h>
53 #include <hpcmips/tx/tx39sibreg.h>
54 #include <hpcmips/tx/tx39icureg.h>
55 
56 #include <hpcmips/dev/ucb1200var.h>
57 #include <hpcmips/dev/ucb1200reg.h>
58 
59 #include <hpcmips/tx/txsnd.h>
60 #include <hpcmips/dev/video_subr.h> /* debug */
61 
62 #ifdef UCBTPDEBUG
63 int	ucbtp_debug = 0;
64 #define	DPRINTF(arg) if (ucbtp_debug) printf arg;
65 #define	DPRINTFN(n, arg) if (ucbtp_debug > (n)) printf arg;
66 #else
67 #define	DPRINTF(arg)
68 #define DPRINTFN(n, arg)
69 #endif
70 
71 enum ucbts_stat {
72 	UCBTS_STAT_DISABLE,
73 	UCBTS_STAT_RELEASE,
74 	UCBTS_STAT_TOUCH,
75 	UCBTS_STAT_DRAG,
76 };
77 
78 #define UCBTS_POSX	1
79 #define UCBTS_POSY	2
80 #define UCBTS_PRESS	3
81 
82 #define UCBTS_PRESS_THRESHOLD	80
83 #define UCBTS_TAP_THRESHOLD	5
84 
85 enum ucbadc_state {
86 /* 0 */	UCBADC_IDLE,
87 /* 1 */	UCBADC_ADC_INIT,
88 /* 2 */	UCBADC_ADC_FINI,
89 /* 3 */	UCBADC_MEASUMENT_INIT,
90 /* 4 */	UCBADC_MEASUMENT_FINI,
91 /* 5 */	UCBADC_ADC_ENABLE,
92 /* 6 */	UCBADC_ADC_START0,
93 /* 7 */	UCBADC_ADC_START1,
94 /* 8 */	UCBADC_ADC_DATAREAD,
95 /* 9 */	UCBADC_ADC_DATAREAD_WAIT,
96 /*10 */	UCBADC_ADC_DISABLE,
97 /*11 */	UCBADC_ADC_INTRMODE,
98 /*12 */	UCBADC_ADC_INPUT,
99 /*13 */	UCBADC_INTR_ACK0,
100 /*14 */	UCBADC_INTR_ACK1,
101 /*15 */	UCBADC_INTR_ACK2,
102 /*16 */	UCBADC_REGREAD,
103 /*17 */	UCBADC_REGWRITE
104 };
105 
106 struct ucbtp_softc {
107 	struct device sc_dev;
108 	struct device *sc_sib; /* parent (TX39 SIB module) */
109 	struct device *sc_ucb; /* parent (UCB1200 module) */
110 	tx_chipset_tag_t sc_tc;
111 
112 	enum ucbts_stat sc_stat;
113 	int sc_polling;
114 	int sc_polling_finish;
115 	void *sc_pollh;
116 
117 	struct tpcalib_softc sc_tpcalib;
118 	int sc_calibrated;
119 
120 	/* measurement value */
121 	int sc_x, sc_y, sc_p;
122 	int sc_ox, sc_oy;
123 	int sc_xy_reverse; /* some platform pin connect interchanged */
124 
125 	/*
126 	 * touch panel state machine
127 	 */
128 	void *sm_ih; /* TX39 SIB subframe 0 interrupt handler */
129 
130 	int sm_addr; /* UCB1200 register address */
131 	u_int32_t sm_reg;  /* UCB1200 register data & TX39 SIB header */
132 	int sm_tmpreg;
133 #define UCBADC_RETRY_DEFAULT		200
134 	int sm_retry; /* retry counter */
135 
136 	enum ucbadc_state sm_state;
137 	int		sm_measurement; /* X, Y, Pressure */
138 #define	UCBADC_MEASUREMENT_X		0
139 #define	UCBADC_MEASUREMENT_Y		1
140 #define	UCBADC_MEASUREMENT_PRESSURE	2
141 	int sm_returnstate;
142 
143 	int sm_read_state, sm_write_state;
144 	int sm_writing;	/* writing state flag */
145 	u_int32_t sm_write_val;	/* temporary buffer */
146 
147 	int sm_rw_retry; /* retry counter for r/w */
148 
149 	/* wsmouse */
150 	struct device *sc_wsmousedev;
151 };
152 
153 int	ucbtp_match	__P((struct device*, struct cfdata*, void*));
154 void	ucbtp_attach	__P((struct device*, struct device*, void*));
155 
156 int	ucbtp_sibintr	__P((void*));
157 int	ucbtp_poll __P((void*));
158 int	ucbtp_adc_async __P((void*));
159 int	ucbtp_input __P((struct ucbtp_softc*));
160 int	ucbtp_busy __P((void*));
161 
162 int	ucbtp_enable __P((void*));
163 int	ucbtp_ioctl __P((void*, u_long, caddr_t, int, struct proc*));
164 void	ucbtp_disable __P((void*));
165 
166 struct cfattach ucbtp_ca = {
167 	sizeof(struct ucbtp_softc), ucbtp_match, ucbtp_attach
168 };
169 
170 const struct wsmouse_accessops ucbtp_accessops = {
171 	ucbtp_enable,
172 	ucbtp_ioctl,
173 	ucbtp_disable,
174 };
175 
176 /*
177  * XXX currently no calibration method. this is temporary hack.
178  */
179 #include <machine/platid.h>
180 
181 struct	wsmouse_calibcoords *calibration_sample_lookup __P((void));
182 int	ucbtp_calibration __P((struct ucbtp_softc*));
183 
184 struct calibration_sample_table {
185 	platid_t	cst_platform;
186 	struct wsmouse_calibcoords cst_sample;
187 } calibration_sample_table[] = {
188 	{{{PLATID_WILD, PLATID_MACH_COMPAQ_C_8XX}},  /* uch machine */
189 	 { 0, 0, 639, 239, 5,
190 	   {{ 507, 510, 320, 120 },
191 	    { 898, 757,  40,  40 },
192 	    { 900, 255,  40, 200 },
193 	    { 109, 249, 600, 200 },
194 	    { 110, 753, 600,  40 }}}},
195 
196 	{{{PLATID_WILD, PLATID_MACH_COMPAQ_C_2010}}, /* uch machine */
197 	 { 0, 0, 639, 239, 5,
198 	   {{ 506, 487, 320, 120 },
199 	    { 880, 250,  40,  40 },
200 	    { 880, 718,  40, 200 },
201 	    { 140, 726, 600, 200 },
202 	    { 137, 250, 600,  40 }}}},
203 
204 	{{{PLATID_WILD, PLATID_MACH_SHARP_MOBILON_HC4100}}, /* uch machine */
205 	 { 0, 0, 639, 239, 5,
206 	   {{ 497, 501, 320, 120 },
207 	    { 752, 893,  40,  40 },
208 	    { 242, 891,  40, 200 },
209 	    { 241, 115, 600, 200 },
210 	    { 747, 101, 600,  40 }}}},
211 
212 	{{{PLATID_WILD, PLATID_MACH_SHARP_TELIOS_HCAJ1}}, /* uch machine */
213 	 { 0, 0, 799, 479, 5,
214 	   {{ 850, 150,   1,   1 },
215 	    { 850, 880,   1, 479 },
216 	    { 850, 880,   1, 479 },
217 	    {  85, 880, 799, 479 },
218 	    {  85, 150, 799,   1 }}}},
219 
220 	{{{PLATID_UNKNOWN, PLATID_UNKNOWN}},
221 	 { 0, 0, 639, 239, 5,
222 	   {{0, 0, 0, 0},
223 	    {0, 0, 0, 0},
224 	    {0, 0, 0, 0},
225 	    {0, 0, 0, 0},
226 	    {0, 0, 0, 0}}}},
227 };
228 
229 struct wsmouse_calibcoords *
230 calibration_sample_lookup()
231 {
232 	struct calibration_sample_table *tab;
233 	platid_mask_t mask;
234 
235 	for (tab = calibration_sample_table;
236 	     tab->cst_platform.dw.dw1 != PLATID_UNKNOWN; tab++) {
237 
238 		mask = PLATID_DEREF(&tab->cst_platform);
239 
240 		if (platid_match(&platid, &mask)) {
241 			return (&tab->cst_sample);
242 		}
243 	}
244 
245 	return (0);
246 }
247 
248 int
249 ucbtp_calibration(sc)
250 	struct ucbtp_softc *sc;
251 {
252 	struct wsmouse_calibcoords *cs;
253 
254 	if (sc->sc_tc->tc_videot)
255 		video_calibration_pattern(sc->sc_tc->tc_videot); /* debug */
256 
257 	tpcalib_init(&sc->sc_tpcalib);
258 
259 	if (!(cs = calibration_sample_lookup())) {
260 		DPRINTF(("no calibration data"));
261 		return (1);
262 	}
263 
264 	sc->sc_calibrated =
265 		tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
266 			      (caddr_t)cs, 0, 0) == 0 ? 1 : 0;
267 
268 	if (!sc->sc_calibrated)
269 		printf("not ");
270 	printf("calibrated");
271 
272 	return (0);
273 }
274 
275 int
276 ucbtp_match(parent, cf, aux)
277 	struct device *parent;
278 	struct cfdata *cf;
279 	void *aux;
280 {
281 	return (1);
282 }
283 
284 void
285 ucbtp_attach(parent, self, aux)
286 	struct device *parent;
287 	struct device *self;
288 	void *aux;
289 {
290 	struct ucb1200_attach_args *ucba = aux;
291 	struct ucbtp_softc *sc = (void*)self;
292 	struct wsmousedev_attach_args wsmaa;
293 	tx_chipset_tag_t tc;
294 
295 	tc = sc->sc_tc = ucba->ucba_tc;
296 	sc->sc_sib = ucba->ucba_sib;
297 	sc->sc_ucb = ucba->ucba_ucb;
298 
299 	printf(": ");
300 	/* touch panel interrupt */
301 	tx_intr_establish(tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBIRQPOSINT),
302 			  IST_EDGE, IPL_TTY, ucbtp_sibintr, sc);
303 
304 	/* attempt to calibrate touch panel */
305 	ucbtp_calibration(sc);
306 #ifdef TX392X /* hack for Telios HC-VJ1C */
307 	sc->sc_xy_reverse = 1;
308 #endif
309 
310 	printf("\n");
311 
312 	wsmaa.accessops = &ucbtp_accessops;
313 	wsmaa.accesscookie = sc;
314 
315 	ucb1200_state_install(parent, ucbtp_busy, self, UCB1200_TP_MODULE);
316 
317 	/*
318 	 * attach the wsmouse
319 	 */
320 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
321 }
322 
323 int
324 ucbtp_busy(arg)
325 	void *arg;
326 {
327 	struct ucbtp_softc *sc = arg;
328 
329 	return (sc->sm_state != UCBADC_IDLE);
330 }
331 
332 int
333 ucbtp_poll(arg)
334 	void *arg;
335 {
336 	struct ucbtp_softc *sc = arg;
337 
338 	if (!ucb1200_state_idle(sc->sc_ucb)) /* subframe0 busy */
339 		return (POLL_CONT);
340 
341 	if (sc->sc_polling_finish) {
342 		sc->sc_polling_finish = 0;
343 		return (POLL_END);
344 	}
345 
346 	/* execute A-D converter */
347 	sc->sm_state = UCBADC_ADC_INIT;
348 	ucbtp_adc_async(sc);
349 
350 	return (POLL_CONT);
351 }
352 
353 int
354 ucbtp_sibintr(arg)
355 	void *arg;
356 {
357 	struct ucbtp_softc *sc = arg;
358 
359 	sc->sc_stat = UCBTS_STAT_TOUCH;
360 
361 	/* click! */
362 	tx_sound_click(sc->sc_tc);
363 
364 	/* invoke touch panel polling */
365 	if (!sc->sc_polling) {
366 		sc->sc_pollh = tx39_poll_establish(sc->sc_tc, 1, IST_EDGE,
367 						   ucbtp_poll, sc);
368 		if (!sc->sc_pollh) {
369 			printf("%s: can't poll\n", sc->sc_dev.dv_xname);
370 		}
371 	}
372 
373 	/* don't acknoledge interrupt until polling finish */
374 
375 	return (0);
376 }
377 
378 #define REGWRITE(addr, reg, ret) (					\
379 	sc->sm_addr = (addr),						\
380 	sc->sm_reg = (reg),						\
381 	sc->sm_returnstate = (ret),					\
382 	sc->sm_state = UCBADC_REGWRITE)
383 #define REGREAD(addr, ret) (						\
384 	sc->sm_addr = (addr),						\
385 	sc->sm_returnstate = (ret),					\
386 	sc->sm_state = UCBADC_REGREAD)
387 
388 int
389 ucbtp_adc_async(arg)
390 	void *arg;
391 {
392 	struct ucbtp_softc *sc = arg;
393 	tx_chipset_tag_t tc = sc->sc_tc;
394 	txreg_t reg;
395 	u_int16_t reg16;
396 
397 	DPRINTFN(9, ("state: %d\n", sc->sm_state));
398 
399 	switch (sc->sm_state) {
400 	default:
401 		panic("ucbtp_adc: invalid state %d", sc->sm_state);
402 		/* NOTREACHED */
403 		break;
404 
405 	case UCBADC_IDLE:
406 		/* nothing to do */
407 		break;
408 
409 	case UCBADC_ADC_INIT:
410 		sc->sc_polling++;
411 		sc->sc_stat = UCBTS_STAT_DRAG;
412 		/* enable heart beat of this state machine */
413 		sc->sm_ih = tx_intr_establish(
414 			tc,
415 			MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT),
416 			IST_EDGE, IPL_TTY, ucbtp_adc_async, sc);
417 
418 		sc->sm_state = UCBADC_MEASUMENT_INIT;
419 		break;
420 
421 	case UCBADC_ADC_FINI:
422 		/* disable heart beat of this state machine */
423 		tx_intr_disestablish(tc, sc->sm_ih);
424 		sc->sm_state = UCBADC_IDLE;
425 		break;
426 
427 	case UCBADC_MEASUMENT_INIT:
428 		switch (sc->sm_measurement) {
429 		default:
430 			panic("unknown measurement spec.");
431 			/* NOTREACHED */
432 			break;
433 		case UCBADC_MEASUREMENT_X:
434 			REGWRITE(UCB1200_TSCTRL_REG,
435 				 UCB1200_TSCTRL_XPOSITION,
436 				 UCBADC_ADC_ENABLE);
437 			break;
438 		case UCBADC_MEASUREMENT_Y:
439 			REGWRITE(UCB1200_TSCTRL_REG,
440 				 UCB1200_TSCTRL_YPOSITION,
441 				 UCBADC_ADC_ENABLE);
442 			break;
443 		case UCBADC_MEASUREMENT_PRESSURE:
444 			REGWRITE(UCB1200_TSCTRL_REG,
445 				 UCB1200_TSCTRL_PRESSURE,
446 				 UCBADC_ADC_ENABLE);
447 			break;
448 		}
449 		break;
450 
451 	case UCBADC_MEASUMENT_FINI:
452 		switch (sc->sm_measurement) {
453 		case UCBADC_MEASUREMENT_X:
454 			sc->sm_measurement = UCBADC_MEASUREMENT_Y;
455 			sc->sm_state = UCBADC_MEASUMENT_INIT;
456 			break;
457 		case UCBADC_MEASUREMENT_Y:
458 			sc->sm_measurement = UCBADC_MEASUREMENT_PRESSURE;
459 			sc->sm_state = UCBADC_MEASUMENT_INIT;
460 			break;
461 		case UCBADC_MEASUREMENT_PRESSURE:
462 			sc->sm_measurement = UCBADC_MEASUREMENT_X;
463 			/* measument complete. pass down to wsmouse_input */
464 			sc->sm_state = UCBADC_ADC_INPUT;
465 			break;
466 		}
467 		break;
468 
469 	case UCBADC_ADC_ENABLE:
470 		switch (sc->sm_measurement) {
471 		case UCBADC_MEASUREMENT_PRESSURE:
472 			/* FALLTHROUGH */
473 		case UCBADC_MEASUREMENT_X:
474 			sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET(
475 				UCB1200_ADCCTRL_ENABLE,
476 				UCB1200_ADCCTRL_INPUT_TSPX);
477 			REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg,
478 				 UCBADC_ADC_START0);
479 			break;
480 		case UCBADC_MEASUREMENT_Y:
481 			sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET(
482 				UCB1200_ADCCTRL_ENABLE,
483 				UCB1200_ADCCTRL_INPUT_TSPY);
484 			REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg,
485 				 UCBADC_ADC_START0);
486 			break;
487 		}
488 		break;
489 
490 	case UCBADC_ADC_START0:
491 		REGWRITE(UCB1200_ADCCTRL_REG,
492 			 sc->sm_tmpreg | UCB1200_ADCCTRL_START,
493 			 UCBADC_ADC_START1);
494 		break;
495 
496 	case UCBADC_ADC_START1:
497 		REGWRITE(UCB1200_ADCCTRL_REG,
498 			 sc->sm_tmpreg,
499 			 UCBADC_ADC_DATAREAD);
500 		sc->sm_retry = UCBADC_RETRY_DEFAULT;
501 		break;
502 
503 	case UCBADC_ADC_DATAREAD:
504 		REGREAD(UCB1200_ADCDATA_REG, UCBADC_ADC_DATAREAD_WAIT);
505 		break;
506 
507 	case UCBADC_ADC_DATAREAD_WAIT:
508 		reg16 = TX39_SIBSF0_REGDATA(sc->sm_reg);
509 		if (!(reg16 & UCB1200_ADCDATA_INPROGRESS) &&
510 		    --sc->sm_retry > 0) {
511 			sc->sm_state = UCBADC_ADC_DATAREAD;
512 		} else {
513 			if (sc->sm_retry <= 0) {
514 				printf("dataread failed\n");
515 				sc->sm_state = UCBADC_ADC_FINI;
516 				break;
517 			}
518 
519 			switch (sc->sm_measurement) {
520 			case UCBADC_MEASUREMENT_X:
521 				sc->sc_x = UCB1200_ADCDATA(reg16);
522 				DPRINTFN(9, ("x=%d\n", sc->sc_x));
523 				break;
524 			case UCBADC_MEASUREMENT_Y:
525 				sc->sc_y = UCB1200_ADCDATA(reg16);
526 				DPRINTFN(9, ("y=%d\n", sc->sc_y));
527 				break;
528 			case UCBADC_MEASUREMENT_PRESSURE:
529 				sc->sc_p = UCB1200_ADCDATA(reg16);
530 				DPRINTFN(9, ("p=%d\n", sc->sc_p));
531 				break;
532 			}
533 
534 			sc->sm_state = UCBADC_ADC_DISABLE;
535 		}
536 
537 		break;
538 
539 	case UCBADC_ADC_DISABLE:
540 		REGWRITE(UCB1200_ADCCTRL_REG, 0, UCBADC_ADC_INTRMODE);
541 
542 		break;
543 	case UCBADC_ADC_INTRMODE:
544 		REGWRITE(UCB1200_TSCTRL_REG, UCB1200_TSCTRL_INTERRUPT,
545 			 UCBADC_MEASUMENT_FINI);
546 		break;
547 
548 	case UCBADC_ADC_INPUT:
549 		if (ucbtp_input(sc) == 0)
550 			sc->sm_state = UCBADC_ADC_FINI;
551 		else
552 			sc->sm_state = UCBADC_INTR_ACK0;
553 		break;
554 
555 	case UCBADC_INTR_ACK0:
556 		REGREAD(UCB1200_INTSTAT_REG, UCBADC_INTR_ACK1);
557 		break;
558 
559 	case UCBADC_INTR_ACK1:
560 		REGWRITE(UCB1200_INTSTAT_REG, sc->sm_reg, UCBADC_INTR_ACK2);
561 		break;
562 
563 	case UCBADC_INTR_ACK2:
564 		sc->sc_polling_finish = 1;
565 		REGWRITE(UCB1200_INTSTAT_REG, 0, UCBADC_ADC_FINI);
566 		break;
567 
568 	/*
569 	 * UCB1200 register access state
570 	 */
571 	case UCBADC_REGREAD:
572 		/*
573 		 * In	: sc->sm_addr
574 		 * Out	: sc->sm_reg  (with SIBtag)
575 		 */
576 #define TXSIB_REGREAD_INIT	0
577 #define TXSIB_REGREAD_READ	1
578 		switch (sc->sm_read_state) {
579 		case TXSIB_REGREAD_INIT:
580 			reg = TX39_SIBSF0_REGADDR_SET(0, sc->sm_addr);
581 			tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
582 			sc->sm_rw_retry = UCBADC_RETRY_DEFAULT;
583 			sc->sm_read_state = TXSIB_REGREAD_READ;
584 			break;
585 		case TXSIB_REGREAD_READ:
586 			reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG);
587 			if ((TX39_SIBSF0_REGADDR(reg) != sc->sm_addr) &&
588 			    --sc->sm_rw_retry > 0) {
589 				break;
590 			}
591 
592 			if (sc->sm_rw_retry <= 0) {
593 				printf("sf0read: command failed\n");
594 				sc->sm_state = UCBADC_ADC_FINI;
595 			} else {
596 				sc->sm_reg = reg;
597 				sc->sm_read_state = TXSIB_REGREAD_INIT;
598 				DPRINTFN(9, ("%08x\n", reg));
599 				if (sc->sm_writing)
600 					sc->sm_state = UCBADC_REGWRITE;
601 				else
602 					sc->sm_state = sc->sm_returnstate;
603 			}
604 			break;
605 		}
606 		break;
607 
608 	case UCBADC_REGWRITE:
609 		/*
610 		 * In	: sc->sm_addr, sc->sm_reg (lower 16bit only)
611 		 */
612 #define TXSIB_REGWRITE_INIT	0
613 #define TXSIB_REGWRITE_WRITE	1
614 		switch (sc->sm_write_state) {
615 		case TXSIB_REGWRITE_INIT:
616 			sc->sm_writing = 1;
617 			sc->sm_write_state = TXSIB_REGWRITE_WRITE;
618 			sc->sm_state = UCBADC_REGREAD;
619 
620 			sc->sm_write_val = sc->sm_reg;
621 			break;
622 		case TXSIB_REGWRITE_WRITE:
623 			sc->sm_writing = 0;
624 			sc->sm_write_state = TXSIB_REGWRITE_INIT;
625 			sc->sm_state = sc->sm_returnstate;
626 
627 			reg = sc->sm_reg;
628 			reg |= TX39_SIBSF0_WRITE;
629 			TX39_SIBSF0_REGDATA_CLR(reg);
630 			reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sm_write_val);
631 			tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg);
632 			break;
633 		}
634 		break;
635 	}
636 
637 	return (0);
638 }
639 
640 int
641 ucbtp_input(sc)
642 	struct ucbtp_softc *sc;
643 {
644 	int rx, ry, x, y, p;
645 
646 	rx = sc->sc_x;
647 	ry = sc->sc_y;
648 	p = sc->sc_p;
649 
650 	if (!sc->sc_calibrated) {
651 		DPRINTFN(2, ("x=%4d y=%4d p=%4d\n", rx, ry, p));
652 		DPRINTF(("ucbtp_input: no calibration data\n"));
653 	}
654 
655 	if (p < UCBTS_PRESS_THRESHOLD || rx == 0x3ff || ry == 0x3ff ||
656 	    rx == 0 || ry == 0) {
657 		sc->sc_stat = UCBTS_STAT_RELEASE;
658 		if (sc->sc_polling < UCBTS_TAP_THRESHOLD) {
659 			DPRINTFN(2, ("TAP!\n"));
660 			/* button 0 DOWN */
661 			wsmouse_input(sc->sc_wsmousedev, 1, 0, 0, 0, 0);
662 			/* button 0 UP */
663 			wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
664 		} else {
665 			wsmouse_input(sc->sc_wsmousedev, 0,
666 				      sc->sc_ox, sc->sc_oy, 0,
667 				      WSMOUSE_INPUT_ABSOLUTE_X |
668 				      WSMOUSE_INPUT_ABSOLUTE_Y);
669 
670 			DPRINTFN(2, ("RELEASE\n"));
671 		}
672 		sc->sc_polling = 0;
673 
674 		return (1);
675 	}
676 
677 	if (sc->sc_xy_reverse)
678 		tpcalib_trans(&sc->sc_tpcalib, ry, rx, &x, &y);
679 	else
680 		tpcalib_trans(&sc->sc_tpcalib, rx, ry, &x, &y);
681 
682 	DPRINTFN(2, ("x: %4d->%4d y: %4d->%4d pressure=%4d\n",
683 		     rx, x, ry, y, p));
684 
685 	/* debug draw */
686 	if (sc->sc_tc->tc_videot) {
687 		if (sc->sc_polling == 1)
688 			video_dot(sc->sc_tc->tc_videot, x, y);
689 		else
690 			video_line(sc->sc_tc->tc_videot, sc->sc_ox,
691 				   sc->sc_oy, x, y);
692 	}
693 
694 	sc->sc_ox = x, sc->sc_oy = y;
695 
696 	wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0,
697 		      WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
698 
699 	return (0);
700 }
701 
702 /*
703  * access ops.
704  */
705 
706 int
707 ucbtp_enable(v)
708 	void *v;
709 {
710 	/* not yet */
711 	return (0);
712 }
713 
714 void
715 ucbtp_disable(v)
716 	void *v;
717 {
718 	/* not yet */
719 }
720 
721 int
722 ucbtp_ioctl(v, cmd, data, flag, p)
723 	void *v;
724 	u_long cmd;
725 	caddr_t data;
726 	int flag;
727 	struct proc *p;
728 {
729 	struct ucbtp_softc *sc = v;
730 
731 	DPRINTF(("%s(%d): ucbtp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
732 
733 	switch (cmd) {
734 	case WSMOUSEIO_GTYPE:
735 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
736 		break;
737 
738 	case WSMOUSEIO_SRES:
739 		printf("%s(%d): WSMOUSRIO_SRES is not supported",
740 		       __FILE__, __LINE__);
741 		break;
742 
743 	case WSMOUSEIO_SCALIBCOORDS:
744 	case WSMOUSEIO_GCALIBCOORDS:
745                 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
746 
747 	default:
748 		return (-1);
749 	}
750 
751 	return (0);
752 }
753