diff options
-rw-r--r-- | Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt | 44 | ||||
-rw-r--r-- | drivers/input/touchscreen/ti_am335x_tsc.c | 105 | ||||
-rw-r--r-- | drivers/mfd/ti_am335x_tscadc.c | 1 |
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 | |||
4 | Required 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 | |||
31 | Example: | ||
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 | ||
315 | static 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 | |||
350 | static 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 | ||
507 | static const struct of_device_id ti_tsc_dt_ids[] = { | ||
508 | { .compatible = "ti,am3359-tsc", }, | ||
509 | { } | ||
510 | }; | ||
511 | MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); | ||
512 | |||
455 | static struct platform_driver ti_tsc_driver = { | 513 | static 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 | }; |
464 | module_platform_driver(ti_tsc_driver); | 523 | module_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 | ||