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