---
 sys/arch/palm/conf/GENERIC    |    5 +
 sys/arch/palm/conf/RAMDISK    |    6 +
 sys/arch/palm/conf/files.palm |    4 +
 sys/arch/palm/dev/palm_tsc.c  |  361 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 376 insertions(+), 0 deletions(-)
 create mode 100644 sys/arch/palm/dev/palm_tsc.c

diff --git a/sys/arch/palm/conf/GENERIC b/sys/arch/palm/conf/GENERIC
index feff44d..c12bf82 100644
--- a/sys/arch/palm/conf/GENERIC
+++ b/sys/arch/palm/conf/GENERIC
@@ -33,6 +33,7 @@ option        WSDISPLAY_DEFAULTSCREENS=2      # initial 
number of text consoles
 option WSDISPLAY_COMPAT_PCVT           # emulate some ioctls; needed for X11
 
 option USBVERBOSE
+option APERTURE
 
 config         bsd     root on sd1a swap on sd1b 
 
@@ -220,6 +221,10 @@ owtemp* at onewire?                        # Temperature
 # APM emulation
 apm0 at pxaip?
 
+# Touchscreen
+palm_tsc0      at pxaip? addr 0x40500000 size 0x10000
+wsmouse*       at palm_tsc? mux 0
+
 # Pseudo-Devices
 pseudo-device  wsmux           2       # mouse & keyboard multiplexor
 pseudo-device  hotplug         1       # devices hot plugging
diff --git a/sys/arch/palm/conf/RAMDISK b/sys/arch/palm/conf/RAMDISK
index c8c40c9..b22e09f 100644
--- a/sys/arch/palm/conf/RAMDISK
+++ b/sys/arch/palm/conf/RAMDISK
@@ -36,6 +36,8 @@ option        WSDISPLAY_COMPAT_RAWKBD         # provide raw 
scancodes; needed for X11
 option WSDISPLAY_DEFAULTSCREENS=2      # initial number of text consoles
 option WSDISPLAY_COMPAT_PCVT           # emulate some ioctls; needed for X11
 
+option APERTURE
+
 config         bsd     root on rd0a swap on rd0b
 
 # The main bus device
@@ -155,6 +157,10 @@ wsdisplay* at lcd? console ?
 # APM emulation
 apm0           at pxaip?
 
+# Touchscreen
+palm_tsc0      at pxaip? addr 0x40500000 size 0x10000
+wsmouse*       at palm_tsc? mux 0
+
 # Pseudo-Devices
 pseudo-device  wsmux           2       # mouse & keyboard multiplexor
 #pseudo-device crypto          1
diff --git a/sys/arch/palm/conf/files.palm b/sys/arch/palm/conf/files.palm
index 6f960ca..94d8351 100644
--- a/sys/arch/palm/conf/files.palm
+++ b/sys/arch/palm/conf/files.palm
@@ -72,6 +72,10 @@ file arch/palm/dev/palm_udc.c        pxaudc_palm
 attach pxa27x_kpc at pxaip with pxakpc_palm
 file   arch/palm/dev/palm_kpc.c        pxakpc_palm
 
+device palm_tsc: wsmousedev
+attach palm_tsc at pxaip
+file arch/palm/dev/palm_tsc.c          palm_tsc needs-flag
+
 # Bluetooth
 include "dev/bluetooth/files.bluetooth"
 
