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 $ */
5 * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org>
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.
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.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: zrc.c,v 1.5 2007/10/17 19:58:35 garbled Exp $");
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>
29 #include <dev/wscons/wsconsio.h>
30 #include <dev/wscons/wskbdvar.h>
31 #include <dev/wscons/wsksymdef.h>
32 #include <dev/wscons/wsksymvar.h>
34 #include <arm/xscale/pxa2x0reg.h>
35 #include <arm/xscale/pxa2x0_gpio.h>
37 #include <machine/intr.h>
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>
44 #define RESCAN_INTERVAL (hz/100)
46 #define KEY_RELEASE 0 /* button release */
47 #define KEY_VOL_DOWN 1
54 #define KEY_EARPHONE 8
57 static const char *zrc_keyname
[] = {
58 "(release)", "volume down", "mute", "rewind", "volume up",
59 "forward", "play", "stop", "(earphone)"
64 int min
; /* minimum ADC value or INT_MIN */
65 int key
; /* remote control key number */
68 /* Values match the resistors in the CE-RH2 remote control. */
69 static const struct zrc_akey zrc_akeytab_c3000
[] = {
71 { 202, KEY_VOL_DOWN
},
78 { INT_MIN
, KEY_EARPHONE
}
81 static const struct zrc_akey
*zrc_akeytab
= zrc_akeytab_c3000
;
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
97 static int zrc_match(struct device
*, struct cfdata
*, void *);
98 static void zrc_attach(struct device
*, struct device
*, void *);
100 CFATTACH_DECL_NEW(zrc
, sizeof(struct zrc_softc
),
101 zrc_match
, zrc_attach
, NULL
, NULL
);
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);
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
*);
112 struct wskbd_accessops zrc_accessops
= {
118 #define KC(n) KS_KEYCODE(n)
120 /* XXX what keys should be generated in translated mode? */
121 static const keysym_t zrc_keydesc
[] = {
122 KC(KEY_VOL_DOWN
), KS_minus
,
124 KC(KEY_REWIND
), KS_b
,
125 KC(KEY_VOL_UP
), KS_plus
,
126 KC(KEY_FORWARD
), KS_f
,
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
,
148 static const struct wscons_keydesc zrc_keydesctab
[] = {
149 {KB_US
, 0, sizeof(zrc_keydesc
)/sizeof(keysym_t
), zrc_keydesc
},
153 struct wskbd_mapdata zrc_keymapdata
= {
154 zrc_keydesctab
, KB_US
160 zrc_match(device_t parent
, cfdata_t cf
, void *aux
)
169 zrc_attach(device_t parent
, device_t self
, void *aux
)
171 struct zrc_softc
*sc
= device_private(self
);
172 struct wskbddev_attach_args a
;
176 aprint_normal(": CE-RH2 remote control\n");
179 /* Configure remote control interrupt handling. */
180 callout_init(&sc
->sc_to
, 0);
181 callout_setfunc(&sc
->sc_to
, zrc_timeout
, sc
);
183 /* Establish interrput */
184 pxa2x0_gpio_set_function(C3000_RC_IRQ_PIN
, GPIO_IN
);
185 sc
->sc_ih
= pxa2x0_gpio_intr_establish(C3000_RC_IRQ_PIN
,
186 IST_EDGE_BOTH
, IPL_BIO
, zrc_intr
, sc
);
187 if (sc
->sc_ih
== NULL
) {
188 aprint_error_dev(sc
->sc_dev
, "couldn't establish interrupt.\n");
192 /* Enable the pullup while waiting for an interrupt. */
193 scoop_akin_pullup(1);
195 sc
->sc_keydown
= KEY_RELEASE
;
198 a
.keymap
= &zrc_keymapdata
;
199 a
.accessops
= &zrc_accessops
;
202 sc
->sc_wskbddev
= config_found(self
, &a
, wskbddevprint
);
208 struct zrc_softc
*sc
= v
;
210 /* just return if remote control isn't present */
212 pxa2x0_gpio_intr_mask(sc
->sc_ih
);
213 scoop_akin_pullup(0);
214 sc
->sc_key
= zrc_scan();
217 callout_schedule(&sc
->sc_to
, RESCAN_INTERVAL
);
225 struct zrc_softc
*sc
= v
;
229 switch (sc
->sc_scans
) {
233 /* wait for a stable read */
234 if (sc
->sc_key
== key
)
241 callout_schedule(&sc
->sc_to
, RESCAN_INTERVAL
);
244 /* generate key press event */
245 if (sc
->sc_key
!= key
) {
257 printf("%s: %s pressed (%d noise)\n",
258 device_xname(sc
->sc_dev
),
259 zrc_keyname
[key
], sc
->sc_noise
);
261 sc
->sc_keydown
= key
;
263 zrc_input(sc
, key
, 1);
266 callout_schedule(&sc
->sc_to
, RESCAN_INTERVAL
);
270 /* wait for key release, permit noise */
271 if (sc
->sc_key
== key
) {
272 if (sc
->sc_scans
== 5)
277 callout_schedule(&sc
->sc_to
, RESCAN_INTERVAL
);
280 /* generate key release event */
281 if (sc
->sc_keydown
!= KEY_RELEASE
) {
282 zrc_input(sc
, sc
->sc_keydown
, 0);
284 printf("%s: %s released (%d noise)\n",
285 device_xname(sc
->sc_dev
),
286 zrc_keyname
[sc
->sc_keydown
], sc
->sc_noise
);
288 sc
->sc_keydown
= KEY_RELEASE
;
292 /* unmask interrupt again */
293 callout_stop(&sc
->sc_to
);
295 scoop_akin_pullup(1);
296 pxa2x0_gpio_intr_unmask(sc
->sc_ih
);
306 /* XXX MAX1111 command word - also appears in zaurus_apm.c */
307 #define MAXCTRL_PD0 (1<<0)
308 #define MAXCTRL_PD1 (1<<1)
309 #define MAXCTRL_SGL (1<<2)
310 #define MAXCTRL_UNI (1<<3)
311 #define MAXCTRL_SEL_SHIFT 4
312 #define MAXCTRL_STR (1<<7)
314 #define C3000_ADCCH_ZRC 0
315 val
= zssp_read_max1111(MAXCTRL_PD0
| MAXCTRL_PD1
| MAXCTRL_SGL
|
316 MAXCTRL_UNI
| (C3000_ADCCH_ZRC
<< MAXCTRL_SEL_SHIFT
) |
318 for (i
= 0; zrc_akeytab
[i
].min
!= INT_MIN
; i
++)
319 if (val
>= zrc_akeytab
[i
].min
)
321 return zrc_akeytab
[i
].key
;
325 zrc_input(struct zrc_softc
*sc
, int key
, int down
)
327 u_int type
= down
? WSCONS_EVENT_KEY_DOWN
: WSCONS_EVENT_KEY_UP
;
332 #ifdef WSDISPLAY_COMPAT_RAWKBD
338 c
= zrc_xt_keymap
[key
];
340 cbuf
[ncbuf
++] = 0xe0;
341 cbuf
[ncbuf
] = c
& 0x7f;
347 wskbd_rawinput(sc
->sc_wskbddev
, cbuf
, ncbuf
);
350 wskbd_input(sc
->sc_wskbddev
, type
, key
);
356 zrc_enable(void *v
, int on
)
363 zrc_set_leds(void *v
, int on
)
370 zrc_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
372 #ifdef WSDISPLAY_COMPAT_RAWKBD
373 struct zrc_softc
*sc
= v
;
378 *(int *)data
= WSKBD_TYPE_ZAURUS
;
380 case WSKBDIO_SETLEDS
:
382 case WSKBDIO_GETLEDS
:
385 #ifdef WSDISPLAY_COMPAT_RAWKBD
386 case WSKBDIO_SETMODE
:
387 sc
->sc_rawkbd
= (*(int *)data
== WSKBD_RAW
);