LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Dmitry Torokhov <dtor@mail.ru>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
Mark Brown <broonie@opensource.wolfsonmicro.com>,
Liam Girdwood <liam.girdwood@wolfsonmicro.com>,
Graeme Gregory <gg@opensource.wolfsonmicro.com>,
Mike Arthur <mike.arthur@wolfsonmicro.com>,
Dmitry Baryshkov <dbaryshkov@gmail.com>,
Stanley Cai <stanley.cai@intel.com>,
Rodolfo Giometti <giometti@enneenne.com>,
Russell King <rmk@arm.linux.org.uk>,
Marc Kleine-Budde <mkl@pengutronix.de>,
Pete MacKay <linux01@architechnical.net>,
Ian Molton <spyro@f2s.com>, Vince Sanders <vince@kyllikki.org>,
Andrew Zabolotny <zap@homelink.ru>
Subject: [PATCH 2/6] Add chip driver for WM9705 touchscreen
Date: Fri, 29 Feb 2008 16:52:22 +0000 [thread overview]
Message-ID: <1204303946-17798-2-git-send-email-broonie@opensource.wolfsonmicro.com> (raw)
In-Reply-To: <1204303946-17798-1-git-send-email-broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
Signed-off-by: Graeme Gregory <gg@opensource.wolfsonmicro.com>
Signed-off-by: Mike Arthur <mike.arthur@wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
Cc: Stanley Cai <stanley.cai@intel.com>
Cc: Rodolfo Giometti <giometti@enneenne.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Pete MacKay <linux01@architechnical.net>
Cc: Ian Molton <spyro@f2s.com>
Cc: Vince Sanders <vince@kyllikki.org>
Cc: Andrew Zabolotny <zap@homelink.ru>
---
drivers/input/touchscreen/wm9705.c | 352 ++++++++++++++++++++++++++++++++++++
1 files changed, 352 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/wm9705.c
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
new file mode 100644
index 0000000..73440f6
--- /dev/null
+++ b/drivers/input/touchscreen/wm9705.c
@@ -0,0 +1,352 @@
+/*
+ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
+ *
+ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ * Andrew Zabolotny <zap@homelink.ru>
+ * Russell King <rmk@arm.linux.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME "wm97xx"
+#define WM9705_VERSION "0.62"
+#define DEFAULT_PRESSURE 0xb0c0
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ * pil = 1 to use 200uA and
+ * pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 4;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Pen detect comparator threshold.
+ *
+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
+ * i.e. 1 = Vmid/15 threshold
+ * 15 = Vmid/1 threshold
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down events.
+ */
+static int pdd = 8;
+module_param(pdd, int, 0);
+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+ 21, /* 1 AC97 Link frames */
+ 42, /* 2 */
+ 84, /* 4 */
+ 167, /* 8 */
+ 333, /* 16 */
+ 667, /* 32 */
+ 1000, /* 48 */
+ 1333, /* 64 */
+ 2000, /* 96 */
+ 2667, /* 128 */
+ 3333, /* 160 */
+ 4000, /* 192 */
+ 4667, /* 224 */
+ 5333, /* 256 */
+ 6000, /* 288 */
+ 0 /* No delay, switch matrix always on */
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
+}
+
+/*
+ * set up the physical settings of the WM9705
+ */
+static void wm9705_phy_init(struct wm97xx *wm)
+{
+ u16 dig1 = 0, dig2 = WM97XX_RPR;
+
+ /*
+ * mute VIDEO and AUX as they share X and Y touchscreen
+ * inputs on the WM9705
+ */
+ wm97xx_reg_write(wm, AC97_AUX, 0x8000);
+ wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
+
+ /* touchpanel pressure current*/
+ if (pil == 2) {
+ dig2 |= WM9705_PIL;
+ dev_dbg(wm->dev,
+ "setting pressure measurement current to 400uA.");
+ } else if (pil)
+ dev_dbg(wm->dev,
+ "setting pressure measurement current to 200uA.");
+ if (!pil)
+ pressure = 0;
+
+ /* polling mode sample settling delay */
+ if (delay != 4) {
+ if (delay < 0 || delay > 15) {
+ dev_dbg(wm->dev, "supplied delay out of range.");
+ delay = 4;
+ }
+ }
+ dig1 &= 0xff0f;
+ dig1 |= WM97XX_DELAY(delay);
+ dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
+ delay_table[delay]);
+
+ /* WM9705 pdd */
+ dig2 |= (pdd & 0x000f);
+ dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
+
+ /* mask */
+ dig2 |= ((mask & 0x3) << 4);
+
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+}
+
+static void wm9705_dig_enable(struct wm97xx *wm, int enable)
+{
+ if (enable) {
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+ wm->dig[2] | WM97XX_PRP_DET_DIG);
+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+ } else
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
+ wm->dig[2] & ~WM97XX_PRP_DET_DIG);
+}
+
+static void wm9705_aux_prepare(struct wm97xx *wm)
+{
+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
+}
+
+static void wm9705_dig_restore(struct wm97xx *wm)
+{
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
+}
+
+static inline int is_pden(struct wm97xx *wm)
+{
+ return wm->dig[2] & WM9705_PDEN;
+}
+
+/*
+ * Read a sample from the WM9705 adc in polling mode.
+ */
+static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
+{
+ int timeout = 5 * delay;
+
+ if (!wm->pen_probably_down) {
+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+ if (!(data & WM97XX_PEN_DOWN))
+ return RC_PENUP;
+ wm->pen_probably_down = 1;
+ }
+
+ /* set up digitiser */
+ if (adcsel & 0x8000)
+ adcsel = ((adcsel & 0x7fff) + 3) << 12;
+
+ if (wm->mach_ops && wm->mach_ops->pre_sample)
+ wm->mach_ops->pre_sample(adcsel);
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
+ adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+
+ /* wait 3 AC97 time slots + delay for conversion */
+ poll_delay(delay);
+
+ /* wait for POLL to go low */
+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
+ && timeout) {
+ udelay(AC97_LINK_FRAME);
+ timeout--;
+ }
+
+ if (timeout == 0) {
+ /* If PDEN is set, we can get a timeout when pen goes up */
+ if (is_pden(wm))
+ wm->pen_probably_down = 0;
+ else
+ dev_dbg(wm->dev, "adc sample timeout");
+ return RC_PENUP;
+ }
+
+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+ if (wm->mach_ops && wm->mach_ops->post_sample)
+ wm->mach_ops->post_sample(adcsel);
+
+ /* check we have correct sample */
+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
+ *sample & WM97XX_ADCSEL_MASK);
+ return RC_PENUP;
+ }
+
+ if (!(*sample & WM97XX_PEN_DOWN)) {
+ wm->pen_probably_down = 0;
+ return RC_PENUP;
+ }
+
+ return RC_VALID;
+}
+
+/*
+ * Sample the WM9705 touchscreen in polling mode
+ */
+static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
+{
+ int rc;
+
+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+ if (rc != RC_VALID)
+ return rc;
+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+ if (rc != RC_VALID)
+ return rc;
+ if (pil) {
+ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
+ if (rc != RC_VALID)
+ return rc;
+ } else
+ data->p = DEFAULT_PRESSURE;
+
+ return RC_VALID;
+}
+
+/*
+ * Enable WM9705 continuous mode, i.e. touch data is streamed across
+ * an AC97 slot
+ */
+static int wm9705_acc_enable(struct wm97xx *wm, int enable)
+{
+ u16 dig1, dig2;
+ int ret = 0;
+
+ dig1 = wm->dig[1];
+ dig2 = wm->dig[2];
+
+ if (enable) {
+ /* continous mode */
+ if (wm->mach_ops->acc_startup &&
+ (ret = wm->mach_ops->acc_startup(wm)) < 0)
+ return ret;
+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
+ WM97XX_DELAY(delay) |
+ WM97XX_SLT(wm->acc_slot) |
+ WM97XX_RATE(wm->acc_rate);
+ if (pil)
+ dig1 |= WM97XX_ADCSEL_PRES;
+ dig2 |= WM9705_PDEN;
+ } else {
+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
+ dig2 &= ~WM9705_PDEN;
+ if (wm->mach_ops->acc_shutdown)
+ wm->mach_ops->acc_shutdown(wm);
+ }
+
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+ return ret;
+}
+
+struct wm97xx_codec_drv wm9705_codec = {
+ .id = WM9705_ID2,
+ .name = "wm9705",
+ .poll_sample = wm9705_poll_sample,
+ .poll_touch = wm9705_poll_touch,
+ .acc_enable = wm9705_acc_enable,
+ .phy_init = wm9705_phy_init,
+ .dig_enable = wm9705_dig_enable,
+ .dig_restore = wm9705_dig_restore,
+ .aux_prepare = wm9705_aux_prepare,
+};
+EXPORT_SYMBOL_GPL(wm9705_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
+MODULE_LICENSE("GPL");
--
1.5.4.3
next prev parent reply other threads:[~2008-02-29 16:52 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-29 16:50 WM97xx touchscreen drivers Mark Brown
2008-02-29 16:52 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-02-29 16:52 ` Mark Brown [this message]
2008-02-29 16:52 ` [PATCH 3/6] Add chip driver for WM9712 touchscreen Mark Brown
2008-02-29 16:52 ` [PATCH 4/6] Add chip driver for WM9713 touchscreen Mark Brown
2008-02-29 16:52 ` [PATCH 5/6] Driver for WM97xx touchscreens in streaming mode on Mainstone Mark Brown
2008-02-29 16:52 ` [PATCH 6/6] Build system and MAINTAINERS entry for WM97xx touchscreen drivers Mark Brown
2008-03-04 14:02 ` Mark Brown
2008-03-04 14:04 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-03-04 14:04 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-03-04 14:04 ` [PATCH 3/6] Add chip driver for WM9712 touchscreen Mark Brown
2008-03-04 14:04 ` [PATCH 4/6] Add chip driver for WM9713 touchscreen Mark Brown
2008-03-04 14:04 ` [PATCH 5/6] Driver for WM97xx touchscreens in streaming mode on Mainstone Mark Brown
2008-03-04 14:04 ` [PATCH 6/6] Build system and MAINTAINERS entry for WM97xx touchscreen drivers Mark Brown
2008-03-04 15:27 ` Dmitry
2008-03-04 15:41 ` Mark Brown
-- strict thread matches above, loose matches on Subject: below --
2008-04-01 10:28 Mark Brown
2008-04-01 10:36 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-04-01 10:36 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-03-20 9:39 WM97xx touchscreen drivers Mark Brown
2008-03-20 9:42 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-03-20 9:42 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
[not found] <12040332183316-git-send-email-broonie@opensource.wolfsonmicro.com>
2008-02-26 13:40 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
[not found] ` <12040332181161-git-send-email-broonie@opensource.wolfsonmicro.com>
2008-02-26 13:40 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-02-28 7:09 ` Andrew Morton
2008-02-28 11:46 ` Mark Brown
2008-02-13 14:06 [UPDATED v7] WM97xx touchscreen drivers Mark Brown
2008-02-13 14:13 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-02-13 14:13 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-02-12 10:17 [UPDATED v6] WM97xx touchscreen drivers Mark Brown
2008-02-12 10:21 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-02-12 10:21 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-01-26 15:18 [UPDATED v4] WM97xx touchscreen drivers Mark Brown
2008-01-26 17:28 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-01-26 17:28 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-01-21 15:24 [UPDATED v3] WM97xx touchscreen drivers Mark Brown
2008-01-21 15:24 ` [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-01-21 15:24 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
2008-01-10 11:51 [PATCH 1/6] Core driver for WM97xx touchscreens Mark Brown
2008-01-10 11:51 ` [PATCH 2/6] Add chip driver for WM9705 touchscreen Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1204303946-17798-2-git-send-email-broonie@opensource.wolfsonmicro.com \
--to=broonie@opensource.wolfsonmicro.com \
--cc=akpm@linux-foundation.org \
--cc=dbaryshkov@gmail.com \
--cc=dtor@mail.ru \
--cc=gg@opensource.wolfsonmicro.com \
--cc=giometti@enneenne.com \
--cc=liam.girdwood@wolfsonmicro.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux01@architechnical.net \
--cc=mike.arthur@wolfsonmicro.com \
--cc=mkl@pengutronix.de \
--cc=rmk@arm.linux.org.uk \
--cc=spyro@f2s.com \
--cc=stanley.cai@intel.com \
--cc=vince@kyllikki.org \
--cc=zap@homelink.ru \
--subject='Re: [PATCH 2/6] Add chip driver for WM9705 touchscreen' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).