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