blob: 7ba896a3888c6da4b17dc69bdbe3926f3b4aa63c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* drivers/input/touchscreen/msm_touch.c
2 *
3 * Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/slab.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/input.h>
21#include <linux/platform_device.h>
22#include <linux/jiffies.h>
23#include <linux/io.h>
24
25#include <mach/msm_touch.h>
26
27/* HW register map */
28#define TSSC_CTL_REG 0x100
29#define TSSC_SI_REG 0x108
30#define TSSC_OPN_REG 0x104
31#define TSSC_STATUS_REG 0x10C
32#define TSSC_AVG12_REG 0x110
33
34/* status bits */
35#define TSSC_STS_OPN_SHIFT 0x6
36#define TSSC_STS_OPN_BMSK 0x1C0
37#define TSSC_STS_NUMSAMP_SHFT 0x1
38#define TSSC_STS_NUMSAMP_BMSK 0x3E
39
40/* CTL bits */
41#define TSSC_CTL_EN (0x1 << 0)
42#define TSSC_CTL_SW_RESET (0x1 << 2)
43#define TSSC_CTL_MASTER_MODE (0x3 << 3)
44#define TSSC_CTL_AVG_EN (0x1 << 5)
45#define TSSC_CTL_DEB_EN (0x1 << 6)
46#define TSSC_CTL_DEB_12_MS (0x2 << 7) /* 1.2 ms */
47#define TSSC_CTL_DEB_16_MS (0x3 << 7) /* 1.6 ms */
48#define TSSC_CTL_DEB_2_MS (0x4 << 7) /* 2 ms */
49#define TSSC_CTL_DEB_3_MS (0x5 << 7) /* 3 ms */
50#define TSSC_CTL_DEB_4_MS (0x6 << 7) /* 4 ms */
51#define TSSC_CTL_DEB_6_MS (0x7 << 7) /* 6 ms */
52#define TSSC_CTL_INTR_FLAG1 (0x1 << 10)
53#define TSSC_CTL_DATA (0x1 << 11)
54#define TSSC_CTL_SSBI_CTRL_EN (0x1 << 13)
55
56/* control reg's default state */
57#define TSSC_CTL_STATE ( \
58 TSSC_CTL_DEB_12_MS | \
59 TSSC_CTL_DEB_EN | \
60 TSSC_CTL_AVG_EN | \
61 TSSC_CTL_MASTER_MODE | \
62 TSSC_CTL_EN)
63
64#define TSSC_NUMBER_OF_OPERATIONS 2
65#define TS_PENUP_TIMEOUT_MS 20
66
67#define TS_DRIVER_NAME "msm_touchscreen"
68
69#define X_MAX 1024
70#define Y_MAX 1024
71#define P_MAX 256
72
73struct ts {
74 struct input_dev *input;
75 struct timer_list timer;
76 int irq;
77 unsigned int x_max;
78 unsigned int y_max;
79};
80
81static void __iomem *virt;
82#define TSSC_REG(reg) (virt + TSSC_##reg##_REG)
83
84static void ts_update_pen_state(struct ts *ts, int x, int y, int pressure)
85{
86 if (pressure) {
87 input_report_abs(ts->input, ABS_X, x);
88 input_report_abs(ts->input, ABS_Y, y);
89 input_report_abs(ts->input, ABS_PRESSURE, pressure);
90 input_report_key(ts->input, BTN_TOUCH, !!pressure);
91 } else {
92 input_report_abs(ts->input, ABS_PRESSURE, 0);
93 input_report_key(ts->input, BTN_TOUCH, 0);
94 }
95
96 input_sync(ts->input);
97}
98
99static void ts_timer(unsigned long arg)
100{
101 struct ts *ts = (struct ts *)arg;
102
103 ts_update_pen_state(ts, 0, 0, 0);
104}
105
106static irqreturn_t ts_interrupt(int irq, void *dev_id)
107{
108 u32 avgs, x, y, lx, ly;
109 u32 num_op, num_samp;
110 u32 status;
111
112 struct ts *ts = dev_id;
113
114 status = readl_relaxed(TSSC_REG(STATUS));
115 avgs = readl_relaxed(TSSC_REG(AVG12));
116 x = avgs & 0xFFFF;
117 y = avgs >> 16;
118
119 /* For pen down make sure that the data just read is still valid.
120 * The DATA bit will still be set if the ARM9 hasn't clobbered
121 * the TSSC. If it's not set, then it doesn't need to be cleared
122 * here, so just return.
123 */
124 if (!(readl_relaxed(TSSC_REG(CTL)) & TSSC_CTL_DATA))
125 goto out;
126
127 /* Data has been read, OK to clear the data flag */
128 writel_relaxed(TSSC_CTL_STATE, TSSC_REG(CTL));
129 /* barrier: Write to complete before the next sample */
130 mb();
131 /* Valid samples are indicated by the sample number in the status
132 * register being the number of expected samples and the number of
133 * samples collected being zero (this check is due to ADC contention).
134 */
135 num_op = (status & TSSC_STS_OPN_BMSK) >> TSSC_STS_OPN_SHIFT;
136 num_samp = (status & TSSC_STS_NUMSAMP_BMSK) >> TSSC_STS_NUMSAMP_SHFT;
137
138 if ((num_op == TSSC_NUMBER_OF_OPERATIONS) && (num_samp == 0)) {
139 /* TSSC can do Z axis measurment, but driver doesn't support
140 * this yet.
141 */
142
143 /*
144 * REMOVE THIS:
145 * These x, y co-ordinates adjustments will be removed once
146 * Android framework adds calibration framework.
147 */
148#ifdef CONFIG_ANDROID_TOUCHSCREEN_MSM_HACKS
149 lx = ts->x_max - x;
150 ly = ts->y_max - y;
151#else
152 lx = x;
153 ly = y;
154#endif
155 ts_update_pen_state(ts, lx, ly, 255);
156 /* kick pen up timer - to make sure it expires again(!) */
157 mod_timer(&ts->timer,
158 jiffies + msecs_to_jiffies(TS_PENUP_TIMEOUT_MS));
159
160 } else
161 printk(KERN_INFO "Ignored interrupt: {%3d, %3d},"
162 " op = %3d samp = %3d\n",
163 x, y, num_op, num_samp);
164
165out:
166 return IRQ_HANDLED;
167}
168
169static int __devinit ts_probe(struct platform_device *pdev)
170{
171 int result;
172 struct input_dev *input_dev;
173 struct resource *res, *ioarea;
174 struct ts *ts;
175 unsigned int x_max, y_max, pressure_max;
176 struct msm_ts_platform_data *pdata = pdev->dev.platform_data;
177
178 /* The primary initialization of the TS Hardware
179 * is taken care of by the ADC code on the modem side
180 */
181
182 ts = kzalloc(sizeof(struct ts), GFP_KERNEL);
183 input_dev = input_allocate_device();
184 if (!input_dev || !ts) {
185 result = -ENOMEM;
186 goto fail_alloc_mem;
187 }
188
189 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
190 if (!res) {
191 dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
192 result = -ENOENT;
193 goto fail_alloc_mem;
194 }
195
196 ts->irq = platform_get_irq(pdev, 0);
197 if (!ts->irq) {
198 dev_err(&pdev->dev, "Could not get IORESOURCE_IRQ\n");
199 result = -ENODEV;
200 goto fail_alloc_mem;
201 }
202
203 ioarea = request_mem_region(res->start, resource_size(res), pdev->name);
204 if (!ioarea) {
205 dev_err(&pdev->dev, "Could not allocate io region\n");
206 result = -EBUSY;
207 goto fail_alloc_mem;
208 }
209
210 virt = ioremap(res->start, resource_size(res));
211 if (!virt) {
212 dev_err(&pdev->dev, "Could not ioremap region\n");
213 result = -ENOMEM;
214 goto fail_ioremap;
215 }
216
217 input_dev->name = TS_DRIVER_NAME;
218 input_dev->phys = "msm_touch/input0";
219 input_dev->id.bustype = BUS_HOST;
220 input_dev->id.vendor = 0x0001;
221 input_dev->id.product = 0x0002;
222 input_dev->id.version = 0x0100;
223 input_dev->dev.parent = &pdev->dev;
224
225 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
226 input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
227 input_dev->absbit[BIT_WORD(ABS_MISC)] = BIT_MASK(ABS_MISC);
228 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
229
230 if (pdata) {
231 x_max = pdata->x_max ? : X_MAX;
232 y_max = pdata->y_max ? : Y_MAX;
233 pressure_max = pdata->pressure_max ? : P_MAX;
234 } else {
235 x_max = X_MAX;
236 y_max = Y_MAX;
237 pressure_max = P_MAX;
238 }
239
240 ts->x_max = x_max;
241 ts->y_max = y_max;
242
243 input_set_abs_params(input_dev, ABS_X, 0, x_max, 0, 0);
244 input_set_abs_params(input_dev, ABS_Y, 0, y_max, 0, 0);
245 input_set_abs_params(input_dev, ABS_PRESSURE, 0, pressure_max, 0, 0);
246
247 result = input_register_device(input_dev);
248 if (result)
249 goto fail_ip_reg;
250
251 ts->input = input_dev;
252
253 setup_timer(&ts->timer, ts_timer, (unsigned long)ts);
254 result = request_irq(ts->irq, ts_interrupt, IRQF_TRIGGER_RISING,
255 "touchscreen", ts);
256 if (result)
257 goto fail_req_irq;
258
259 platform_set_drvdata(pdev, ts);
260
261 return 0;
262
263fail_req_irq:
264 input_unregister_device(input_dev);
265 input_dev = NULL;
266fail_ip_reg:
267 iounmap(virt);
268fail_ioremap:
269 release_mem_region(res->start, resource_size(res));
270fail_alloc_mem:
271 input_free_device(input_dev);
272 kfree(ts);
273 return result;
274}
275
276static int __devexit ts_remove(struct platform_device *pdev)
277{
278 struct resource *res;
279 struct ts *ts = platform_get_drvdata(pdev);
280
281 free_irq(ts->irq, ts);
282 del_timer_sync(&ts->timer);
283
284 input_unregister_device(ts->input);
285 iounmap(virt);
286 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
287 release_mem_region(res->start, resource_size(res));
288 platform_set_drvdata(pdev, NULL);
289 kfree(ts);
290
291 return 0;
292}
293
294static struct platform_driver ts_driver = {
295 .probe = ts_probe,
296 .remove = __devexit_p(ts_remove),
297 .driver = {
298 .name = TS_DRIVER_NAME,
299 .owner = THIS_MODULE,
300 },
301};
302
303static int __init ts_init(void)
304{
305 return platform_driver_register(&ts_driver);
306}
307module_init(ts_init);
308
309static void __exit ts_exit(void)
310{
311 platform_driver_unregister(&ts_driver);
312}
313module_exit(ts_exit);
314
315MODULE_DESCRIPTION("MSM Touch Screen driver");
316MODULE_LICENSE("GPL v2");
317MODULE_ALIAS("platform:msm_touchscreen");