1 /* $NetBSD: j720tp.c,v 1.2 2006/06/27 14:36:50 peter Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by IWAMOTO Toshihiro and Peter Postma. 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 /* Jornada 720 touch-panel driver. */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: j720tp.c,v 1.2 2006/06/27 14:36:50 peter Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/kernel.h> 48 #include <sys/malloc.h> 49 #include <sys/ioctl.h> 50 #include <sys/callout.h> 51 52 #include <machine/platid.h> 53 #include <machine/platid_mask.h> 54 55 #include <arm/sa11x0/sa11x0_var.h> 56 #include <arm/sa11x0/sa11x0_gpioreg.h> 57 #include <arm/sa11x0/sa11x0_ppcreg.h> 58 #include <arm/sa11x0/sa11x0_sspreg.h> 59 60 #include <dev/wscons/wsconsio.h> 61 #include <dev/wscons/wsmousevar.h> 62 #include <dev/hpc/hpctpanelvar.h> 63 64 #include <hpcarm/dev/j720sspvar.h> 65 66 #include "opt_j720tp.h" 67 68 #ifdef J720TP_DEBUG 69 #define DPRINTF(arg) printf arg 70 #else 71 #define DPRINTF(arg) /* nothing */ 72 #endif 73 74 struct j720tp_softc { 75 struct device sc_dev; 76 77 int sc_enabled; 78 79 struct callout sc_tpcallout; 80 struct j720ssp_softc *sc_ssp; 81 82 struct device *sc_wsmousedev; 83 84 struct tpcalib_softc sc_tpcalib; 85 }; 86 87 static int j720tp_match(struct device *, struct cfdata *, void *); 88 static void j720tp_attach(struct device *, struct device *, void *); 89 90 static int j720tp_wsmouse_enable(void *); 91 static int j720tp_wsmouse_ioctl(void *, u_long, caddr_t, int, 92 struct lwp *); 93 static void j720tp_wsmouse_disable(void *); 94 95 static void j720tp_enable_intr(struct j720tp_softc *); 96 static void j720tp_disable_intr(struct j720tp_softc *); 97 static int j720tp_intr(void *); 98 static int j720tp_get_rawxy(struct j720tp_softc *, int *, int *); 99 static void j720tp_wsmouse_input(struct j720tp_softc *, int, int); 100 static void j720tp_wsmouse_callout(void *); 101 102 103 const struct wsmouse_accessops j720tp_wsmouse_accessops = { 104 j720tp_wsmouse_enable, 105 j720tp_wsmouse_ioctl, 106 j720tp_wsmouse_disable 107 }; 108 109 static const struct wsmouse_calibcoords j720tp_default_calib = { 110 0, 0, 639, 239, 111 4, 112 {{ 988, 80, 0, 0 }, 113 { 88, 84, 639, 0 }, 114 { 988, 927, 0, 239 }, 115 { 88, 940, 639, 239 }} 116 }; 117 118 CFATTACH_DECL(j720tp, sizeof(struct j720tp_softc), 119 j720tp_match, j720tp_attach, NULL, NULL); 120 121 122 static int 123 j720tp_match(struct device *parent, struct cfdata *cf, void *aux) 124 { 125 126 if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX)) 127 return 0; 128 if (strcmp(cf->cf_name, "j720tp") != 0) 129 return 0; 130 131 return 1; 132 } 133 134 static void 135 j720tp_attach(struct device *parent, struct device *self, void *aux) 136 { 137 struct j720tp_softc *sc = (struct j720tp_softc *)self; 138 struct wsmousedev_attach_args wsma; 139 140 printf("\n"); 141 142 sc->sc_ssp = (struct j720ssp_softc *)parent; 143 sc->sc_enabled = 0; 144 145 /* Touch-panel as a pointing device. */ 146 wsma.accessops = &j720tp_wsmouse_accessops; 147 wsma.accesscookie = sc; 148 149 sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &wsma, 150 wsmousedevprint); 151 152 /* Initialize calibration, set default parameters. */ 153 tpcalib_init(&sc->sc_tpcalib); 154 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 155 __UNCONST(&j720tp_default_calib), 0, 0); 156 157 j720tp_wsmouse_disable(sc); 158 callout_init(&sc->sc_tpcallout); 159 160 /* Setup touch-panel interrupt. */ 161 sa11x0_intr_establish(0, 9, 1, IPL_TTY, j720tp_intr, sc); 162 } 163 164 static int 165 j720tp_wsmouse_enable(void *self) 166 { 167 struct j720tp_softc *sc = self; 168 int s; 169 170 s = spltty(); 171 172 j720tp_enable_intr(sc); 173 174 sc->sc_enabled = 1; 175 176 splx(s); 177 return 0; 178 } 179 180 static int 181 j720tp_wsmouse_ioctl(void *self, u_long cmd, caddr_t data, int flag, 182 struct lwp *l) 183 { 184 struct j720tp_softc *sc = self; 185 186 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 187 } 188 189 static void 190 j720tp_wsmouse_disable(void *self) 191 { 192 struct j720tp_softc *sc = self; 193 int s; 194 195 s = spltty(); 196 197 j720tp_disable_intr(sc); 198 callout_stop(&sc->sc_tpcallout); 199 200 sc->sc_enabled = 0; 201 202 splx(s); 203 } 204 205 /* 206 * Enable touch-panel interrupt. Must be called at spltty(). 207 */ 208 static void 209 j720tp_enable_intr(struct j720tp_softc *sc) 210 { 211 struct j720ssp_softc *ssp = sc->sc_ssp; 212 uint32_t er; 213 214 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 215 er |= 1 << 9; 216 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 217 } 218 219 /* 220 * Disable touch-panel interrupt. Must be called at spltty(). 221 */ 222 static void 223 j720tp_disable_intr(struct j720tp_softc *sc) 224 { 225 struct j720ssp_softc *ssp = sc->sc_ssp; 226 uint32_t er; 227 228 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 229 er &= ~(1 << 9); 230 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 231 } 232 233 static int 234 j720tp_intr(void *arg) 235 { 236 struct j720tp_softc *sc = arg; 237 struct j720ssp_softc *ssp = sc->sc_ssp; 238 int rawx, rawy; 239 240 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1 << 9); 241 242 if (!sc->sc_enabled) { 243 DPRINTF(("j720tp_intr: !sc_enabled\n")); 244 return 0; 245 } 246 247 j720tp_disable_intr(sc); 248 249 if (j720tp_get_rawxy(sc, &rawx, &rawy)) 250 j720tp_wsmouse_input(sc, rawx, rawy); 251 252 callout_reset(&sc->sc_tpcallout, hz / 32, j720tp_wsmouse_callout, sc); 253 254 return 1; 255 } 256 257 static int 258 j720tp_get_rawxy(struct j720tp_softc *sc, int *rawx, int *rawy) 259 { 260 struct j720ssp_softc *ssp = sc->sc_ssp; 261 int buf[8], data, i; 262 263 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 264 265 /* Send read touch-panel command. */ 266 if (j720ssp_readwrite(ssp, 1, 0xa0, &data, 100) < 0 || data != 0x11) { 267 DPRINTF(("j720tp_get_rawxy: no dummy received\n")); 268 goto out; 269 } 270 271 for (i = 0; i < 8; i++) { 272 if (j720ssp_readwrite(ssp, 0, 0x11, &data, 100) < 0) 273 goto out; 274 buf[i] = data; 275 } 276 277 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 278 279 buf[6] <<= 8; 280 buf[7] <<= 8; 281 for (i = 0; i < 3; i++) { 282 buf[i] |= buf[6] & 0x300; 283 buf[6] >>= 2; 284 buf[i + 3] |= buf[7] & 0x300; 285 buf[7] >>= 2; 286 } 287 288 #if 0 289 DPRINTF(("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n", buf[0], buf[1], 290 buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])); 291 #endif 292 293 *rawx = buf[1]; 294 *rawy = buf[4]; 295 296 return 1; 297 out: 298 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 299 300 /* reset SSP */ 301 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 302 delay(100); 303 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 304 305 DPRINTF(("j720tp_get_rawxy: error %x\n", data)); 306 return 0; 307 } 308 309 static void 310 j720tp_wsmouse_input(struct j720tp_softc *sc, int rawx, int rawy) 311 { 312 int x, y; 313 314 tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y); 315 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 316 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 317 } 318 319 static void 320 j720tp_wsmouse_callout(void *arg) 321 { 322 struct j720tp_softc *sc = arg; 323 struct j720ssp_softc *ssp = sc->sc_ssp; 324 int rawx, rawy, s; 325 326 s = spltty(); 327 328 if (!sc->sc_enabled) { 329 DPRINTF(("j720tp_wsmouse_callout: !sc_enabled\n")); 330 splx(s); 331 return; 332 } 333 334 if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { 335 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); 336 j720tp_enable_intr(sc); 337 } else { 338 if (j720tp_get_rawxy(sc, &rawx, &rawy)) 339 j720tp_wsmouse_input(sc, rawx, rawy); 340 341 callout_schedule(&sc->sc_tpcallout, hz / 32); 342 } 343 344 splx(s); 345 } 346