1 /* $NetBSD: zrc.c,v 1.5 2007/10/17 19:58:35 garbled Exp $ */ 2 /* $OpenBSD: zaurus_remote.c,v 1.1 2005/11/17 05:26:31 uwe Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: zrc.c,v 1.5 2007/10/17 19:58:35 garbled Exp $"); 22 23 #include <sys/param.h> 24 #include <sys/device.h> 25 #include <sys/kernel.h> 26 #include <sys/callout.h> 27 #include <sys/systm.h> 28 29 #include <dev/wscons/wsconsio.h> 30 #include <dev/wscons/wskbdvar.h> 31 #include <dev/wscons/wsksymdef.h> 32 #include <dev/wscons/wsksymvar.h> 33 34 #include <arm/xscale/pxa2x0reg.h> 35 #include <arm/xscale/pxa2x0_gpio.h> 36 37 #include <machine/intr.h> 38 39 #include <zaurus/dev/scoopvar.h> 40 #include <zaurus/dev/zsspvar.h> 41 #include <zaurus/zaurus/zaurus_reg.h> 42 #include <zaurus/zaurus/zaurus_var.h> 43 44 #define RESCAN_INTERVAL (hz/100) 45 46 #define KEY_RELEASE 0 /* button release */ 47 #define KEY_VOL_DOWN 1 48 #define KEY_MUTE 2 49 #define KEY_REWIND 3 50 #define KEY_VOL_UP 4 51 #define KEY_FORWARD 5 52 #define KEY_PLAY 6 53 #define KEY_STOP 7 54 #define KEY_EARPHONE 8 55 56 #ifdef DEBUG 57 static const char *zrc_keyname[] = { 58 "(release)", "volume down", "mute", "rewind", "volume up", 59 "forward", "play", "stop", "(earphone)" 60 }; 61 #endif 62 63 struct zrc_akey { 64 int min; /* minimum ADC value or INT_MIN */ 65 int key; /* remote control key number */ 66 }; 67 68 /* Values match the resistors in the CE-RH2 remote control. */ 69 static const struct zrc_akey zrc_akeytab_c3000[] = { 70 { 238, KEY_RELEASE }, 71 { 202, KEY_VOL_DOWN }, 72 { 168, KEY_MUTE }, 73 { 135, KEY_REWIND }, 74 { 105, KEY_VOL_UP }, 75 { 74, KEY_FORWARD }, 76 { 42, KEY_PLAY }, 77 { 12, KEY_STOP }, 78 { INT_MIN, KEY_EARPHONE } 79 }; 80 81 static const struct zrc_akey *zrc_akeytab = zrc_akeytab_c3000; 82 83 struct zrc_softc { 84 struct device sc_dev; 85 struct callout sc_to; 86 void *sc_ih; 87 int sc_key; /* being scanned */ 88 int sc_scans; /* rescan counter */ 89 int sc_noise; /* discard if too noisy? */ 90 int sc_keydown; /* currently pressed key */ 91 struct device *sc_wskbddev; 92 #ifdef WSDISPLAY_COMPAT_RAWKBD 93 int sc_rawkbd; 94 #endif 95 }; 96 97 static int zrc_match(struct device *, struct cfdata *, void *); 98 static void zrc_attach(struct device *, struct device *, void *); 99 100 CFATTACH_DECL(zrc, sizeof(struct zrc_softc), 101 zrc_match, zrc_attach, NULL, NULL); 102 103 static int zrc_intr(void *); 104 static void zrc_timeout(void *); 105 static int zrc_scan(void); 106 static void zrc_input(struct zrc_softc *, int, int); 107 108 static int zrc_enable(void *, int); 109 static void zrc_set_leds(void *, int); 110 static int zrc_ioctl(void *, u_long, void *, int, struct lwp *); 111 112 struct wskbd_accessops zrc_accessops = { 113 zrc_enable, 114 zrc_set_leds, 115 zrc_ioctl, 116 }; 117 118 #define KC(n) KS_KEYCODE(n) 119 120 /* XXX what keys should be generated in translated mode? */ 121 static const keysym_t zrc_keydesc[] = { 122 KC(KEY_VOL_DOWN), KS_minus, 123 KC(KEY_MUTE), KS_m, 124 KC(KEY_REWIND), KS_b, 125 KC(KEY_VOL_UP), KS_plus, 126 KC(KEY_FORWARD), KS_f, 127 KC(KEY_PLAY), KS_p, 128 KC(KEY_STOP), KS_s, 129 }; 130 131 #ifdef WSDISPLAY_COMPAT_RAWKBD 132 #define RAWKEY_AudioRewind 0xa0 133 #define RAWKEY_AudioForward 0xa1 134 #define RAWKEY_AudioPlay 0xa2 135 #define RAWKEY_AudioStop 0xa3 136 static const keysym_t zrc_xt_keymap[] = { 137 /* KC(KEY_RELEASE), */ RAWKEY_Null, 138 /* KC(KEY_VOL_DOWN), */ RAWKEY_AudioLower, 139 /* KC(KEY_MUTE), */ RAWKEY_AudioMute, 140 /* KC(KEY_REWIND), */ RAWKEY_AudioRewind, 141 /* KC(KEY_VOL_UP), */ RAWKEY_AudioRaise, 142 /* KC(KEY_FORWARD), */ RAWKEY_AudioForward, 143 /* KC(KEY_PLAY), */ RAWKEY_AudioPlay, 144 /* KC(KEY_STOP), */ RAWKEY_AudioStop, 145 }; 146 #endif 147 148 static const struct wscons_keydesc zrc_keydesctab[] = { 149 {KB_US, 0, sizeof(zrc_keydesc)/sizeof(keysym_t), zrc_keydesc}, 150 {0, 0, 0, 0} 151 }; 152 153 struct wskbd_mapdata zrc_keymapdata = { 154 zrc_keydesctab, KB_US 155 }; 156 157 #undef KC 158 159 static int 160 zrc_match(struct device *parent, struct cfdata *cf, void *aux) 161 { 162 163 if (ZAURUS_ISC3000) 164 return 1; 165 return 0; 166 } 167 168 static void 169 zrc_attach(struct device *parent, struct device *self, void *aux) 170 { 171 struct zrc_softc *sc = (struct zrc_softc *)self; 172 struct wskbddev_attach_args a; 173 174 /* Configure remote control interrupt handling. */ 175 callout_init(&sc->sc_to, 0); 176 callout_setfunc(&sc->sc_to, zrc_timeout, sc); 177 pxa2x0_gpio_set_function(C3000_RC_IRQ_PIN, GPIO_IN); 178 sc->sc_ih = pxa2x0_gpio_intr_establish(C3000_RC_IRQ_PIN, 179 IST_EDGE_BOTH, IPL_BIO, zrc_intr, sc); 180 181 /* Enable the pullup while waiting for an interrupt. */ 182 scoop_akin_pullup(1); 183 184 sc->sc_keydown = KEY_RELEASE; 185 186 printf(": CE-RH2 remote control\n"); 187 188 a.console = 0; 189 a.keymap = &zrc_keymapdata; 190 a.accessops = &zrc_accessops; 191 a.accesscookie = sc; 192 193 sc->sc_wskbddev = config_found(self, &a, wskbddevprint); 194 } 195 196 static int 197 zrc_intr(void *v) 198 { 199 struct zrc_softc *sc = v; 200 201 /* just return if remote control isn't present */ 202 203 pxa2x0_gpio_intr_mask(sc->sc_ih); 204 scoop_akin_pullup(0); 205 sc->sc_key = zrc_scan(); 206 sc->sc_scans = 0; 207 sc->sc_noise = 0; 208 callout_schedule(&sc->sc_to, RESCAN_INTERVAL); 209 210 return 1; 211 } 212 213 static void 214 zrc_timeout(void *v) 215 { 216 struct zrc_softc *sc = v; 217 int key; 218 219 key = zrc_scan(); 220 switch (sc->sc_scans) { 221 case 0: 222 case 1: 223 case 2: 224 /* wait for a stable read */ 225 if (sc->sc_key == key) 226 sc->sc_scans++; 227 else { 228 sc->sc_key = key; 229 sc->sc_scans = 0; 230 sc->sc_noise++; 231 } 232 callout_schedule(&sc->sc_to, RESCAN_INTERVAL); 233 break; 234 case 3: 235 /* generate key press event */ 236 if (sc->sc_key != key) { 237 key = sc->sc_key; 238 sc->sc_noise++; 239 } 240 sc->sc_scans++; 241 switch (key) { 242 case KEY_EARPHONE: 243 case KEY_RELEASE: 244 sc->sc_scans = 6; 245 break; 246 default: 247 #ifdef DEBUG 248 printf("%s pressed (%d noise)\n", zrc_keyname[key], 249 sc->sc_noise); 250 #endif 251 sc->sc_keydown = key; 252 sc->sc_noise = 0; 253 zrc_input(sc, key, 1); 254 break; 255 } 256 callout_schedule(&sc->sc_to, RESCAN_INTERVAL); 257 break; 258 case 4: 259 case 5: 260 /* wait for key release, permit noise */ 261 if (sc->sc_key == key) { 262 if (sc->sc_scans == 5) 263 sc->sc_noise++; 264 sc->sc_scans = 4; 265 } else 266 sc->sc_scans++; 267 callout_schedule(&sc->sc_to, RESCAN_INTERVAL); 268 break; 269 case 6: 270 /* generate key release event */ 271 if (sc->sc_keydown != KEY_RELEASE) { 272 zrc_input(sc, sc->sc_keydown, 0); 273 #ifdef DEBUG 274 printf("%s released (%d noise)\n", 275 zrc_keyname[sc->sc_keydown], sc->sc_noise); 276 #endif 277 sc->sc_keydown = KEY_RELEASE; 278 } 279 /* FALLTHROUGH */ 280 default: 281 /* unmask interrupt again */ 282 callout_stop(&sc->sc_to); 283 sc->sc_scans = 7; 284 scoop_akin_pullup(1); 285 pxa2x0_gpio_intr_unmask(sc->sc_ih); 286 } 287 } 288 289 static int 290 zrc_scan(void) 291 { 292 int val; 293 int i; 294 295 /* XXX MAX1111 command word - also appears in zaurus_apm.c */ 296 #define MAXCTRL_PD0 (1<<0) 297 #define MAXCTRL_PD1 (1<<1) 298 #define MAXCTRL_SGL (1<<2) 299 #define MAXCTRL_UNI (1<<3) 300 #define MAXCTRL_SEL_SHIFT 4 301 #define MAXCTRL_STR (1<<7) 302 303 #define C3000_ADCCH_ZRC 0 304 val = zssp_read_max1111(MAXCTRL_PD0 | MAXCTRL_PD1 | MAXCTRL_SGL | 305 MAXCTRL_UNI | (C3000_ADCCH_ZRC << MAXCTRL_SEL_SHIFT) | 306 MAXCTRL_STR); 307 for (i = 0; zrc_akeytab[i].min != INT_MIN; i++) 308 if (val >= zrc_akeytab[i].min) 309 break; 310 return zrc_akeytab[i].key; 311 } 312 313 static void 314 zrc_input(struct zrc_softc *sc, int key, int down) 315 { 316 u_int type = down ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 317 int s; 318 319 s = spltty(); 320 321 #ifdef WSDISPLAY_COMPAT_RAWKBD 322 if (sc->sc_rawkbd) { 323 int c; 324 u_char cbuf[2]; 325 int ncbuf = 0; 326 327 c = zrc_xt_keymap[key]; 328 if (c & 0x80) 329 cbuf[ncbuf++] = 0xe0; 330 cbuf[ncbuf] = c & 0x7f; 331 332 if (!down) 333 cbuf[ncbuf] |= 0x80; 334 ncbuf++; 335 336 wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf); 337 } else 338 #endif 339 wskbd_input(sc->sc_wskbddev, type, key); 340 341 splx(s); 342 } 343 344 static int 345 zrc_enable(void *v, int on) 346 { 347 348 return 0; 349 } 350 351 static void 352 zrc_set_leds(void *v, int on) 353 { 354 355 /* Nothing to do */ 356 } 357 358 static int 359 zrc_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 360 { 361 #ifdef WSDISPLAY_COMPAT_RAWKBD 362 struct zrc_softc *sc = v; 363 #endif 364 365 switch (cmd) { 366 case WSKBDIO_GTYPE: 367 *(int *)data = WSKBD_TYPE_ZAURUS; 368 return 0; 369 case WSKBDIO_SETLEDS: 370 return 0; 371 case WSKBDIO_GETLEDS: 372 *(int *)data = 0; 373 return 0; 374 #ifdef WSDISPLAY_COMPAT_RAWKBD 375 case WSKBDIO_SETMODE: 376 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW); 377 return 0; 378 #endif 379 } 380 return EPASSTHROUGH; 381 } 382