fix touchpanel broken behavior:
- when moving the stylus, the cursor was updated only when the screen was released - when moving the stylus for too long, the kernel crashed This was caused by improper delays in SSP read and write, and by interrupt hammering while the screen is touched). Both led to the machine handling interrupts all the time and been unable to schedule the X server, therefore the lack of cursor refresh. The problem is fixed by - masking touchpanel interrupts as soon as we are already handling them - creating a kernel thread (j720ssp) that takes care of keyboard and touchpanel I/O, instead of doing it in a softintr. - reducing delays in j720ssp_readwrite operations from 5ms to 0.1ms. NB: If the delay in j720ssp_readwrite operation is lowered to 0.1, then switching on the screen using the power key pushes brightness to maximum. In order to avoid this, we introduce a wait argument to j720ssp_readwrite, which specify how many microseconds we have to wait. j720ssp_readwrite is called with wait = 100 everywhere except in j720lcdparam where it is called with wait = 500. That way it works.
This commit is contained in:
parent
c7acd88451
commit
100872541e
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: j720ssp.c,v 1.8 2002/07/22 20:55:48 manu Exp $ */
|
||||
/* $NetBSD: j720ssp.c,v 1.9 2002/09/13 22:44:58 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -77,10 +77,11 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/lock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/config_hook.h>
|
||||
|
@ -115,18 +116,27 @@ struct j720ssp_softc {
|
|||
|
||||
void *sc_kbdsi;
|
||||
void *sc_tpsi;
|
||||
struct callout sc_tptimeout;
|
||||
int sc_enabled;
|
||||
};
|
||||
|
||||
struct proc *sc_ssp_kthread;
|
||||
int sc_ssp_status;
|
||||
struct simplelock sc_ssp_status_lock;
|
||||
};
|
||||
/* Values for struct softc's sc_ssp_status */
|
||||
#define J720_SSP_STATUS_NONE 0
|
||||
#define J720_SSP_STATUS_TP 1
|
||||
#define J720_SSP_STATUS_KBD 2
|
||||
|
||||
void j720ssp_create_kthread(void *);
|
||||
void j720ssp_kthread(void *);
|
||||
int j720kbd_intr(void *);
|
||||
int j720tp_intr(void *);
|
||||
void j720kbdsoft(void *);
|
||||
void j720tpsoft(void *);
|
||||
void j720tp_timeout(void *);
|
||||
void j720kbd_poll(void *);
|
||||
int j720tp_poll(void *);
|
||||
|
||||
int j720lcdparam(void *, int, long, void *);
|
||||
static void j720kbd_read(struct j720ssp_softc *, char *);
|
||||
static int j720ssp_readwrite(struct j720ssp_softc *, int, int, int *);
|
||||
static int j720ssp_readwrite(struct j720ssp_softc *, int, int, int *, int);
|
||||
|
||||
int j720sspprobe(struct device *, struct cfdata *, void *);
|
||||
void j720sspattach(struct device *, struct device *, void *);
|
||||
|
@ -221,7 +231,9 @@ j720sspattach(struct device *parent, struct device *self, void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
sc->sc_kbdsi = softintr_establish(IPL_SOFTCLOCK, j720kbdsoft, sc);
|
||||
sc->sc_ssp_status = J720_SSP_STATUS_NONE;
|
||||
simple_lock_init(&sc->sc_ssp_status_lock);
|
||||
kthread_create(j720ssp_create_kthread, sc);
|
||||
|
||||
sc->sc_enabled = 0;
|
||||
|
||||
|
@ -278,10 +290,8 @@ j720sspattach(struct device *parent, struct device *self, void *aux)
|
|||
}
|
||||
|
||||
j720tp_disable(sc);
|
||||
callout_init(&sc->sc_tptimeout);
|
||||
|
||||
/* Setup touchpad interrupt */
|
||||
sc->sc_tpsi = softintr_establish(IPL_SOFTCLOCK, j720tpsoft, sc);
|
||||
sa11x0_intr_establish(0, 9, 1, IPL_BIO, j720tp_intr, sc);
|
||||
|
||||
/* LCD control is on the same bus */
|
||||
|
@ -300,6 +310,53 @@ j720sspattach(struct device *parent, struct device *self, void *aux)
|
|||
CONFIG_HOOK_SHARE, j720lcdparam, sc);
|
||||
}
|
||||
|
||||
void
|
||||
j720ssp_create_kthread(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct j720ssp_softc *sc = arg;
|
||||
|
||||
if (kthread_create1(j720ssp_kthread, sc,
|
||||
&sc->sc_ssp_kthread, "j720ssp"))
|
||||
panic("j720ssp_create_kthread");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
j720ssp_kthread(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct j720ssp_softc *sc = arg;
|
||||
int ssp_status;
|
||||
|
||||
while (1) {
|
||||
if (ssp_status & J720_SSP_STATUS_TP)
|
||||
tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", hz / 25);
|
||||
else
|
||||
tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", 0);
|
||||
|
||||
simple_lock(&sc->sc_ssp_status_lock);
|
||||
ssp_status = sc->sc_ssp_status;
|
||||
sc->sc_ssp_status &= ~J720_SSP_STATUS_KBD;
|
||||
simple_unlock(&sc->sc_ssp_status_lock);
|
||||
|
||||
if (ssp_status & J720_SSP_STATUS_KBD)
|
||||
j720kbd_poll(sc);
|
||||
|
||||
if (ssp_status & J720_SSP_STATUS_TP) {
|
||||
if (j720tp_poll(sc) == 0) {
|
||||
simple_lock(&sc->sc_ssp_status_lock);
|
||||
sc->sc_ssp_status &= ~J720_SSP_STATUS_TP;
|
||||
simple_unlock(&sc->sc_ssp_status_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
j720kbd_submatch(struct device *parant, struct cfdata *cf, void *aux) {
|
||||
|
||||
|
@ -361,16 +418,11 @@ j720kbd_intr(void *arg)
|
|||
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1);
|
||||
|
||||
/*
|
||||
* Schedule a soft interrupt to process at lower priority,
|
||||
* as reading keycodes takes time.
|
||||
*
|
||||
* Interrupts are generated every 25-33ms as long as there
|
||||
* are unprocessed key events. So it is not a good idea to
|
||||
* use callout to call j720kbdsoft after some delay in hope
|
||||
* of reducing interrupts.
|
||||
*/
|
||||
softintr_schedule(sc->sc_kbdsi);
|
||||
simple_lock(&sc->sc_ssp_status_lock);
|
||||
sc->sc_ssp_status |= J720_SSP_STATUS_KBD;
|
||||
simple_unlock(&sc->sc_ssp_status_lock);
|
||||
|
||||
wakeup(&sc->sc_ssp_kthread);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
@ -382,13 +434,18 @@ j720tp_intr(void *arg)
|
|||
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9);
|
||||
|
||||
softintr_schedule(sc->sc_tpsi);
|
||||
simple_lock(&sc->sc_ssp_status_lock);
|
||||
sc->sc_ssp_status |= J720_SSP_STATUS_TP;
|
||||
simple_unlock(&sc->sc_ssp_status_lock);
|
||||
|
||||
j720tp_disable(sc);
|
||||
wakeup(&sc->sc_ssp_kthread);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
j720kbdsoft(void *arg)
|
||||
j720kbd_poll(void *arg)
|
||||
{
|
||||
struct j720ssp_softc *sc = arg;
|
||||
int s, type, value;
|
||||
|
@ -427,18 +484,18 @@ j720kbd_read(struct j720ssp_softc *sc, char *buf)
|
|||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
|
||||
|
||||
/* send scan keycode command */
|
||||
if (j720ssp_readwrite(sc, 1, 0x900, &data) < 0 ||
|
||||
if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 ||
|
||||
data != 0x88)
|
||||
goto out;
|
||||
|
||||
/* read numbers of scancode available */
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0)
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
|
||||
goto out;
|
||||
BIT_INVERT(data);
|
||||
count = data;
|
||||
|
||||
for(; count; count--) {
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0)
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
|
||||
goto out;
|
||||
BIT_INVERT(data);
|
||||
*buf++ = data;
|
||||
|
@ -465,21 +522,32 @@ out:
|
|||
printf("j720kbd_read: error %x\n", data);
|
||||
}
|
||||
|
||||
void
|
||||
j720tpsoft(void *arg)
|
||||
int
|
||||
j720tp_poll(void *arg)
|
||||
{
|
||||
struct j720ssp_softc *sc = arg;
|
||||
int buf[8], data, i, x, y;
|
||||
|
||||
/*
|
||||
* If touch panel is not touched anymore,
|
||||
* stop polling and re-enable interrupt
|
||||
*/
|
||||
if (bus_space_read_4(sc->sc_iot,
|
||||
sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) {
|
||||
wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
|
||||
j720tp_enable(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
|
||||
|
||||
/* send read touchpanel command */
|
||||
if (j720ssp_readwrite(sc, 1, 0x500, &data) < 0 ||
|
||||
if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 ||
|
||||
data != 0x88)
|
||||
goto out;
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0)
|
||||
if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
|
||||
goto out;
|
||||
BIT_INVERT(data);
|
||||
buf[i] = data;
|
||||
|
@ -496,7 +564,7 @@ j720tpsoft(void *arg)
|
|||
buf[7] >>= 2;
|
||||
}
|
||||
#if 0
|
||||
printf("j720tpsoft: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2],
|
||||
printf("j720tp_poll: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2],
|
||||
buf[3], buf[4], buf[5]);
|
||||
#endif
|
||||
|
||||
|
@ -505,9 +573,7 @@ j720tpsoft(void *arg)
|
|||
wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0,
|
||||
WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
|
||||
|
||||
callout_reset(&sc->sc_tptimeout, hz / 10, j720tp_timeout, sc);
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
out:
|
||||
*buf = 0;
|
||||
|
@ -517,25 +583,9 @@ out:
|
|||
bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307);
|
||||
delay(100);
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
|
||||
printf("j720tpsoft: error %x\n", data);
|
||||
}
|
||||
printf("j720tp_poll: error %x\n", data);
|
||||
|
||||
void
|
||||
j720tp_timeout(void *arg)
|
||||
{
|
||||
struct j720ssp_softc *sc = arg;
|
||||
|
||||
#if 0
|
||||
/* XXX I don't this this is necessary (untested) */
|
||||
if (bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) &
|
||||
(1 << 9)) {
|
||||
/* Touchpad is still pressed */
|
||||
callout_reset(&sc->sc_tptimeout, hz / 10, j720tp_timeout, sc);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -642,7 +692,7 @@ j720lcdparam(void *ctx, int type, long id, void *msg)
|
|||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (j720ssp_readwrite(sc, 1, data[i], &data[i]) < 0)
|
||||
if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0)
|
||||
goto out;
|
||||
}
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
|
||||
|
@ -668,7 +718,12 @@ out:
|
|||
}
|
||||
|
||||
static int
|
||||
j720ssp_readwrite(struct j720ssp_softc *sc, int drainfifo, int in, int *out)
|
||||
j720ssp_readwrite(sc, drainfifo, in, out, wait)
|
||||
struct j720ssp_softc *sc;
|
||||
int drainfifo;
|
||||
int in;
|
||||
int *out;
|
||||
int wait;
|
||||
{
|
||||
int timo;
|
||||
|
||||
|
@ -683,13 +738,13 @@ j720ssp_readwrite(struct j720ssp_softc *sc, int drainfifo, int in, int *out)
|
|||
SR_RNE)
|
||||
bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR);
|
||||
#if 1
|
||||
delay(5000);
|
||||
delay(wait);
|
||||
#endif
|
||||
}
|
||||
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in);
|
||||
|
||||
delay(5000);
|
||||
delay(wait);
|
||||
timo = 100000;
|
||||
while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE))
|
||||
if (--timo == 0) {
|
||||
|
|
Loading…
Reference in New Issue