Module Name: src Committed By: nonaka Date: Sat May 22 15:37:58 UTC 2010
Modified Files: src/sys/arch/hpcarm/dev: wzero3_reg.h wzero3_ssp.c wzero3_sspvar.h wzero3_tp.c Log Message: Added touchpad driver for WS011SH. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/hpcarm/dev/wzero3_reg.h \ src/sys/arch/hpcarm/dev/wzero3_tp.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/hpcarm/dev/wzero3_ssp.c \ src/sys/arch/hpcarm/dev/wzero3_sspvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hpcarm/dev/wzero3_reg.h diff -u src/sys/arch/hpcarm/dev/wzero3_reg.h:1.3 src/sys/arch/hpcarm/dev/wzero3_reg.h:1.4 --- src/sys/arch/hpcarm/dev/wzero3_reg.h:1.3 Thu May 13 21:01:59 2010 +++ src/sys/arch/hpcarm/dev/wzero3_reg.h Sat May 22 15:37:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: wzero3_reg.h,v 1.3 2010/05/13 21:01:59 nonaka Exp $ */ +/* $NetBSD: wzero3_reg.h,v 1.4 2010/05/22 15:37:58 nonaka Exp $ */ /* * Copyright (c) 2008, 2009, 2010 NONAKA Kimihiro <non...@netbsd.org> @@ -95,6 +95,7 @@ #define GPIO_WS011SH_POWER_BUTTON 9 /* In */ #define GPIO_WS011SH_TENKEY 14 /* In */ #define GPIO_WS011SH_TOUCH_PANEL 21 /* In */ +#define GPIO_WS011SH_AK4184_CS 33 /* Out */ #define GPIO_WS011SH_USB_HOST_POWER 37 /* Out */ #define GPIO_WS011SH_USB_HOST_DETECT 41 /* In */ #define GPIO_WS011SH_SD_DETECT 48 /* In */ Index: src/sys/arch/hpcarm/dev/wzero3_tp.c diff -u src/sys/arch/hpcarm/dev/wzero3_tp.c:1.3 src/sys/arch/hpcarm/dev/wzero3_tp.c:1.4 --- src/sys/arch/hpcarm/dev/wzero3_tp.c:1.3 Sat May 15 03:54:35 2010 +++ src/sys/arch/hpcarm/dev/wzero3_tp.c Sat May 22 15:37:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: wzero3_tp.c,v 1.3 2010/05/15 03:54:35 nonaka Exp $ */ +/* $NetBSD: wzero3_tp.c,v 1.4 2010/05/22 15:37:58 nonaka Exp $ */ /* * Copyright (c) 2010 NONAKA Kimihiro <non...@netbsd.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.3 2010/05/15 03:54:35 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.4 2010/05/22 15:37:58 nonaka Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -94,6 +94,18 @@ } }; +static const struct wsmouse_calibcoords ws011sh_default_calib = { + 0, 0, 479, 799, /* minx, miny, maxx, maxy */ + 5, /* samplelen */ + { + { 2126, 2048, 240, 400 }, /* rawx, rawy, x, y */ + { 527, 3464, 48, 80 }, + { 3628, 3376, 48, 720 }, + { 3351, 595, 432, 720 }, + { 554, 562, 432, 80 }, + } +}; + struct wzero3tp_pos { int x; int y; @@ -131,6 +143,11 @@ void ads7846_resume(void); extern void (*ads7846_wait_for_hsync)(void); +void ak4184_init(void); +int ak4184_readpos(struct wzero3tp_pos *); +void ak4184_suspend(void); +void ak4184_resume(void); + static int wzero3tp_match(device_t, cfdata_t, void *); static void wzero3tp_attach(device_t, device_t, void *); @@ -199,10 +216,10 @@ &platid_mask_MACH_SHARP_WZERO3_WS011SH, "WS011SH", GPIO_WS011SH_TOUCH_PANEL, + &ws011sh_default_calib, NULL, - NULL, - { nulldrv_init, nulldrv_readpos, - nulldrv_suspend, nulldrv_resume, }, + { ak4184_init, ak4184_readpos, + ak4184_suspend, ak4184_resume, }, }, #if 0 /* WS0020H */ @@ -622,7 +639,7 @@ DPRINTF(("%s: z2=%d\n", __func__, z2)); if (z1) { - rt = 400/*XXX*/; + rt = 400 /* XXX: X plate ohms */; rt *= pos->x; rt *= (z2 / z1) - 1; rt >>= 12; @@ -642,12 +659,12 @@ /*---------------------------------------------------------------------------- * ADS7846/TSC2046 touch screen controller for WS007SH */ -#define ADSCTRL_PD0_SH 0 /* PD0 bit */ -#define ADSCTRL_PD1_SH 1 /* PD1 bit */ -#define ADSCTRL_DFR_SH 2 /* SER/DFR bit */ -#define ADSCTRL_MOD_SH 3 /* Mode bit */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS_SH 7 /* Start bit */ +#define ADSCTRL_PD0_SH 0 /* PD0 bit */ +#define ADSCTRL_PD1_SH 1 /* PD1 bit */ +#define ADSCTRL_DFR_SH 2 /* SER/DFR bit */ +#define ADSCTRL_MOD_SH 3 /* Mode bit */ +#define ADSCTRL_ADR_SH 4 /* Address setting */ +#define ADSCTRL_STS_SH 7 /* Start bit */ static uint32_t ads7846_sync(int, int, uint32_t); @@ -763,3 +780,106 @@ return rv; } + +/*---------------------------------------------------------------------------- + * AK4184 touch screen controller for WS011SH + */ +#define AKMCTRL_PD_SH 12 /* Power down bit */ +#define AKMCTRL_ADR_SH 13 /* Address setting bits */ +#define AKMCTRL_STS_SH 15 /* Start bit */ + +static uint32_t ak4184_sync(int, int, uint32_t); + +void +ak4184_init(void) +{ + + /* Enable automatic low power mode. */ + (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184, + (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0); +} + +int +ak4184_readpos(struct wzero3tp_pos *pos) +{ + u_int rt; + int z1, z2; + + /* X (discard) */ + (void)ak4184_sync(0, 1, + (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + + /* X */ + (void)ak4184_sync(1, 1, + (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + + /* Y */ + pos->x = ak4184_sync(1, 1, + (1<<AKMCTRL_STS_SH) | (1<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + DPRINTF(("%s: x=%d\n", __func__, pos->x)); + pos->y = ak4184_sync(1, 1, + (1<<AKMCTRL_STS_SH) | (2<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + DPRINTF(("%s: y=%d\n", __func__, pos->y)); + z1 = ak4184_sync(1, 1, + (1<<AKMCTRL_STS_SH) | (3<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + DPRINTF(("%s: z1=%d\n", __func__, z1)); + z2 = ak4184_sync(1, 0, + (1<<AKMCTRL_STS_SH) | (3<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH)); + DPRINTF(("%s: z2=%d\n", __func__, z2)); + + if (z1 >= 10) { + rt = 400 /* XXX: X plate ohms */; + rt *= pos->x; + rt *= (z2 / z1) - 1; + rt >>= 12; + } else + rt = 0; + DPRINTF(("%s: rt=%d\n", __func__, rt)); + + /* check that pen is still down */ + if (z1 == 0 || rt == 0) + pos->z = 0; + else + pos->z = 1; + + /* Enable automatic low power mode. */ + (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184, + (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0); + + return pos->z; +} + +void +ak4184_suspend(void) +{ + + /* Nothing to do */ +} + +void +ak4184_resume(void) +{ + + /* Enable automatic low power mode. */ + (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184, + (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0); +} + +static uint32_t +ak4184_sync(int dorecv, int dosend, uint32_t cmd) +{ + uint32_t rv = 0; + + if (dorecv) + rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_AK4184); + + if (dosend) { + /* send dummy command; discard SSDR */ + (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184, cmd, 0); + + /* send the actual command; keep AK4184 enabled */ + wzero3ssp_ic_start(WZERO3_SSP_IC_AK4184, cmd); + } + + return rv; +} Index: src/sys/arch/hpcarm/dev/wzero3_ssp.c diff -u src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.2 src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.3 --- src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.2 Thu May 13 21:01:59 2010 +++ src/sys/arch/hpcarm/dev/wzero3_ssp.c Sat May 22 15:37:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: wzero3_ssp.c,v 1.2 2010/05/13 21:01:59 nonaka Exp $ */ +/* $NetBSD: wzero3_ssp.c,v 1.3 2010/05/22 15:37:58 nonaka Exp $ */ /* * Copyright (c) 2010 NONAKA Kimihiro <non...@netbsd.org> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.2 2010/05/13 21:01:59 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.3 2010/05/22 15:37:58 nonaka Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -49,8 +49,8 @@ #define WS003SH_SSCR0_MAX1233 0x0000048f /* 16bit/SPI/div by 5 */ #define WS007SH_SSCR0_ADS7846 0x000006ab /* 12bit/Microwire/div by 7 */ -#define WS011SH_SSCR0_TP 0x0010068f /* 32bit/SPI/div by 7 */ -#define WS011SH_SSCR0_TENKEY 0x0000068f /* 16bit/SPI/div by 7 */ +#define WS011SH_SSCR0_AK4184_TP 0x0010068f /* 32bit/SPI/div by 7 */ +#define WS011SH_SSCR0_AK4184_TENKEY 0x0000068f /* 16bit/SPI/div by 7 */ struct wzero3ssp_model; struct wzero3ssp_softc { @@ -72,6 +72,7 @@ static uint32_t wzero3ssp_read_ads7846(struct wzero3ssp_softc *, uint32_t); static uint32_t wzero3ssp_read_max1233(struct wzero3ssp_softc *, uint32_t, uint32_t); +static uint32_t wzero3ssp_read_ak4184(struct wzero3ssp_softc *, uint32_t); static struct wzero3ssp_softc *wzero3ssp_sc; @@ -198,6 +199,10 @@ pxa2x0_gpio_set_function(GPIO_WS007SH_ADS7846_CS, GPIO_OUT|GPIO_SET); } + if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) { + pxa2x0_gpio_set_function(GPIO_WS011SH_AK4184_CS, + GPIO_OUT|GPIO_SET); + } } static bool @@ -229,8 +234,14 @@ /* disable other ICs */ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0); - if (ic != WZERO3_SSP_IC_ADS7846) - pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS); + if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS007SH)) { + if (ic != WZERO3_SSP_IC_ADS7846) + pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS); + } + if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) { + if (ic != WZERO3_SSP_IC_AK4184) + pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS); + } /* activate the chosen one */ switch (ic) { @@ -244,6 +255,20 @@ & SSSR_TNF) != SSSR_TNF) continue; /* poll */ break; + case WZERO3_SSP_IC_AK4184: + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, + WS011SH_SSCR0_AK4184_TP); + pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS); + (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); + while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_TNF)) + continue; /* poll */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd << 16); + while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_BUSY) + continue; /* poll */ + break; case WZERO3_SSP_IC_MAX1233: case WZERO3_SSP_IC_NUM: default: @@ -272,6 +297,14 @@ rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS); break; + case WZERO3_SSP_IC_AK4184: + /* read result of last command */ + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_RNE) != SSSR_RNE) + continue; /* poll */ + rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); + pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS); + break; case WZERO3_SSP_IC_MAX1233: case WZERO3_SSP_IC_NUM: default: @@ -304,6 +337,8 @@ return wzero3ssp_read_ads7846(sc, data); case WZERO3_SSP_IC_MAX1233: return wzero3ssp_read_max1233(sc, data, data2); + case WZERO3_SSP_IC_AK4184: + return wzero3ssp_read_ak4184(sc, data); case WZERO3_SSP_IC_NUM: default: aprint_error("%s: invalid IC %d\n", __func__, ic); @@ -381,3 +416,36 @@ return rv; } + +static uint32_t +wzero3ssp_read_ak4184(struct wzero3ssp_softc *sc, uint32_t cmd) +{ + uint32_t rv; + + mutex_enter(&sc->sc_mtx); + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, + WS011SH_SSCR0_AK4184_TP); + + pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS); + + (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); + + /* send cmd */ + while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF)) + continue; /* poll */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd << 16); + while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY) + continue; /* poll */ + + while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE)) + continue; /* poll */ + rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); + + pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS); + + mutex_exit(&sc->sc_mtx); + + return rv; +} Index: src/sys/arch/hpcarm/dev/wzero3_sspvar.h diff -u src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.2 src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.3 --- src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.2 Thu May 13 21:01:59 2010 +++ src/sys/arch/hpcarm/dev/wzero3_sspvar.h Sat May 22 15:37:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: wzero3_sspvar.h,v 1.2 2010/05/13 21:01:59 nonaka Exp $ */ +/* $NetBSD: wzero3_sspvar.h,v 1.3 2010/05/22 15:37:58 nonaka Exp $ */ /* * Copyright (c) 2010 NONAKA Kimihiro <non...@netbsd.org> @@ -32,6 +32,7 @@ enum { WZERO3_SSP_IC_ADS7846, /* touch screen controller */ WZERO3_SSP_IC_MAX1233, /* touch screen controller */ + WZERO3_SSP_IC_AK4184, /* touch screen controller */ WZERO3_SSP_IC_NUM };