Root/target/linux/xburst/patches-2.6.37/061-touchscreen.patch

1From d231cea1dca0c1b04d11cbf996077cf59612e3c4 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 20:45:08 +0200
4Subject: [PATCH 14/23] input: Add touchscreen driver for the JZ4740 SoC
5
6This patch adds a touchscreen driver for the Ingenic JZ4740 SoC.
7The touchscreen controller is part of the ADC unit and thus this driver is a mfd
8cell from the jz4740-adc driver.
9
10Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
11---
12 drivers/input/touchscreen/Kconfig | 12 ++
13 drivers/input/touchscreen/Makefile | 1 +
14 drivers/input/touchscreen/jz4740-ts.c | 330 +++++++++++++++++++++++++++++++++
15 3 files changed, 343 insertions(+), 0 deletions(-)
16 create mode 100644 drivers/input/touchscreen/jz4740-ts.c
17
18--- a/drivers/input/touchscreen/Kconfig
19+++ b/drivers/input/touchscreen/Kconfig
20@@ -681,4 +681,16 @@ config TOUCHSCREEN_STMPE
21       To compile this driver as a module, choose M here: the
22       module will be called stmpe-ts.
23 
24+config TOUCHSCREEN_JZ4740
25+ tristate "JZ4740 touchscreen support"
26+ depends on MFD_JZ4740_ADC
27+ help
28+ Say Y here if you want support for the touchscreen controller found on
29+ Ingenic JZ4740 SoCs.
30+
31+ If unsure, say N.
32+
33+ To compile this driver as a module, choose M here: the
34+ module will be called jz4740-ts.
35+
36 endif
37--- a/drivers/input/touchscreen/Makefile
38+++ b/drivers/input/touchscreen/Makefile
39@@ -26,6 +26,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fuj
40 obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
41 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
42 obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
43+obj-$(CONFIG_TOUCHSCREEN_JZ4740) += jz4740-ts.o
44 obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
45 obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
46 obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
47--- /dev/null
48+++ b/drivers/input/touchscreen/jz4740-ts.c
49@@ -0,0 +1,330 @@
50+/*
51+ * Touchscreen driver for Ingenic JZ SoCs.
52+ *
53+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
54+ *
55+ * This program is free software; you can redistribute it and/or modify
56+ * it under the terms of the GNU General Public License version 2 as
57+ * published by the Free Software Foundation.
58+ *
59+ */
60+
61+#include <linux/interrupt.h>
62+#include <linux/kernel.h>
63+#include <linux/module.h>
64+#include <linux/platform_device.h>
65+#include <linux/slab.h>
66+
67+#include <linux/delay.h>
68+#include <linux/mfd/core.h>
69+#include <linux/input.h>
70+#include <linux/bitops.h>
71+#include <linux/jz4740-adc.h>
72+
73+struct jz4740_ts {
74+ struct platform_device *pdev;
75+
76+ struct resource *mem;
77+ void __iomem *base;
78+
79+ int irq_penup;
80+ int irq_pendown;
81+ int irq_data_ready;
82+
83+ struct mfd_cell *cell;
84+ struct input_dev *input;
85+
86+ bool is_open;
87+};
88+
89+static irqreturn_t jz4740_ts_data_ready_irq_handler(int irq, void *devid)
90+{
91+ struct jz4740_ts *jz4740_ts = devid;
92+ uint32_t data;
93+ unsigned long x, y, z1, z2, pressure;
94+
95+ data = readl(jz4740_ts->base + 0x08);
96+ x = data & 0xfff;
97+ y = (data >> 16) & 0xfff;
98+
99+ data = readl(jz4740_ts->base + 0x08);
100+ z1 = data & 0xfff;
101+ z2 = (data >> 16) & 0xfff;
102+ if (z1 == 0) {
103+ pressure = 4095UL;
104+ } else if (z1 > z2) {
105+ pressure = 0;
106+ } else {
107+ if (data & 0x8000)
108+ pressure = (((480UL * x * z2) / z1) - 480UL * x) / 4096UL;
109+ else
110+ pressure = (((272UL * y * z2) / z1) - 272UL * y) / 4096UL;
111+ if (pressure >= 4096UL)
112+ pressure = 4095UL;
113+ pressure = 4095UL - pressure;
114+ }
115+
116+ input_report_abs(jz4740_ts->input, ABS_X, y);
117+ input_report_abs(jz4740_ts->input, ABS_Y, 4095 - x);
118+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, pressure);
119+ input_report_key(jz4740_ts->input, BTN_TOUCH, 1);
120+ input_sync(jz4740_ts->input);
121+
122+ return IRQ_HANDLED;
123+}
124+
125+static irqreturn_t jz4740_ts_pen_irq_handler(int irq, void *devid)
126+{
127+ struct jz4740_ts *jz4740_ts = devid;
128+ int is_pressed;
129+
130+ if (irq == jz4740_ts->irq_penup) {
131+ enable_irq(jz4740_ts->irq_pendown);
132+ is_pressed = 0;
133+ } else {
134+ enable_irq(jz4740_ts->irq_penup);
135+ is_pressed = 1;
136+ }
137+ disable_irq_nosync(irq);
138+
139+ printk("pen irq: %d\n", irq);
140+ input_report_key(jz4740_ts->input, BTN_TOUCH, is_pressed);
141+ if (is_pressed == 0)
142+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, 0);
143+ input_sync(jz4740_ts->input);
144+
145+ return IRQ_HANDLED;
146+}
147+
148+static int jz4740_ts_open(struct input_dev *input)
149+{
150+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
151+
152+ jz4740_ts->is_open = true;
153+ jz4740_ts->cell->enable(jz4740_ts->pdev);
154+
155+ return 0;
156+}
157+
158+static void jz4740_ts_close(struct input_dev *input)
159+{
160+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
161+
162+ jz4740_ts->cell->disable(jz4740_ts->pdev);
163+ jz4740_ts->is_open = false;
164+}
165+
166+static int __devinit jz4740_ts_probe(struct platform_device *pdev)
167+{
168+ int ret = 0;
169+ struct jz4740_ts *jz4740_ts;
170+ struct input_dev *input;
171+
172+ jz4740_ts = kzalloc(sizeof(*jz4740_ts), GFP_KERNEL);
173+ if (!jz4740_ts) {
174+ dev_err(&pdev->dev, "Failed to allocate driver structure\n");
175+ return -ENOMEM;
176+ }
177+
178+ jz4740_ts->pdev = pdev;
179+ jz4740_ts->cell = pdev->dev.platform_data;
180+
181+ jz4740_ts->irq_data_ready = platform_get_irq(pdev, 0);
182+ if (jz4740_ts->irq_data_ready < 0) {
183+ ret = jz4740_ts->irq_data_ready;
184+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
185+ goto err_free;
186+ }
187+
188+ jz4740_ts->irq_penup = platform_get_irq(pdev, 1);
189+ if (jz4740_ts->irq_penup < 0) {
190+ ret = jz4740_ts->irq_penup;
191+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
192+ goto err_free;
193+ }
194+
195+ jz4740_ts->irq_pendown = platform_get_irq(pdev, 2);
196+ if (jz4740_ts->irq_pendown < 0) {
197+ ret = jz4740_ts->irq_pendown;
198+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
199+ goto err_free;
200+ }
201+
202+ jz4740_ts->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203+ if (!jz4740_ts->mem) {
204+ ret = -ENOENT;
205+ dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
206+ goto err_free;
207+ }
208+
209+ jz4740_ts->mem = request_mem_region(jz4740_ts->mem->start,
210+ resource_size(jz4740_ts->mem), pdev->name);
211+ if (!jz4740_ts->mem) {
212+ ret = -EBUSY;
213+ dev_err(&pdev->dev, "Failed to request mmio memory region\n");
214+ goto err_free;
215+ }
216+
217+ jz4740_ts->base = ioremap_nocache(jz4740_ts->mem->start,
218+ resource_size(jz4740_ts->mem));
219+ if (!jz4740_ts->base) {
220+ ret = -EBUSY;
221+ dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
222+ goto err_release_mem_region;
223+ }
224+
225+ input = input_allocate_device();
226+ if (!input) {
227+ dev_err(&pdev->dev, "Failed to allocate input device\n");
228+ ret = -ENOMEM;
229+ goto err_iounmap;
230+ }
231+
232+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
233+ __set_bit(BTN_TOUCH, input->keybit);
234+
235+ input_set_abs_params(input, ABS_X, 150, 3920, 0, 0);
236+ input_set_abs_params(input, ABS_Y, 270, 3700, 0, 0);
237+ input_set_abs_params(input, ABS_PRESSURE, 0, 4096, 0, 0);
238+
239+ input->name = pdev->name;
240+ input->phys = "jz4740";
241+ input->id.bustype = BUS_HOST;
242+ input->dev.parent = &pdev->dev;
243+
244+ input->open = jz4740_ts_open;
245+ input->close = jz4740_ts_close;
246+
247+ input_set_drvdata(input, jz4740_ts);
248+
249+ ret = input_register_device(input);
250+ if (ret) {
251+ dev_err(&pdev->dev, "Failed to register input device: %d\n", ret);
252+ input_free_device(input);
253+ goto err_iounmap;
254+ }
255+ jz4740_ts->input = input;
256+
257+ ret = request_irq(jz4740_ts->irq_data_ready, jz4740_ts_data_ready_irq_handler, 0, pdev->name,
258+ jz4740_ts);
259+ if (ret) {
260+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
261+ goto err_input_unregister_device;
262+ }
263+ ret = request_irq(jz4740_ts->irq_penup, jz4740_ts_pen_irq_handler, 0, pdev->name,
264+ jz4740_ts);
265+ if (ret) {
266+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
267+ goto err_free_irq_data_ready;
268+ }
269+ disable_irq(jz4740_ts->irq_penup);
270+ ret = request_irq(jz4740_ts->irq_pendown, jz4740_ts_pen_irq_handler, 0, pdev->name,
271+ jz4740_ts);
272+ if (ret) {
273+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
274+ goto err_free_irq_penup;
275+ }
276+ platform_set_drvdata(pdev, jz4740_ts);
277+
278+ jz4740_adc_set_config(pdev->dev.parent,
279+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_OFFSET(2) | JZ_ADC_CONFIG_DNUM(7),
280+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_MASK | JZ_ADC_CONFIG_DNUM_MASK);
281+
282+
283+ writel(0x15e, jz4740_ts->base);
284+ writel(0x32, jz4740_ts->base + 0x04);
285+
286+ return 0;
287+
288+err_free_irq_penup:
289+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
290+err_free_irq_data_ready:
291+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
292+err_input_unregister_device:
293+ input_unregister_device(jz4740_ts->input);
294+err_iounmap:
295+ platform_set_drvdata(pdev, NULL);
296+ iounmap(jz4740_ts->base);
297+err_release_mem_region:
298+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
299+err_free:
300+ kfree(jz4740_ts);
301+ return ret;
302+}
303+
304+static int __devexit jz4740_ts_remove(struct platform_device *pdev)
305+{
306+ struct jz4740_ts *jz4740_ts = platform_get_drvdata(pdev);
307+
308+
309+ free_irq(jz4740_ts->irq_pendown, jz4740_ts);
310+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
311+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
312+
313+ input_unregister_device(jz4740_ts->input);
314+
315+ iounmap(jz4740_ts->base);
316+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
317+
318+ kfree(jz4740_ts);
319+
320+ return 0;
321+}
322+
323+#ifdef CONFIG_PM
324+static int jz4740_ts_suspend(struct device *dev)
325+{
326+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
327+
328+ if (jz4740_ts->is_open);
329+ jz4740_ts->cell->disable(jz4740_ts->pdev);
330+
331+ return 0;
332+}
333+
334+static int jz4740_ts_resume(struct device *dev)
335+{
336+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
337+
338+ if (jz4740_ts->is_open);
339+ jz4740_ts->cell->enable(jz4740_ts->pdev);
340+
341+ return 0;
342+}
343+
344+static const struct dev_pm_ops jz4740_ts_pm_ops = {
345+ .suspend = jz4740_ts_suspend,
346+ .resume = jz4740_ts_resume,
347+};
348+
349+#define JZ4740_TS_PM_OPS (&jz4740_ts_pm_ops)
350+#else
351+#define JZ4740_TS_PM_OPS NULL
352+#endif
353+
354+static struct platform_driver jz4740_ts_driver = {
355+ .probe = jz4740_ts_probe,
356+ .remove = __devexit_p(jz4740_ts_remove),
357+ .driver = {
358+ .name = "jz4740-ts",
359+ .owner = THIS_MODULE,
360+ .pm = JZ4740_TS_PM_OPS,
361+ },
362+};
363+
364+static int __init jz4740_ts_init(void)
365+{
366+ return platform_driver_register(&jz4740_ts_driver);
367+}
368+module_init(jz4740_ts_init);
369+
370+static void __exit jz4740_ts_exit(void)
371+{
372+ platform_driver_unregister(&jz4740_ts_driver);
373+}
374+module_exit(jz4740_ts_exit);
375+
376+MODULE_ALIAS("platform:jz4740-ts");
377+MODULE_LICENSE("GPL");
378+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
379+MODULE_DESCRIPTION("JZ4740 SoC battery driver");
380

Archive Download this file



interactive