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