diff --git a/sys/arch/palm/dev/palm_tsc.c b/sys/arch/palm/dev/palm_tsc.c
new file mode 100644
index 0000000..0a2ec04
--- /dev/null
+++ b/sys/arch/palm/dev/palm_tsc.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2009 Marek Vasut <ma...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/timeout.h>
+#include <sys/kernel.h>
+
+#include <arm/xscale/pxa2x0reg.h>
+#include <arm/xscale/pxa2x0_gpio.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <arm/xscale/pxa2x0var.h>
+#include <arm/xscale/pxa2x0_lcd.h>
+
+struct tsscale {
+       int minx, maxx;
+       int miny, maxy;
+       int swapxy;
+       int resx, resy;
+} palm_tsc_scale = {
+       0x128, 0xe8f, 0xa0, 0xf40, 0, 324, 484
+};
+
+struct palm_tsc_softc {
+       struct device sc_dev;
+       bus_space_tag_t sc_iot;
+       bus_space_handle_t sc_ioh;
+
+
+       struct timeout sc_ts_poll;
+       void *sc_touch_ih;
+       struct device *sc_wsmousedev;
+       int sc_oldx;
+       int sc_oldy;
+       int sc_rawmode;
+       
+       struct tsscale sc_tsscale;
+};
+
+int    palm_tsc_gsrw(struct palm_tsc_softc *, int);
+int    palm_tsc_read_4(struct palm_tsc_softc *, int);
+void   palm_tsc_write_4(struct palm_tsc_softc *, int, int);
+
+int    palm_tsc_match(struct device *, void *, void *);
+void   palm_tsc_attach(struct device *, struct device *, void *);
+
+int    palm_tsc_enable(void *);
+void   palm_tsc_disable(void *);
+int    palm_tsc_ioctl(void *, u_long, caddr_t, int, struct proc *);
+
+void   palm_tsc_power(int, void *);
+void   palm_tsc_poll(void *);
+int    palm_tsc_irq(void *);
+
+
+struct cfattach palm_tsc_ca = {
+       sizeof(struct palm_tsc_softc), palm_tsc_match, palm_tsc_attach
+};
+
+struct cfdriver palm_tsc_cd = {
+       NULL, "palm_tsc", DV_DULL
+};
+
+const struct wsmouse_accessops palm_tsc_accessops = {
+        palm_tsc_enable,
+       palm_tsc_ioctl,
+       palm_tsc_disable
+};
+
+int
+palm_tsc_gsrw(struct palm_tsc_softc *sc, int mask)
+{
+       int timeout, val;
+       for (timeout = 5000; timeout > 0; timeout--) {
+               val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AC97_GSR);
+               if ((val & mask) == mask)
+                       return 0;
+       }
+       return 1;
+}
+int
+palm_tsc_read_4(struct palm_tsc_softc *sc, int reg)
+{
+       int ret;
+       bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
+       if (!palm_tsc_gsrw(sc, GSR_SDONE))
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_GSR, GSR_SDONE | 
GSR_CDONE);
+
+       ret = bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
+       if (!palm_tsc_gsrw(sc, GSR_SDONE))
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_GSR, GSR_SDONE | 
GSR_CDONE);
+
+       return ret;
+}
+
+void
+palm_tsc_write_4(struct palm_tsc_softc *sc, int reg, int val)
+{
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val);
+       if (!palm_tsc_gsrw(sc, GSR_CDONE))
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_GSR, GSR_SDONE | 
GSR_CDONE);
+}
+
+int
+palm_tsc_match(struct device *parent, void *cf, void *aux)
+{
+       struct pxaip_attach_args *pxa = aux;
+       return (pxa->pxa_addr == 0x40500000);
+}
+
+void
+palm_tsc_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct pxaip_attach_args *pxa = aux;
+       struct wsmousedev_attach_args a;  
+       struct palm_tsc_softc *sc = (struct palm_tsc_softc *)self;
+       int s;
+
+       s = spltty();
+       timeout_set(&sc->sc_ts_poll, palm_tsc_poll, sc);
+
+       /* Map registers */
+       sc->sc_iot = pxa->pxa_sa.sa_iot;
+       if (bus_space_map(sc->sc_iot, pxa->pxa_addr, pxa->pxa_size, 0,
+           &sc->sc_ioh) != 0) {
+               splx(s);
+               printf(": can't map regs\n");
+               return;
+       }
+
+       pxa2x0_gpio_set_function(27, GPIO_IN);
+       sc->sc_touch_ih = pxa2x0_gpio_intr_establish(27,
+               IST_EDGE_BOTH, IPL_TTY, palm_tsc_irq, sc, "palm_tscd");
+       if (sc->sc_touch_ih == NULL) {
+               splx(s);
+               printf(": can't establish touchscreen interrupt\n");
+               return;
+       }
+       pxa2x0_gpio_intr_mask(sc->sc_touch_ih);
+
+       /* Configure GPIOs */
+       pxa2x0_gpio_set_function(28, GPIO_ALT_FN_1_IN);         // BITCLK
+       pxa2x0_gpio_set_function(29, GPIO_ALT_FN_1_IN);         // SDATA_IN_0
+       pxa2x0_gpio_set_function(30, GPIO_ALT_FN_2_OUT);        // SDATA_OUT
+       pxa2x0_gpio_set_function(31, GPIO_ALT_FN_2_OUT);        // SYNC
+       pxa2x0_gpio_set_function(89, GPIO_ALT_FN_1_OUT);        // SYSCLK
+       pxa2x0_gpio_set_function(95, GPIO_ALT_FN_1_OUT);        // nRESET
+
+       /* Enable clock */
+       pxa2x0_clkman_config(CKEN_AC97, 1);
+       delay(100);
+
+       /* Cold reset the codec */
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_GCR, 0);
+       delay(100);
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_GCR, GCR_nCRST);
+       delay(100);
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, AC97_CAR, 0);
+
+       /* Wait for codec ready */
+       if (palm_tsc_gsrw(sc, GSR_PCRDY))
+               return;
+
+       /* init phy */
+       palm_tsc_write_4(sc, (0x200 + (0x76<<1)), 0x0030);
+       palm_tsc_write_4(sc, (0x200 + (0x78<<1)), 0x2008);
+
+       /* start TS */
+       palm_tsc_write_4(sc, (0x200 + (0x78<<1)), 0xe008);
+       palm_tsc_read_4(sc, (0x200 + (0x7a<<1)));
+
+       a.accessops = &palm_tsc_accessops;
+       a.accesscookie = sc;
+
+       /* Copy the default scale values to each softc */
+       bcopy(&palm_tsc_scale, &sc->sc_tsscale, sizeof(sc->sc_tsscale));
+               
+       sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+
+       pxa2x0_gpio_intr_unmask(sc->sc_touch_ih);
+       splx(s);
+}
+
+int
+palm_tsc_enable(void *v)
+{
+       struct palm_tsc_softc *sc = v;
+       timeout_del(&sc->sc_ts_poll);
+       return 0;
+}
+
+void
+palm_tsc_disable(void *v)
+{
+       struct palm_tsc_softc *sc = v;
+       timeout_del(&sc->sc_ts_poll);
+}
+
+void
+palm_tsc_power(int why, void *v)
+{
+       struct palm_tsc_softc *sc = v;
+       switch (why) {
+       case PWR_STANDBY:
+       case PWR_SUSPEND:
+               timeout_del(&sc->sc_ts_poll);
+               break;
+       case PWR_RESUME:
+               break;
+       }
+}
+
+void
+palm_tsc_poll(void *v)
+{
+       int s;
+       struct palm_tsc_softc *sc = v;
+       s = spltty();
+       pxa2x0_gpio_intr_unmask(sc->sc_touch_ih);
+       splx(s);
+       palm_tsc_irq(v);
+}
+
+#define TS_STABLE 8
+int
+palm_tsc_irq(void *v)
+{
+       int s;
+       int x = 0, y = 0, t;
+       int i, timeout;
+       struct palm_tsc_softc *sc = v;
+
+       s = spltty();
+
+       if (pxa2x0_gpio_get_bit(27)) {
+               timeout_add(&sc->sc_ts_poll, hz/20);
+               pxa2x0_gpio_intr_mask(sc->sc_touch_ih);
+
+               palm_tsc_write_4(sc, (0x200 + (0x54<<1)), 0xdfff);
+
+               i = 0;
+               timeout = 10;
+               while(--timeout && i < 3) {
+                       palm_tsc_write_4(sc, (0x200 + (0x76<<1)), 0x9030);
+                       while(palm_tsc_read_4(sc, (0x200 + (0x76<<1))) & 
0x8000);
+                       t = palm_tsc_read_4(sc, (0x200 + (0x7a<<1)));
+                       if ((t & 0x9000) == 0x9000) {
+                               x += t & 0xfff;
+                               i++;
+                       }
+               }
+               if (!timeout)
+                       goto penrel;
+               x /= i;
+
+               i = 0;
+               timeout = 10;
+               while(--timeout && i < 3) {
+                       palm_tsc_write_4(sc, (0x200 + (0x76<<1)), 0xa030);
+                       while(palm_tsc_read_4(sc, (0x200 + (0x76<<1))) & 
0x8000);
+                       t = palm_tsc_read_4(sc, (0x200 + (0x7a<<1)));
+                       if ((t & 0xa000) == 0xa000) {
+                               y += t & 0xfff;
+                               i++;
+                       }
+               }
+               if (!timeout)
+                       goto penrel;
+               y /= i;
+
+               splx(s);
+                       if (!sc->sc_rawmode) {
+                               x = ((x - sc->sc_tsscale.minx) * 
(sc->sc_tsscale.resx)) / (sc->sc_tsscale.maxx - sc->sc_tsscale.minx);
+                               y = ((y - sc->sc_tsscale.miny) * 
(sc->sc_tsscale.resy)) / (sc->sc_tsscale.maxy - sc->sc_tsscale.miny);
+                       }
+                       x = sc->sc_tsscale.maxx - x;
+                       y = sc->sc_tsscale.maxy - y;
+
+                       sc->sc_oldx = x;
+                       sc->sc_oldy = y;
+                       wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0 /* z */, 0 
/* w */,
+                               WSMOUSE_INPUT_ABSOLUTE_X | 
WSMOUSE_INPUT_ABSOLUTE_Y |
+                               WSMOUSE_INPUT_ABSOLUTE_Z);
+                       return 1;
+       }
+penrel:
+       splx(s);
+       wsmouse_input(sc->sc_wsmousedev, 0, sc->sc_oldx, sc->sc_oldy,
+               0 /* z */, 0 /* w */,
+               WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
+               WSMOUSE_INPUT_ABSOLUTE_Z);
+
+       return 1;
+}
+
+int
+palm_tsc_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+       int error = 0;
+       struct palm_tsc_softc *sc = v;
+       struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
+       switch (cmd) {
+       case WSMOUSEIO_SCALIBCOORDS:
+               if (!(wsmc->minx >= 0 && wsmc->maxx >= 0 &&
+                   wsmc->miny >= 0 && wsmc->maxy >= 0 &&
+                   wsmc->resx >= 0 && wsmc->resy >= 0 &&
+                   wsmc->minx < 32768 && wsmc->maxx < 32768 &&
+                   wsmc->miny < 32768 && wsmc->maxy < 32768 &&
+                   wsmc->resx < 32768 && wsmc->resy < 32768 &&
+                   wsmc->swapxy >= 0 && wsmc->swapxy <= 1 &&
+                   wsmc->samplelen >= 0 && wsmc->samplelen <= 1))
+                       return (EINVAL);
+
+               sc->sc_tsscale.minx = wsmc->minx;
+               sc->sc_tsscale.maxx = wsmc->maxx;
+               sc->sc_tsscale.miny = wsmc->miny;
+               sc->sc_tsscale.maxy = wsmc->maxy;
+               sc->sc_tsscale.swapxy = wsmc->swapxy;
+               sc->sc_tsscale.resx = wsmc->resx;
+               sc->sc_tsscale.resy = wsmc->resy;
+               sc->sc_rawmode = wsmc->samplelen;
+               break;
+       case WSMOUSEIO_GCALIBCOORDS:
+               wsmc->minx = sc->sc_tsscale.minx;
+               wsmc->maxx = sc->sc_tsscale.maxx;
+               wsmc->miny = sc->sc_tsscale.miny;
+               wsmc->maxy = sc->sc_tsscale.maxy;
+               wsmc->swapxy = sc->sc_tsscale.swapxy;
+               wsmc->resx = sc->sc_tsscale.resx;
+               wsmc->resy = sc->sc_tsscale.resy;
+               wsmc->samplelen = sc->sc_rawmode;
+               break;
+       case WSMOUSEIO_GTYPE:
+               *(u_int *)data = WSMOUSE_TYPE_TPANEL;
+               break;
+       default:
+               error = ENOTTY;
+               break;
+       }
+       return (error);
+}
-- 
1.7.0.5

Reply via email to