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