Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ti_tscadc.c
Go to the documentation of this file.
1 /*
2  * TI Touch Screen driver
3  *
4  * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  */
15 
16 
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/err.h>
20 #include <linux/module.h>
21 #include <linux/input.h>
22 #include <linux/slab.h>
23 #include <linux/interrupt.h>
24 #include <linux/clk.h>
25 #include <linux/platform_device.h>
26 #include <linux/io.h>
27 #include <linux/input/ti_tscadc.h>
28 #include <linux/delay.h>
29 
30 #define REG_IRQEOI 0x020
31 #define REG_RAWIRQSTATUS 0x024
32 #define REG_IRQSTATUS 0x028
33 #define REG_IRQENABLE 0x02C
34 #define REG_IRQWAKEUP 0x034
35 #define REG_CTRL 0x040
36 #define REG_ADCFSM 0x044
37 #define REG_CLKDIV 0x04C
38 #define REG_SE 0x054
39 #define REG_IDLECONFIG 0x058
40 #define REG_CHARGECONFIG 0x05C
41 #define REG_CHARGEDELAY 0x060
42 #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
43 #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
44 #define REG_STEPCONFIG13 0x0C4
45 #define REG_STEPDELAY13 0x0C8
46 #define REG_STEPCONFIG14 0x0CC
47 #define REG_STEPDELAY14 0x0D0
48 #define REG_FIFO0CNT 0xE4
49 #define REG_FIFO1THR 0xF4
50 #define REG_FIFO0 0x100
51 #define REG_FIFO1 0x200
52 
53 /* Register Bitfields */
54 #define IRQWKUP_ENB BIT(0)
55 #define STPENB_STEPENB 0x7FFF
56 #define IRQENB_FIFO1THRES BIT(5)
57 #define IRQENB_PENUP BIT(9)
58 #define STEPCONFIG_MODE_HWSYNC 0x2
59 #define STEPCONFIG_SAMPLES_AVG (1 << 4)
60 #define STEPCONFIG_XPP (1 << 5)
61 #define STEPCONFIG_XNN (1 << 6)
62 #define STEPCONFIG_YPP (1 << 7)
63 #define STEPCONFIG_YNN (1 << 8)
64 #define STEPCONFIG_XNP (1 << 9)
65 #define STEPCONFIG_YPN (1 << 10)
66 #define STEPCONFIG_INM (1 << 18)
67 #define STEPCONFIG_INP (1 << 20)
68 #define STEPCONFIG_INP_5 (1 << 21)
69 #define STEPCONFIG_FIFO1 (1 << 26)
70 #define STEPCONFIG_OPENDLY 0xff
71 #define STEPCONFIG_Z1 (3 << 19)
72 #define STEPIDLE_INP (1 << 22)
73 #define STEPCHARGE_RFP (1 << 12)
74 #define STEPCHARGE_INM (1 << 15)
75 #define STEPCHARGE_INP (1 << 19)
76 #define STEPCHARGE_RFM (1 << 23)
77 #define STEPCHARGE_DELAY 0x1
78 #define CNTRLREG_TSCSSENB (1 << 0)
79 #define CNTRLREG_STEPID (1 << 1)
80 #define CNTRLREG_STEPCONFIGWRT (1 << 2)
81 #define CNTRLREG_4WIRE (1 << 5)
82 #define CNTRLREG_5WIRE (1 << 6)
83 #define CNTRLREG_8WIRE (3 << 5)
84 #define CNTRLREG_TSCENB (1 << 7)
85 #define ADCFSM_STEPID 0x10
86 
87 #define SEQ_SETTLE 275
88 #define ADC_CLK 3000000
89 #define MAX_12BIT ((1 << 12) - 1)
90 #define TSCADC_DELTA_X 15
91 #define TSCADC_DELTA_Y 15
92 
93 struct tscadc {
94  struct input_dev *input;
95  struct clk *tsc_ick;
97  unsigned int irq;
98  unsigned int wires;
99  unsigned int x_plate_resistance;
100  bool pen_down;
101 };
102 
103 static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
104 {
105  return readl(ts->tsc_base + reg);
106 }
107 
108 static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
109  unsigned int val)
110 {
111  writel(val, tsc->tsc_base + reg);
112 }
113 
114 static void tscadc_step_config(struct tscadc *ts_dev)
115 {
116  unsigned int config;
117  int i;
118 
119  /* Configure the Step registers */
120 
121  config = STEPCONFIG_MODE_HWSYNC |
123  switch (ts_dev->wires) {
124  case 4:
125  config |= STEPCONFIG_INP | STEPCONFIG_XNN;
126  break;
127  case 5:
128  config |= STEPCONFIG_YNN |
131  break;
132  case 8:
133  config |= STEPCONFIG_INP | STEPCONFIG_XNN;
134  break;
135  }
136 
137  for (i = 1; i < 7; i++) {
138  tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
139  tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
140  }
141 
142  config = 0;
143  config = STEPCONFIG_MODE_HWSYNC |
146  switch (ts_dev->wires) {
147  case 4:
148  config |= STEPCONFIG_YPP;
149  break;
150  case 5:
151  config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
153  break;
154  case 8:
155  config |= STEPCONFIG_YPP;
156  break;
157  }
158 
159  for (i = 7; i < 13; i++) {
160  tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
161  tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
162  }
163 
164  config = 0;
165  /* Charge step configuration */
166  config = STEPCONFIG_XPP | STEPCONFIG_YNN |
169 
170  tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
171  tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
172 
173  config = 0;
174  /* Configure to calculate pressure */
175  config = STEPCONFIG_MODE_HWSYNC |
178  tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
179  tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
180 
181  config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
182  tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
183  tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
184 
185  tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
186 }
187 
188 static void tscadc_idle_config(struct tscadc *ts_config)
189 {
190  unsigned int idleconfig;
191 
192  idleconfig = STEPCONFIG_YNN |
195  tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
196 }
197 
198 static void tscadc_read_coordinates(struct tscadc *ts_dev,
199  unsigned int *x, unsigned int *y)
200 {
201  unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
202  unsigned int prev_val_x = ~0, prev_val_y = ~0;
203  unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
204  unsigned int read, diff;
205  unsigned int i;
206 
207  /*
208  * Delta filter is used to remove large variations in sampled
209  * values from ADC. The filter tries to predict where the next
210  * coordinate could be. This is done by taking a previous
211  * coordinate and subtracting it form current one. Further the
212  * algorithm compares the difference with that of a present value,
213  * if true the value is reported to the sub system.
214  */
215  for (i = 0; i < fifocount - 1; i++) {
216  read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
217  diff = abs(read - prev_val_x);
218  if (diff < prev_diff_x) {
219  prev_diff_x = diff;
220  *x = read;
221  }
222  prev_val_x = read;
223 
224  read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
225  diff = abs(read - prev_val_y);
226  if (diff < prev_diff_y) {
227  prev_diff_y = diff;
228  *y = read;
229  }
230  prev_val_y = read;
231  }
232 }
233 
234 static irqreturn_t tscadc_irq(int irq, void *dev)
235 {
236  struct tscadc *ts_dev = dev;
237  struct input_dev *input_dev = ts_dev->input;
238  unsigned int status, irqclr = 0;
239  unsigned int x = 0, y = 0;
240  unsigned int z1, z2, z;
241  unsigned int fsm;
242 
243  status = tscadc_readl(ts_dev, REG_IRQSTATUS);
244  if (status & IRQENB_FIFO1THRES) {
245  tscadc_read_coordinates(ts_dev, &x, &y);
246 
247  z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
248  z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
249 
250  if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
251  /*
252  * Calculate pressure using formula
253  * Resistance(touch) = x plate resistance *
254  * x postion/4096 * ((z2 / z1) - 1)
255  */
256  z = z2 - z1;
257  z *= x;
258  z *= ts_dev->x_plate_resistance;
259  z /= z1;
260  z = (z + 2047) >> 12;
261 
262  if (z <= MAX_12BIT) {
263  input_report_abs(input_dev, ABS_X, x);
264  input_report_abs(input_dev, ABS_Y, y);
265  input_report_abs(input_dev, ABS_PRESSURE, z);
266  input_report_key(input_dev, BTN_TOUCH, 1);
267  input_sync(input_dev);
268  }
269  }
270  irqclr |= IRQENB_FIFO1THRES;
271  }
272 
273  /*
274  * Time for sequencer to settle, to read
275  * correct state of the sequencer.
276  */
278 
279  status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
280  if (status & IRQENB_PENUP) {
281  /* Pen up event */
282  fsm = tscadc_readl(ts_dev, REG_ADCFSM);
283  if (fsm == ADCFSM_STEPID) {
284  ts_dev->pen_down = false;
285  input_report_key(input_dev, BTN_TOUCH, 0);
286  input_report_abs(input_dev, ABS_PRESSURE, 0);
287  input_sync(input_dev);
288  } else {
289  ts_dev->pen_down = true;
290  }
291  irqclr |= IRQENB_PENUP;
292  }
293 
294  tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
295  /* check pending interrupts */
296  tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
297 
298  tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
299  return IRQ_HANDLED;
300 }
301 
302 /*
303  * The functions for inserting/removing driver as a module.
304  */
305 
306 static int __devinit tscadc_probe(struct platform_device *pdev)
307 {
308  const struct tsc_data *pdata = pdev->dev.platform_data;
309  struct resource *res;
310  struct tscadc *ts_dev;
311  struct input_dev *input_dev;
312  struct clk *clk;
313  int err;
314  int clk_value, ctrl, irq;
315 
316  if (!pdata) {
317  dev_err(&pdev->dev, "missing platform data.\n");
318  return -EINVAL;
319  }
320 
321  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
322  if (!res) {
323  dev_err(&pdev->dev, "no memory resource defined.\n");
324  return -EINVAL;
325  }
326 
327  irq = platform_get_irq(pdev, 0);
328  if (irq < 0) {
329  dev_err(&pdev->dev, "no irq ID is specified.\n");
330  return -EINVAL;
331  }
332 
333  /* Allocate memory for device */
334  ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
335  input_dev = input_allocate_device();
336  if (!ts_dev || !input_dev) {
337  dev_err(&pdev->dev, "failed to allocate memory.\n");
338  err = -ENOMEM;
339  goto err_free_mem;
340  }
341 
342  ts_dev->input = input_dev;
343  ts_dev->irq = irq;
344  ts_dev->wires = pdata->wires;
345  ts_dev->x_plate_resistance = pdata->x_plate_resistance;
346 
347  res = request_mem_region(res->start, resource_size(res), pdev->name);
348  if (!res) {
349  dev_err(&pdev->dev, "failed to reserve registers.\n");
350  err = -EBUSY;
351  goto err_free_mem;
352  }
353 
354  ts_dev->tsc_base = ioremap(res->start, resource_size(res));
355  if (!ts_dev->tsc_base) {
356  dev_err(&pdev->dev, "failed to map registers.\n");
357  err = -ENOMEM;
358  goto err_release_mem_region;
359  }
360 
361  err = request_irq(ts_dev->irq, tscadc_irq,
362  0, pdev->dev.driver->name, ts_dev);
363  if (err) {
364  dev_err(&pdev->dev, "failed to allocate irq.\n");
365  goto err_unmap_regs;
366  }
367 
368  ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
369  if (IS_ERR(ts_dev->tsc_ick)) {
370  dev_err(&pdev->dev, "failed to get TSC ick\n");
371  goto err_free_irq;
372  }
373  clk_enable(ts_dev->tsc_ick);
374 
375  clk = clk_get(&pdev->dev, "adc_tsc_fck");
376  if (IS_ERR(clk)) {
377  dev_err(&pdev->dev, "failed to get TSC fck\n");
378  err = PTR_ERR(clk);
379  goto err_disable_clk;
380  }
381 
382  clk_value = clk_get_rate(clk) / ADC_CLK;
383  clk_put(clk);
384 
385  if (clk_value < 7) {
386  dev_err(&pdev->dev, "clock input less than min clock requirement\n");
387  goto err_disable_clk;
388  }
389  /* CLKDIV needs to be configured to the value minus 1 */
390  tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
391 
392  /* Enable wake-up of the SoC using touchscreen */
393  tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
394 
395  ctrl = CNTRLREG_STEPCONFIGWRT |
398  switch (ts_dev->wires) {
399  case 4:
400  ctrl |= CNTRLREG_4WIRE;
401  break;
402  case 5:
403  ctrl |= CNTRLREG_5WIRE;
404  break;
405  case 8:
406  ctrl |= CNTRLREG_8WIRE;
407  break;
408  }
409  tscadc_writel(ts_dev, REG_CTRL, ctrl);
410 
411  tscadc_idle_config(ts_dev);
412  tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
413  tscadc_step_config(ts_dev);
414  tscadc_writel(ts_dev, REG_FIFO1THR, 6);
415 
416  ctrl |= CNTRLREG_TSCSSENB;
417  tscadc_writel(ts_dev, REG_CTRL, ctrl);
418 
419  input_dev->name = "ti-tsc-adc";
420  input_dev->dev.parent = &pdev->dev;
421 
422  input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
423  input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
424 
425  input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
426  input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
427  input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
428 
429  /* register to the input system */
430  err = input_register_device(input_dev);
431  if (err)
432  goto err_disable_clk;
433 
434  platform_set_drvdata(pdev, ts_dev);
435  return 0;
436 
437 err_disable_clk:
438  clk_disable(ts_dev->tsc_ick);
439  clk_put(ts_dev->tsc_ick);
440 err_free_irq:
441  free_irq(ts_dev->irq, ts_dev);
442 err_unmap_regs:
443  iounmap(ts_dev->tsc_base);
444 err_release_mem_region:
445  release_mem_region(res->start, resource_size(res));
446 err_free_mem:
447  input_free_device(input_dev);
448  kfree(ts_dev);
449  return err;
450 }
451 
452 static int __devexit tscadc_remove(struct platform_device *pdev)
453 {
454  struct tscadc *ts_dev = platform_get_drvdata(pdev);
455  struct resource *res;
456 
457  free_irq(ts_dev->irq, ts_dev);
458 
459  input_unregister_device(ts_dev->input);
460 
461  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
462  iounmap(ts_dev->tsc_base);
463  release_mem_region(res->start, resource_size(res));
464 
465  clk_disable(ts_dev->tsc_ick);
466  clk_put(ts_dev->tsc_ick);
467 
468  kfree(ts_dev);
469 
470  platform_set_drvdata(pdev, NULL);
471  return 0;
472 }
473 
474 static struct platform_driver ti_tsc_driver = {
475  .probe = tscadc_probe,
476  .remove = __devexit_p(tscadc_remove),
477  .driver = {
478  .name = "tsc",
479  .owner = THIS_MODULE,
480  },
481 };
482 module_platform_driver(ti_tsc_driver);
483 
484 MODULE_DESCRIPTION("TI touchscreen controller driver");
485 MODULE_AUTHOR("Rachna Patil <[email protected]>");
486 MODULE_LICENSE("GPL");