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