aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt44
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c105
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c1
3 files changed, 127 insertions, 23 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
new file mode 100644
index 000000000000..491c97b78384
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
@@ -0,0 +1,44 @@
1* TI - TSC ADC (Touschscreen and analog digital converter)
2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4Required properties:
5- child "tsc"
6 ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
7 support on the platform.
8 ti,x-plate-resistance: X plate resistance
9 ti,coordiante-readouts: The sequencer supports a total of 16
10 programmable steps each step is used to
11 read a single coordinate. A single
12 readout is enough but multiple reads can
13 increase the quality.
14 A value of 5 means, 5 reads for X, 5 for
15 Y and 2 for Z (always). This utilises 12
16 of the 16 software steps available. The
17 remaining 4 can be used by the ADC.
18 ti,wire-config: Different boards could have a different order for
19 connecting wires on touchscreen. We need to provide an
20 8 bit number where in the 1st four bits represent the
21 analog lines and the next 4 bits represent positive/
22 negative terminal on that input line. Notations to
23 represent the input lines and terminals resoectively
24 is as follows:
25 AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
26 XP = 0, XN = 1, YP = 2, YN = 3.
27- child "adc"
28 ti,adc-channels: List of analog inputs available for ADC.
29 AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
30
31Example:
32 tscadc: tscadc@44e0d000 {
33 compatible = "ti,am3359-tscadc";
34 tsc {
35 ti,wires = <4>;
36 ti,x-plate-resistance = <200>;
37 ti,coordiante-readouts = <5>;
38 ti,wire-config = <0x00 0x11 0x22 0x33>;
39 };
40
41 adc {
42 ti,adc-channels = <4 5 6 7>;
43 };
44 }
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 7b7de6035af7..449c0fbbe1d6 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -26,6 +26,8 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/input/ti_am335x_tsc.h> 27#include <linux/input/ti_am335x_tsc.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/of.h>
30#include <linux/of_device.h>
29 31
30#include <linux/mfd/ti_am335x_tscadc.h> 32#include <linux/mfd/ti_am335x_tscadc.h>
31 33
@@ -47,7 +49,7 @@ struct titsc {
47 unsigned int wires; 49 unsigned int wires;
48 unsigned int x_plate_resistance; 50 unsigned int x_plate_resistance;
49 bool pen_down; 51 bool pen_down;
50 int steps_to_configure; 52 int coordinate_readouts;
51 u32 config_inp[4]; 53 u32 config_inp[4];
52 u32 bit_xp, bit_xn, bit_yp, bit_yn; 54 u32 bit_xp, bit_xn, bit_yp, bit_yn;
53 u32 inp_xp, inp_xn, inp_yp, inp_yn; 55 u32 inp_xp, inp_xn, inp_yp, inp_yn;
@@ -123,7 +125,7 @@ static void titsc_step_config(struct titsc *ts_dev)
123 int i, total_steps; 125 int i, total_steps;
124 126
125 /* Configure the Step registers */ 127 /* Configure the Step registers */
126 total_steps = 2 * ts_dev->steps_to_configure; 128 total_steps = 2 * ts_dev->coordinate_readouts;
127 129
128 config = STEPCONFIG_MODE_HWSYNC | 130 config = STEPCONFIG_MODE_HWSYNC |
129 STEPCONFIG_AVG_16 | ts_dev->bit_xp; 131 STEPCONFIG_AVG_16 | ts_dev->bit_xp;
@@ -141,7 +143,7 @@ static void titsc_step_config(struct titsc *ts_dev)
141 break; 143 break;
142 } 144 }
143 145
144 for (i = 1; i <= ts_dev->steps_to_configure; i++) { 146 for (i = 1; i <= ts_dev->coordinate_readouts; i++) {
145 titsc_writel(ts_dev, REG_STEPCONFIG(i), config); 147 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
146 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); 148 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
147 } 149 }
@@ -163,7 +165,7 @@ static void titsc_step_config(struct titsc *ts_dev)
163 break; 165 break;
164 } 166 }
165 167
166 for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { 168 for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) {
167 titsc_writel(ts_dev, REG_STEPCONFIG(i), config); 169 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
168 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); 170 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
169 } 171 }
@@ -218,7 +220,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
218 read = titsc_readl(ts_dev, REG_FIFO0); 220 read = titsc_readl(ts_dev, REG_FIFO0);
219 channel = read & 0xf0000; 221 channel = read & 0xf0000;
220 channel = channel >> 0x10; 222 channel = channel >> 0x10;
221 if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { 223 if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) {
222 read &= 0xfff; 224 read &= 0xfff;
223 diff = abs(read - prev_val_x); 225 diff = abs(read - prev_val_x);
224 if (diff < prev_diff_x) { 226 if (diff < prev_diff_x) {
@@ -231,8 +233,8 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
231 read = titsc_readl(ts_dev, REG_FIFO1); 233 read = titsc_readl(ts_dev, REG_FIFO1);
232 channel = read & 0xf0000; 234 channel = read & 0xf0000;
233 channel = channel >> 0x10; 235 channel = channel >> 0x10;
234 if ((channel >= ts_dev->steps_to_configure) && 236 if ((channel >= ts_dev->coordinate_readouts) &&
235 (channel < (2 * ts_dev->steps_to_configure - 1))) { 237 (channel < (2 * ts_dev->coordinate_readouts - 1))) {
236 read &= 0xfff; 238 read &= 0xfff;
237 diff = abs(read - prev_val_y); 239 diff = abs(read - prev_val_y);
238 if (diff < prev_diff_y) { 240 if (diff < prev_diff_y) {
@@ -310,6 +312,59 @@ static irqreturn_t titsc_irq(int irq, void *dev)
310 return IRQ_HANDLED; 312 return IRQ_HANDLED;
311} 313}
312 314
315static int titsc_parse_dt(struct platform_device *pdev,
316 struct titsc *ts_dev)
317{
318 struct device_node *node = pdev->dev.of_node;
319 int err;
320
321 if (!node)
322 return -EINVAL;
323
324 err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
325 if (err < 0)
326 return err;
327 switch (ts_dev->wires) {
328 case 4:
329 case 5:
330 case 8:
331 break;
332 default:
333 return -EINVAL;
334 }
335
336 err = of_property_read_u32(node, "ti,x-plate-resistance",
337 &ts_dev->x_plate_resistance);
338 if (err < 0)
339 return err;
340
341 err = of_property_read_u32(node, "ti,coordiante-readouts",
342 &ts_dev->coordinate_readouts);
343 if (err < 0)
344 return err;
345
346 return of_property_read_u32_array(node, "ti,wire-config",
347 ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
348}
349
350static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev,
351 struct titsc *ts_dev)
352{
353 struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data;
354
355 if (!pdata)
356 return -EINVAL;
357
358 ts_dev->wires = pdata->tsc_init->wires;
359 ts_dev->x_plate_resistance =
360 pdata->tsc_init->x_plate_resistance;
361 ts_dev->steps_to_configure =
362 pdata->tsc_init->steps_to_configure;
363 memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
364 sizeof(pdata->tsc_init->wire_config));
365 return 0;
366}
367
313/* 368/*
314 * The functions for inserting/removing driver as a module. 369 * The functions for inserting/removing driver as a module.
315 */ 370 */
@@ -319,16 +374,8 @@ static int titsc_probe(struct platform_device *pdev)
319 struct titsc *ts_dev; 374 struct titsc *ts_dev;
320 struct input_dev *input_dev; 375 struct input_dev *input_dev;
321 struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); 376 struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
322 struct mfd_tscadc_board *pdata;
323 int err; 377 int err;
324 378
325 pdata = tscadc_dev->dev->platform_data;
326
327 if (!pdata) {
328 dev_err(&pdev->dev, "Could not find platform data\n");
329 return -EINVAL;
330 }
331
332 /* Allocate memory for device */ 379 /* Allocate memory for device */
333 ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); 380 ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
334 input_dev = input_allocate_device(); 381 input_dev = input_allocate_device();
@@ -342,11 +389,16 @@ static int titsc_probe(struct platform_device *pdev)
342 ts_dev->mfd_tscadc = tscadc_dev; 389 ts_dev->mfd_tscadc = tscadc_dev;
343 ts_dev->input = input_dev; 390 ts_dev->input = input_dev;
344 ts_dev->irq = tscadc_dev->irq; 391 ts_dev->irq = tscadc_dev->irq;
345 ts_dev->wires = pdata->tsc_init->wires; 392
346 ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; 393 if (tscadc_dev->dev->platform_data)
347 ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; 394 err = titsc_parse_pdata(tscadc_dev, ts_dev);
348 memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, 395 else
349 sizeof(pdata->tsc_init->wire_config)); 396 err = titsc_parse_dt(pdev, ts_dev);
397
398 if (err) {
399 dev_err(&pdev->dev, "Could not find valid DT data.\n");
400 goto err_free_mem;
401 }
350 402
351 err = request_irq(ts_dev->irq, titsc_irq, 403 err = request_irq(ts_dev->irq, titsc_irq,
352 0, pdev->dev.driver->name, ts_dev); 404 0, pdev->dev.driver->name, ts_dev);
@@ -362,7 +414,7 @@ static int titsc_probe(struct platform_device *pdev)
362 goto err_free_irq; 414 goto err_free_irq;
363 } 415 }
364 titsc_step_config(ts_dev); 416 titsc_step_config(ts_dev);
365 titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); 417 titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts);
366 418
367 input_dev->name = "ti-tsc"; 419 input_dev->name = "ti-tsc";
368 input_dev->dev.parent = &pdev->dev; 420 input_dev->dev.parent = &pdev->dev;
@@ -398,7 +450,7 @@ static int titsc_remove(struct platform_device *pdev)
398 free_irq(ts_dev->irq, ts_dev); 450 free_irq(ts_dev->irq, ts_dev);
399 451
400 /* total steps followed by the enable mask */ 452 /* total steps followed by the enable mask */
401 steps = 2 * ts_dev->steps_to_configure + 2; 453 steps = 2 * ts_dev->coordinate_readouts + 2;
402 steps = (1 << steps) - 1; 454 steps = (1 << steps) - 1;
403 am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); 455 am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
404 456
@@ -439,7 +491,7 @@ static int titsc_resume(struct device *dev)
439 } 491 }
440 titsc_step_config(ts_dev); 492 titsc_step_config(ts_dev);
441 titsc_writel(ts_dev, REG_FIFO0THR, 493 titsc_writel(ts_dev, REG_FIFO0THR,
442 ts_dev->steps_to_configure); 494 ts_dev->coordinate_readouts);
443 return 0; 495 return 0;
444} 496}
445 497
@@ -452,6 +504,12 @@ static const struct dev_pm_ops titsc_pm_ops = {
452#define TITSC_PM_OPS NULL 504#define TITSC_PM_OPS NULL
453#endif 505#endif
454 506
507static const struct of_device_id ti_tsc_dt_ids[] = {
508 { .compatible = "ti,am3359-tsc", },
509 { }
510};
511MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
512
455static struct platform_driver ti_tsc_driver = { 513static struct platform_driver ti_tsc_driver = {
456 .probe = titsc_probe, 514 .probe = titsc_probe,
457 .remove = titsc_remove, 515 .remove = titsc_remove,
@@ -459,6 +517,7 @@ static struct platform_driver ti_tsc_driver = {
459 .name = "tsc", 517 .name = "tsc",
460 .owner = THIS_MODULE, 518 .owner = THIS_MODULE,
461 .pm = TITSC_PM_OPS, 519 .pm = TITSC_PM_OPS,
520 .of_match_table = of_match_ptr(ti_tsc_dt_ids),
462 }, 521 },
463}; 522};
464module_platform_driver(ti_tsc_driver); 523module_platform_driver(ti_tsc_driver);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 90ccfc07e16b..f50976623a01 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -203,6 +203,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
203 /* TSC Cell */ 203 /* TSC Cell */
204 cell = &tscadc->cells[TSC_CELL]; 204 cell = &tscadc->cells[TSC_CELL];
205 cell->name = "tsc"; 205 cell->name = "tsc";
206 cell->of_compatible = "ti,am3359-tsc";
206 cell->platform_data = &tscadc; 207 cell->platform_data = &tscadc;
207 cell->pdata_size = sizeof(tscadc); 208 cell->pdata_size = sizeof(tscadc);
208 209