* mc13892 touchscreen support
@ 2012-01-29 22:51 Marc Reilly
2012-01-29 22:51 ` [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts Marc Reilly
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Marc Reilly @ 2012-01-29 22:51 UTC (permalink / raw)
To: linux-input; +Cc: s.hauer, linux-arm-kernel, u.kleine-koenig
Hi,
This patch series adds touchscreen support for the mc13892 to the
mc13873 driver. The driver is renamed to mc13xxx_ts to reflect this.
The first 3 patches apply cleanly to v3.2.
The fourth patch allows setting the ATO and ATOX registers with each
conversion. It requires another series I just posted [1].
Cheers,
Marc
[1] http://lists.arm.linux.org.uk/lurker/message/20120129.223322.722b7424.en.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts
2012-01-29 22:51 mc13892 touchscreen support Marc Reilly
@ 2012-01-29 22:51 ` Marc Reilly
2012-01-30 2:52 ` Fabio Estevam
2012-01-29 22:51 ` [PATCH 2/4] input: mc13xxx_ts: add support for mc13892 Marc Reilly
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Marc Reilly @ 2012-01-29 22:51 UTC (permalink / raw)
To: linux-input; +Cc: s.hauer, linux-arm-kernel, u.kleine-koenig, Marc Reilly
Start moving this driver towards support for both mc13892 and mc13783.
This patch simply renames mc13783 specific identifiers to the generic
mc13xxx. A platform_device_id table is also added so that the driver
is still created correctly for the mc13783 only.
Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
---
drivers/input/touchscreen/Kconfig | 8 +-
drivers/input/touchscreen/Makefile | 2 +-
drivers/input/touchscreen/mc13783_ts.c | 259 -------------------------------
drivers/input/touchscreen/mc13xxx_ts.c | 267 ++++++++++++++++++++++++++++++++
4 files changed, 272 insertions(+), 264 deletions(-)
delete mode 100644 drivers/input/touchscreen/mc13783_ts.c
create mode 100644 drivers/input/touchscreen/mc13xxx_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3488ffe..79831d9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -548,9 +548,9 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
-config TOUCHSCREEN_MC13783
- tristate "Freescale MC13783 touchscreen input driver"
- depends on MFD_MC13783
+config TOUCHSCREEN_MC13XXX
+ tristate "Freescale MC13xxx touchscreen input driver"
+ depends on MFD_MC13XXX
help
Say Y here if you have an Freescale MC13783 PMIC on your
board and want to use its touchscreen
@@ -558,7 +558,7 @@ config TOUCHSCREEN_MC13783
If unsure, say N.
To compile this driver as a module, choose M here: the
- module will be called mc13783_ts.
+ module will be called mc13xxx_ts.
config TOUCHSCREEN_USB_EGALAX
default y
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f957676..919c254 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MC13XXX) += mc13xxx_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
deleted file mode 100644
index ede0274..0000000
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Driver for the Freescale Semiconductor MC13783 touchscreen.
- *
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009 Sascha Hauer, Pengutronix
- *
- * Initial development of this code was funded by
- * Phytec Messtechnik GmbH, http://www.phytec.de/
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-#include <linux/platform_device.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define MC13783_TS_NAME "mc13783-ts"
-
-#define DEFAULT_SAMPLE_TOLERANCE 300
-
-static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
-module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(sample_tolerance,
- "If the minimal and maximal value read out for one axis (out "
- "of three) differ by this value (default: "
- __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
- "is supposed to be wrong and is discarded. Set to 0 to "
- "disable this check.");
-
-struct mc13783_ts_priv {
- struct input_dev *idev;
- struct mc13xxx *mc13xxx;
- struct delayed_work work;
- struct workqueue_struct *workq;
- unsigned int sample[4];
-};
-
-static irqreturn_t mc13783_ts_handler(int irq, void *data)
-{
- struct mc13783_ts_priv *priv = data;
-
- mc13xxx_irq_ack(priv->mc13xxx, irq);
-
- /*
- * Kick off reading coordinates. Note that if work happens already
- * be queued for future execution (it rearms itself) it will not
- * be rescheduled for immediate execution here. However the rearm
- * delay is HZ / 50 which is acceptable.
- */
- queue_delayed_work(priv->workq, &priv->work, 0);
-
- return IRQ_HANDLED;
-}
-
-#define sort3(a0, a1, a2) ({ \
- if (a0 > a1) \
- swap(a0, a1); \
- if (a1 > a2) \
- swap(a1, a2); \
- if (a0 > a1) \
- swap(a0, a1); \
- })
-
-static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
-{
- struct input_dev *idev = priv->idev;
- int x0, x1, x2, y0, y1, y2;
- int cr0, cr1;
-
- /*
- * the values are 10-bit wide only, but the two least significant
- * bits are for future 12 bit use and reading yields 0
- */
- x0 = priv->sample[0] & 0xfff;
- x1 = priv->sample[1] & 0xfff;
- x2 = priv->sample[2] & 0xfff;
- y0 = priv->sample[3] & 0xfff;
- y1 = (priv->sample[0] >> 12) & 0xfff;
- y2 = (priv->sample[1] >> 12) & 0xfff;
- cr0 = (priv->sample[2] >> 12) & 0xfff;
- cr1 = (priv->sample[3] >> 12) & 0xfff;
-
- dev_dbg(&idev->dev,
- "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
- x0, x1, x2, y0, y1, y2, cr0, cr1);
-
- sort3(x0, x1, x2);
- sort3(y0, y1, y2);
-
- cr0 = (cr0 + cr1) / 2;
-
- if (!cr0 || !sample_tolerance ||
- (x2 - x0 < sample_tolerance &&
- y2 - y0 < sample_tolerance)) {
- /* report the median coordinate and average pressure */
- if (cr0) {
- input_report_abs(idev, ABS_X, x1);
- input_report_abs(idev, ABS_Y, y1);
-
- dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
- x1, y1, 0x1000 - cr0);
- queue_delayed_work(priv->workq, &priv->work, HZ / 50);
- } else
- dev_dbg(&idev->dev, "report release\n");
-
- input_report_abs(idev, ABS_PRESSURE,
- cr0 ? 0x1000 - cr0 : cr0);
- input_report_key(idev, BTN_TOUCH, cr0);
- input_sync(idev);
- } else
- dev_dbg(&idev->dev, "discard event\n");
-}
-
-static void mc13783_ts_work(struct work_struct *work)
-{
- struct mc13783_ts_priv *priv =
- container_of(work, struct mc13783_ts_priv, work.work);
- unsigned int mode = MC13XXX_ADC_MODE_TS;
- unsigned int channel = 12;
-
- if (mc13xxx_adc_do_conversion(priv->mc13xxx,
- mode, channel, priv->sample) == 0)
- mc13783_ts_report_sample(priv);
-}
-
-static int mc13783_ts_open(struct input_dev *dev)
-{
- struct mc13783_ts_priv *priv = input_get_drvdata(dev);
- int ret;
-
- mc13xxx_lock(priv->mc13xxx);
-
- mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
-
- ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
- mc13783_ts_handler, MC13783_TS_NAME, priv);
- if (ret)
- goto out;
-
- ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
- MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0);
- if (ret)
- mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
-out:
- mc13xxx_unlock(priv->mc13xxx);
- return ret;
-}
-
-static void mc13783_ts_close(struct input_dev *dev)
-{
- struct mc13783_ts_priv *priv = input_get_drvdata(dev);
-
- mc13xxx_lock(priv->mc13xxx);
- mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
- MC13XXX_ADC0_TSMOD_MASK, 0);
- mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
- mc13xxx_unlock(priv->mc13xxx);
-
- cancel_delayed_work_sync(&priv->work);
-}
-
-static int __init mc13783_ts_probe(struct platform_device *pdev)
-{
- struct mc13783_ts_priv *priv;
- struct input_dev *idev;
- int ret = -ENOMEM;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- idev = input_allocate_device();
- if (!priv || !idev)
- goto err_free_mem;
-
- INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
- priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
- priv->idev = idev;
-
- /*
- * We need separate workqueue because mc13783_adc_do_conversion
- * uses keventd and thus would deadlock.
- */
- priv->workq = create_singlethread_workqueue("mc13783_ts");
- if (!priv->workq)
- goto err_free_mem;
-
- idev->name = MC13783_TS_NAME;
- idev->dev.parent = &pdev->dev;
-
- idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
- input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
- input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
-
- idev->open = mc13783_ts_open;
- idev->close = mc13783_ts_close;
-
- input_set_drvdata(idev, priv);
-
- ret = input_register_device(priv->idev);
- if (ret) {
- dev_err(&pdev->dev,
- "register input device failed with %d\n", ret);
- goto err_destroy_wq;
- }
-
- platform_set_drvdata(pdev, priv);
- return 0;
-
-err_destroy_wq:
- destroy_workqueue(priv->workq);
-err_free_mem:
- input_free_device(idev);
- kfree(priv);
- return ret;
-}
-
-static int __devexit mc13783_ts_remove(struct platform_device *pdev)
-{
- struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- destroy_workqueue(priv->workq);
- input_unregister_device(priv->idev);
- kfree(priv);
-
- return 0;
-}
-
-static struct platform_driver mc13783_ts_driver = {
- .remove = __devexit_p(mc13783_ts_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = MC13783_TS_NAME,
- },
-};
-
-static int __init mc13783_ts_init(void)
-{
- return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
-}
-module_init(mc13783_ts_init);
-
-static void __exit mc13783_ts_exit(void)
-{
- platform_driver_unregister(&mc13783_ts_driver);
-}
-module_exit(mc13783_ts_exit);
-
-MODULE_DESCRIPTION("MC13783 input touchscreen driver");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" MC13783_TS_NAME);
diff --git a/drivers/input/touchscreen/mc13xxx_ts.c b/drivers/input/touchscreen/mc13xxx_ts.c
new file mode 100644
index 0000000..2c000a9
--- /dev/null
+++ b/drivers/input/touchscreen/mc13xxx_ts.c
@@ -0,0 +1,267 @@
+/*
+ * Driver for the Freescale Semiconductor MC13XXX touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13xxx.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#define MC13XXX_TS_NAME "mc13xxx-ts"
+
+#define DEFAULT_SAMPLE_TOLERANCE 300
+
+static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
+module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_tolerance,
+ "If the minimal and maximal value read out for one axis (out "
+ "of three) differ by this value (default: "
+ __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
+ "is supposed to be wrong and is discarded. Set to 0 to "
+ "disable this check.");
+
+struct mc13xxx_ts_priv {
+ struct input_dev *idev;
+ struct mc13xxx *mc13xxx;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+static irqreturn_t mc13xxx_ts_handler(int irq, void *data)
+{
+ struct mc13xxx_ts_priv *priv = data;
+
+ mc13xxx_irq_ack(priv->mc13xxx, irq);
+
+ /*
+ * Kick off reading coordinates. Note that if work happens already
+ * be queued for future execution (it rearms itself) it will not
+ * be rescheduled for immediate execution here. However the rearm
+ * delay is HZ / 50 which is acceptable.
+ */
+ queue_delayed_work(priv->workq, &priv->work, 0);
+
+ return IRQ_HANDLED;
+}
+
+#define sort3(a0, a1, a2) ({ \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ if (a1 > a2) \
+ swap(a1, a2); \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ })
+
+static void mc13xxx_ts_report_sample(struct mc13xxx_ts_priv *priv)
+{
+ struct input_dev *idev = priv->idev;
+ int x0, x1, x2, y0, y1, y2;
+ int cr0, cr1;
+
+ /*
+ * the values are 10-bit wide only, but the two least significant
+ * bits are for future 12 bit use and reading yields 0
+ */
+ x0 = priv->sample[0] & 0xfff;
+ x1 = priv->sample[1] & 0xfff;
+ x2 = priv->sample[2] & 0xfff;
+ y0 = priv->sample[3] & 0xfff;
+ y1 = (priv->sample[0] >> 12) & 0xfff;
+ y2 = (priv->sample[1] >> 12) & 0xfff;
+ cr0 = (priv->sample[2] >> 12) & 0xfff;
+ cr1 = (priv->sample[3] >> 12) & 0xfff;
+
+ dev_dbg(&idev->dev,
+ "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
+ x0, x1, x2, y0, y1, y2, cr0, cr1);
+
+ sort3(x0, x1, x2);
+ sort3(y0, y1, y2);
+
+ cr0 = (cr0 + cr1) / 2;
+
+ if (!cr0 || !sample_tolerance ||
+ (x2 - x0 < sample_tolerance &&
+ y2 - y0 < sample_tolerance)) {
+ /* report the median coordinate and average pressure */
+ if (cr0) {
+ input_report_abs(idev, ABS_X, x1);
+ input_report_abs(idev, ABS_Y, y1);
+
+ dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
+ x1, y1, 0x1000 - cr0);
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ } else
+ dev_dbg(&idev->dev, "report release\n");
+
+ input_report_abs(idev, ABS_PRESSURE,
+ cr0 ? 0x1000 - cr0 : cr0);
+ input_report_key(idev, BTN_TOUCH, cr0);
+ input_sync(idev);
+ } else
+ dev_dbg(&idev->dev, "discard event\n");
+}
+
+static void mc13xxx_ts_work(struct work_struct *work)
+{
+ struct mc13xxx_ts_priv *priv =
+ container_of(work, struct mc13xxx_ts_priv, work.work);
+ unsigned int mode = MC13XXX_ADC_MODE_TS;
+ unsigned int channel = 12;
+
+ if (mc13xxx_adc_do_conversion(priv->mc13xxx,
+ mode, channel, priv->sample) == 0)
+ mc13xxx_ts_report_sample(priv);
+}
+
+static int mc13xxx_ts_open(struct input_dev *dev)
+{
+ struct mc13xxx_ts_priv *priv = input_get_drvdata(dev);
+ int ret;
+
+ mc13xxx_lock(priv->mc13xxx);
+
+ mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
+
+ ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
+ mc13xxx_ts_handler, MC13XXX_TS_NAME, priv);
+ if (ret)
+ goto out;
+
+ ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+ MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0);
+ if (ret)
+ mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
+out:
+ mc13xxx_unlock(priv->mc13xxx);
+ return ret;
+}
+
+static void mc13xxx_ts_close(struct input_dev *dev)
+{
+ struct mc13xxx_ts_priv *priv = input_get_drvdata(dev);
+
+ mc13xxx_lock(priv->mc13xxx);
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+ MC13XXX_ADC0_TSMOD_MASK, 0);
+ mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
+ mc13xxx_unlock(priv->mc13xxx);
+
+ cancel_delayed_work_sync(&priv->work);
+}
+
+static int __init mc13xxx_ts_probe(struct platform_device *pdev)
+{
+ struct mc13xxx_ts_priv *priv;
+ struct input_dev *idev;
+ int ret = -ENOMEM;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ idev = input_allocate_device();
+ if (!priv || !idev)
+ goto err_free_mem;
+
+ INIT_DELAYED_WORK(&priv->work, mc13xxx_ts_work);
+ priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
+ priv->idev = idev;
+
+ /*
+ * We need separate workqueue because mc13xxx_adc_do_conversion
+ * uses keventd and thus would deadlock.
+ */
+ priv->workq = create_singlethread_workqueue("mc13xxx_ts");
+ if (!priv->workq)
+ goto err_free_mem;
+
+ idev->name = MC13XXX_TS_NAME;
+ idev->dev.parent = &pdev->dev;
+
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
+
+ idev->open = mc13xxx_ts_open;
+ idev->close = mc13xxx_ts_close;
+
+ input_set_drvdata(idev, priv);
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_destroy_wq;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+err_destroy_wq:
+ destroy_workqueue(priv->workq);
+err_free_mem:
+ input_free_device(idev);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit mc13xxx_ts_remove(struct platform_device *pdev)
+{
+ struct mc13xxx_ts_priv *priv = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ destroy_workqueue(priv->workq);
+ input_unregister_device(priv->idev);
+ kfree(priv);
+
+ return 0;
+}
+
+const struct platform_device_id mc13xxx_ts_idtable[] = {
+ {
+ .name = "mc13783-ts",
+ },
+ { }
+};
+
+static struct platform_driver mc13xxx_ts_driver = {
+ .id_table = mc13xxx_ts_idtable,
+ .remove = __devexit_p(mc13xxx_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13XXX_TS_NAME,
+ },
+};
+
+static int __init mc13xxx_ts_init(void)
+{
+ return platform_driver_probe(&mc13xxx_ts_driver, &mc13xxx_ts_probe);
+}
+module_init(mc13xxx_ts_init);
+
+static void __exit mc13xxx_ts_exit(void)
+{
+ platform_driver_unregister(&mc13xxx_ts_driver);
+}
+module_exit(mc13xxx_ts_exit);
+
+MODULE_DESCRIPTION("MC13xxx input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MC13XXX_TS_NAME);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] input: mc13xxx_ts: add support for mc13892
2012-01-29 22:51 mc13892 touchscreen support Marc Reilly
2012-01-29 22:51 ` [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts Marc Reilly
@ 2012-01-29 22:51 ` Marc Reilly
2012-01-29 22:51 ` [PATCH 3/4] input: mc13xxx_ts: handle bad adc conversions Marc Reilly
2012-01-29 22:51 ` [PATCH 4/4] input: mc13xxx_ts: intersperse delays between ts samples Marc Reilly
3 siblings, 0 replies; 7+ messages in thread
From: Marc Reilly @ 2012-01-29 22:51 UTC (permalink / raw)
To: linux-input; +Cc: s.hauer, linux-arm-kernel, u.kleine-koenig, Marc Reilly
The way the raw touchscreen co-ordinates are sampled have some minor
differences for the mc13892 and mc13873. This patch introduces an IC
specific handler to convert the raw samples into x, y, pressure readings
for the input sub-system.
The mc13892 ignores samples that have too high a contact resistance.
Behaviour for the mc13873 is (intended to be) preserved.
Help text for the config item changes to reflect support for both IC
types
Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
---
drivers/input/touchscreen/Kconfig | 2 +-
drivers/input/touchscreen/mc13xxx_ts.c | 132 +++++++++++++++++++++++++++-----
2 files changed, 115 insertions(+), 19 deletions(-)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 79831d9..0c44b37 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -552,7 +552,7 @@ config TOUCHSCREEN_MC13XXX
tristate "Freescale MC13xxx touchscreen input driver"
depends on MFD_MC13XXX
help
- Say Y here if you have an Freescale MC13783 PMIC on your
+ Say Y here if you have an Freescale MC13xxx PMIC on your
board and want to use its touchscreen
If unsure, say N.
diff --git a/drivers/input/touchscreen/mc13xxx_ts.c b/drivers/input/touchscreen/mc13xxx_ts.c
index 2c000a9..264b977 100644
--- a/drivers/input/touchscreen/mc13xxx_ts.c
+++ b/drivers/input/touchscreen/mc13xxx_ts.c
@@ -3,6 +3,7 @@
*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2009 Sascha Hauer, Pengutronix
+ * Copyright 2011 Marc Reilly, Creative Product Design
*
* Initial development of this code was funded by
* Phytec Messtechnik GmbH, http://www.phytec.de/
@@ -27,8 +28,8 @@
static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(sample_tolerance,
- "If the minimal and maximal value read out for one axis (out "
- "of three) differ by this value (default: "
+ "If the minimal and maximal value read out for one axis "
+ "differ by this value (default: "
__stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
"is supposed to be wrong and is discarded. Set to 0 to "
"disable this check.");
@@ -36,9 +37,14 @@ MODULE_PARM_DESC(sample_tolerance,
struct mc13xxx_ts_priv {
struct input_dev *idev;
struct mc13xxx *mc13xxx;
+
struct delayed_work work;
struct workqueue_struct *workq;
+
unsigned int sample[4];
+
+ bool (*convert_and_check_samples)(struct mc13xxx_ts_priv *priv,
+ int *x, int *y, int *pressure);
};
static irqreturn_t mc13xxx_ts_handler(int irq, void *data)
@@ -67,9 +73,9 @@ static irqreturn_t mc13xxx_ts_handler(int irq, void *data)
swap(a0, a1); \
})
-static void mc13xxx_ts_report_sample(struct mc13xxx_ts_priv *priv)
+static bool mc13783_convert_and_check_samples(struct mc13xxx_ts_priv *priv,
+ int *x, int *y, int *pressure)
{
- struct input_dev *idev = priv->idev;
int x0, x1, x2, y0, y1, y2;
int cr0, cr1;
@@ -86,32 +92,100 @@ static void mc13xxx_ts_report_sample(struct mc13xxx_ts_priv *priv)
cr0 = (priv->sample[2] >> 12) & 0xfff;
cr1 = (priv->sample[3] >> 12) & 0xfff;
- dev_dbg(&idev->dev,
+ dev_dbg(&priv->idev->dev,
"x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
x0, x1, x2, y0, y1, y2, cr0, cr1);
sort3(x0, x1, x2);
sort3(y0, y1, y2);
+ if (sample_tolerance && ((x2 - x0 >= sample_tolerance)
+ || (y2 - y0 >= sample_tolerance)))
+ return false;
+
+ /* report the median coordinate and average pressure */
+ *x = x1;
+ *y = y1;
cr0 = (cr0 + cr1) / 2;
+ *pressure = cr0 ? 0x1000 - cr0 : cr0;
- if (!cr0 || !sample_tolerance ||
- (x2 - x0 < sample_tolerance &&
- y2 - y0 < sample_tolerance)) {
- /* report the median coordinate and average pressure */
- if (cr0) {
- input_report_abs(idev, ABS_X, x1);
- input_report_abs(idev, ABS_Y, y1);
+ return true;
+}
+
+/*
+ * Any ADC readings for contact pressure are only valid below if they are
+ * below TOUCHED_ADC_THRESH. We don't use the full scale of the ADC because
+ * the touchscreen doesn't always read 0xfff when the ts is not touched.
+ */
+#define TOUCHED_ADC_THRESH 2048
+static bool mc13892_convert_and_check_samples(struct mc13xxx_ts_priv *priv,
+ int *x, int *y, int *pressure)
+{
+ int x0, x1, y0, y1;
+ int cr0, cr1;
+ bool both_cr_invalid;
+
+ /*
+ * the values are 10-bit wide only, but the two least significant
+ * bits are for future 12 bit use and reading yields 0
+ */
+ x0 = priv->sample[0] & 0xfff;
+ x1 = priv->sample[1] & 0xfff;
+ y0 = priv->sample[3] & 0xfff;
+ y1 = (priv->sample[0] >> 12) & 0xfff;
+ cr0 = (priv->sample[2] >> 12) & 0xfff;
+ cr1 = (priv->sample[3] >> 12) & 0xfff;
+
+ dev_dbg(&priv->idev->dev,
+ "x: (%4d,%4d) y: (%4d, %4d) cr: (%4d, %4d)\n",
+ x0, x1, y0, y1, cr0, cr1);
+
+ /*
+ * if both cr values are above threshold then the pen up has occurred,
+ * but the values can often be quite far apart, so don't filter them
+ * out based on sample tolerance in this case.
+ */
+ both_cr_invalid = (cr0 > TOUCHED_ADC_THRESH)
+ && (cr1 > TOUCHED_ADC_THRESH);
+
+ if (sample_tolerance &&
+ (((abs(x1 - x0) >= sample_tolerance)
+ || (abs(y1 - y0) >= sample_tolerance))
+ || (!both_cr_invalid
+ && (abs(cr0 - cr1) >= sample_tolerance))))
+ return false;
+
+ *x = (x0 + x1) / 2;
+ *y = (y0 + y1) / 2;
+ cr0 = (cr0 + cr1) / 2;
+
+ /* turn contact resistance into pressure. */
+ if (both_cr_invalid || (cr0 >= TOUCHED_ADC_THRESH))
+ *pressure = 0;
+ else
+ *pressure = TOUCHED_ADC_THRESH - cr0;
+
+ return true;
+}
+
+static void mc13xxx_ts_report_sample(struct mc13xxx_ts_priv *priv)
+{
+ struct input_dev *idev = priv->idev;
+ int x, y, pressure;
+
+ if (priv->convert_and_check_samples(priv, &x, &y, &pressure)) {
+ if (pressure) {
+ input_report_abs(idev, ABS_X, x);
+ input_report_abs(idev, ABS_Y, y);
dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
- x1, y1, 0x1000 - cr0);
+ x, y, pressure);
queue_delayed_work(priv->workq, &priv->work, HZ / 50);
} else
dev_dbg(&idev->dev, "report release\n");
- input_report_abs(idev, ABS_PRESSURE,
- cr0 ? 0x1000 - cr0 : cr0);
- input_report_key(idev, BTN_TOUCH, cr0);
+ input_report_abs(idev, ABS_PRESSURE, pressure);
+ input_report_key(idev, BTN_TOUCH, pressure ? 1 : 0);
input_sync(idev);
} else
dev_dbg(&idev->dev, "discard event\n");
@@ -165,10 +239,14 @@ static void mc13xxx_ts_close(struct input_dev *dev)
cancel_delayed_work_sync(&priv->work);
}
+#define DRIVERID_MC13783 0
+#define DRIVERID_MC13892 1
+
static int __init mc13xxx_ts_probe(struct platform_device *pdev)
{
struct mc13xxx_ts_priv *priv;
struct input_dev *idev;
+ const struct platform_device_id *devid;
int ret = -ENOMEM;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -195,11 +273,26 @@ static int __init mc13xxx_ts_probe(struct platform_device *pdev)
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
- input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
idev->open = mc13xxx_ts_open;
idev->close = mc13xxx_ts_close;
+ devid = platform_get_device_id(pdev);
+
+ if (devid->driver_data == DRIVERID_MC13783) {
+ input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
+ priv->convert_and_check_samples =
+ mc13783_convert_and_check_samples;
+ } else if (devid->driver_data == DRIVERID_MC13892) {
+ input_set_abs_params(idev, ABS_PRESSURE, 0,
+ TOUCHED_ADC_THRESH - 1, 0, 0);
+ priv->convert_and_check_samples =
+ mc13892_convert_and_check_samples;
+ } else {
+ ret = -ENODEV;
+ goto err_destroy_wq;
+ }
+
input_set_drvdata(idev, priv);
ret = input_register_device(priv->idev);
@@ -232,10 +325,13 @@ static int __devexit mc13xxx_ts_remove(struct platform_device *pdev)
return 0;
}
-
const struct platform_device_id mc13xxx_ts_idtable[] = {
{
.name = "mc13783-ts",
+ .driver_data = DRIVERID_MC13783,
+ }, {
+ .name = "mc13892-ts",
+ .driver_data = DRIVERID_MC13892,
},
{ }
};
--
1.7.3.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] input: mc13xxx_ts: handle bad adc conversions
2012-01-29 22:51 mc13892 touchscreen support Marc Reilly
2012-01-29 22:51 ` [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts Marc Reilly
2012-01-29 22:51 ` [PATCH 2/4] input: mc13xxx_ts: add support for mc13892 Marc Reilly
@ 2012-01-29 22:51 ` Marc Reilly
2012-01-29 22:51 ` [PATCH 4/4] input: mc13xxx_ts: intersperse delays between ts samples Marc Reilly
3 siblings, 0 replies; 7+ messages in thread
From: Marc Reilly @ 2012-01-29 22:51 UTC (permalink / raw)
To: linux-input; +Cc: s.hauer, linux-arm-kernel, u.kleine-koenig, Marc Reilly
Before, if the adc conversion failed for some reason then no more
samples would be taken until the after the next pen up/down interrupt.
Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
---
drivers/input/touchscreen/mc13xxx_ts.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/input/touchscreen/mc13xxx_ts.c b/drivers/input/touchscreen/mc13xxx_ts.c
index 264b977..8924d66 100644
--- a/drivers/input/touchscreen/mc13xxx_ts.c
+++ b/drivers/input/touchscreen/mc13xxx_ts.c
@@ -199,8 +199,12 @@ static void mc13xxx_ts_work(struct work_struct *work)
unsigned int channel = 12;
if (mc13xxx_adc_do_conversion(priv->mc13xxx,
- mode, channel, priv->sample) == 0)
+ mode, channel, priv->sample) == 0) {
mc13xxx_ts_report_sample(priv);
+ } else {
+ dev_warn(&priv->idev->dev, "bad conversion");
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ }
}
static int mc13xxx_ts_open(struct input_dev *dev)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] input: mc13xxx_ts: intersperse delays between ts samples
2012-01-29 22:51 mc13892 touchscreen support Marc Reilly
` (2 preceding siblings ...)
2012-01-29 22:51 ` [PATCH 3/4] input: mc13xxx_ts: handle bad adc conversions Marc Reilly
@ 2012-01-29 22:51 ` Marc Reilly
3 siblings, 0 replies; 7+ messages in thread
From: Marc Reilly @ 2012-01-29 22:51 UTC (permalink / raw)
To: linux-input; +Cc: s.hauer, linux-arm-kernel, u.kleine-koenig, Marc Reilly
The mc13xxx ICs have the ability to add a small delay in between each
sample taken in a set of TS samples. This allows time for the ts to be
biased correctly, and improved accuracy of raw readings.
Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
---
drivers/input/touchscreen/mc13xxx_ts.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/mc13xxx_ts.c b/drivers/input/touchscreen/mc13xxx_ts.c
index 8924d66..f46e49d 100644
--- a/drivers/input/touchscreen/mc13xxx_ts.c
+++ b/drivers/input/touchscreen/mc13xxx_ts.c
@@ -197,9 +197,13 @@ static void mc13xxx_ts_work(struct work_struct *work)
container_of(work, struct mc13xxx_ts_priv, work.work);
unsigned int mode = MC13XXX_ADC_MODE_TS;
unsigned int channel = 12;
+ u32 adc1_mask = MC13XXX_ADC1_ATOX | MC13XXX_ADC1_ATO_MASK;
+ u32 adc1_val = MC13XXX_ADC1_ATOX | (3 << MC13XXX_ADC1_ATO_SHIFT);
- if (mc13xxx_adc_do_conversion(priv->mc13xxx,
- mode, channel, priv->sample) == 0) {
+ if (mc13xxx_adc_do_conversion_ex(priv->mc13xxx,
+ mode, channel, priv->sample,
+ 0, 0,
+ adc1_mask, adc1_val) == 0) {
mc13xxx_ts_report_sample(priv);
} else {
dev_warn(&priv->idev->dev, "bad conversion");
--
1.7.3.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts
2012-01-29 22:51 ` [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts Marc Reilly
@ 2012-01-30 2:52 ` Fabio Estevam
2012-01-30 7:33 ` Uwe Kleine-König
0 siblings, 1 reply; 7+ messages in thread
From: Fabio Estevam @ 2012-01-30 2:52 UTC (permalink / raw)
To: Marc Reilly; +Cc: linux-input, s.hauer, linux-arm-kernel, u.kleine-koenig
Hi Marc,
On Sun, Jan 29, 2012 at 8:51 PM, Marc Reilly <marc@cpdesign.com.au> wrote:
> Start moving this driver towards support for both mc13892 and mc13783.
>
> This patch simply renames mc13783 specific identifiers to the generic
> mc13xxx. A platform_device_id table is also added so that the driver
> is still created correctly for the mc13783 only.
>
> Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
> ---
> drivers/input/touchscreen/Kconfig | 8 +-
> drivers/input/touchscreen/Makefile | 2 +-
> drivers/input/touchscreen/mc13783_ts.c | 259 -------------------------------
> drivers/input/touchscreen/mc13xxx_ts.c | 267 ++++++++++++++++++++++++++++++++
> 4 files changed, 272 insertions(+), 264 deletions(-)
> delete mode 100644 drivers/input/touchscreen/mc13783_ts.c
> create mode 100644 drivers/input/touchscreen/mc13xxx_ts.c
For the rename, it is better to do:
git mv drivers/input/touchscreen/mc13783_ts.c
drivers/input/touchscreen/mc13xxx_ts.c
git commit -a
and then git format -M -1 , as it will detect the rename.
Regards,
Fabio Estevam
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts
2012-01-30 2:52 ` Fabio Estevam
@ 2012-01-30 7:33 ` Uwe Kleine-König
0 siblings, 0 replies; 7+ messages in thread
From: Uwe Kleine-König @ 2012-01-30 7:33 UTC (permalink / raw)
To: Fabio Estevam; +Cc: Marc Reilly, linux-input, s.hauer, linux-arm-kernel
Hello,
On Mon, Jan 30, 2012 at 12:52:59AM -0200, Fabio Estevam wrote:
> On Sun, Jan 29, 2012 at 8:51 PM, Marc Reilly <marc@cpdesign.com.au> wrote:
> > Start moving this driver towards support for both mc13892 and mc13783.
> >
> > This patch simply renames mc13783 specific identifiers to the generic
> > mc13xxx. A platform_device_id table is also added so that the driver
> > is still created correctly for the mc13783 only.
> >
> > Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
> > ---
> > drivers/input/touchscreen/Kconfig | 8 +-
> > drivers/input/touchscreen/Makefile | 2 +-
> > drivers/input/touchscreen/mc13783_ts.c | 259 -------------------------------
> > drivers/input/touchscreen/mc13xxx_ts.c | 267 ++++++++++++++++++++++++++++++++
> > 4 files changed, 272 insertions(+), 264 deletions(-)
> > delete mode 100644 drivers/input/touchscreen/mc13783_ts.c
> > create mode 100644 drivers/input/touchscreen/mc13xxx_ts.c
>
> For the rename, it is better to do:
> git mv drivers/input/touchscreen/mc13783_ts.c
> drivers/input/touchscreen/mc13xxx_ts.c
>
> git commit -a
>
> and then git format -M -1 , as it will detect the rename.
git format-patch -M will detect the rename independently of how the
commit was created. Using git mv doesn't result in adding any special
metadata to the commit, it's just mv $old $new; git rm $old; git add
$new.
But +1 on using -M (or not renaming the driver).
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-01-30 7:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-29 22:51 mc13892 touchscreen support Marc Reilly
2012-01-29 22:51 ` [PATCH 1/4] input: mc13783_ts: rename to mc13xxx_ts Marc Reilly
2012-01-30 2:52 ` Fabio Estevam
2012-01-30 7:33 ` Uwe Kleine-König
2012-01-29 22:51 ` [PATCH 2/4] input: mc13xxx_ts: add support for mc13892 Marc Reilly
2012-01-29 22:51 ` [PATCH 3/4] input: mc13xxx_ts: handle bad adc conversions Marc Reilly
2012-01-29 22:51 ` [PATCH 4/4] input: mc13xxx_ts: intersperse delays between ts samples Marc Reilly
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).