diff options
-rw-r--r-- | Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt | 41 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-cpuimx35.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-cpuimx51sd.c | 2 | ||||
-rw-r--r-- | arch/sh/boards/mach-ecovec24/setup.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007.c | 173 | ||||
-rw-r--r-- | include/linux/i2c/tsc2007.h | 6 |
6 files changed, 180 insertions, 46 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt new file mode 100644 index 000000000000..ec365e172236 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt | |||
@@ -0,0 +1,41 @@ | |||
1 | * Texas Instruments tsc2007 touchscreen controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be "ti,tsc2007". | ||
5 | - reg: I2C address of the chip. | ||
6 | - ti,x-plate-ohms: X-plate resistance in ohms. | ||
7 | |||
8 | Optional properties: | ||
9 | - gpios: the interrupt gpio the chip is connected to (trough the penirq pin). | ||
10 | The penirq pin goes to low when the panel is touched. | ||
11 | (see GPIO binding[1] for more details). | ||
12 | - interrupt-parent: the phandle for the gpio controller | ||
13 | (see interrupt binding[0]). | ||
14 | - interrupts: (gpio) interrupt to which the chip is connected | ||
15 | (see interrupt binding[0]). | ||
16 | - ti,max-rt: maximum pressure. | ||
17 | - ti,fuzzx: specifies the absolute input fuzz x value. | ||
18 | If set, it will permit noise in the data up to +- the value given to the fuzz | ||
19 | parameter, that is used to filter noise from the event stream. | ||
20 | - ti,fuzzy: specifies the absolute input fuzz y value. | ||
21 | - ti,fuzzz: specifies the absolute input fuzz z value. | ||
22 | - ti,poll-period: how much time to wait (in milliseconds) before reading again the | ||
23 | values from the tsc2007. | ||
24 | |||
25 | [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | ||
26 | [1]: Documentation/devicetree/bindings/gpio/gpio.txt | ||
27 | |||
28 | Example: | ||
29 | &i2c1 { | ||
30 | /* ... */ | ||
31 | tsc2007@49 { | ||
32 | compatible = "ti,tsc2007"; | ||
33 | reg = <0x49>; | ||
34 | interrupt-parent = <&gpio4>; | ||
35 | interrupts = <0x0 0x8>; | ||
36 | gpios = <&gpio4 0 0>; | ||
37 | ti,x-plate-ohms = <180>; | ||
38 | }; | ||
39 | |||
40 | /* ... */ | ||
41 | }; | ||
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 771362d1fbee..65e4c53e1554 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c | |||
@@ -53,7 +53,7 @@ static const struct imxi2c_platform_data | |||
53 | }; | 53 | }; |
54 | 54 | ||
55 | #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) | 55 | #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) |
56 | static int tsc2007_get_pendown_state(void) | 56 | static int tsc2007_get_pendown_state(struct device *dev) |
57 | { | 57 | { |
58 | return !gpio_get_value(TSC2007_IRQGPIO); | 58 | return !gpio_get_value(TSC2007_IRQGPIO); |
59 | } | 59 | } |
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index 9b5ddf5bbd33..1fba2b8e983f 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c | |||
@@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = { | |||
121 | .flags = IMXUART_HAVE_RTSCTS, | 121 | .flags = IMXUART_HAVE_RTSCTS, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | static int tsc2007_get_pendown_state(void) | 124 | static int tsc2007_get_pendown_state(struct device *dev) |
125 | { | 125 | { |
126 | if (mx51_revision() < IMX_CHIP_REVISION_3_0) | 126 | if (mx51_revision() < IMX_CHIP_REVISION_3_0) |
127 | return !gpio_get_value(TSC2007_IRQGPIO_REV2); | 127 | return !gpio_get_value(TSC2007_IRQGPIO_REV2); |
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 1fa8be409771..23d7e45f9d14 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -501,7 +501,7 @@ static struct platform_device keysc_device = { | |||
501 | /* TouchScreen */ | 501 | /* TouchScreen */ |
502 | #define IRQ0 evt2irq(0x600) | 502 | #define IRQ0 evt2irq(0x600) |
503 | 503 | ||
504 | static int ts_get_pendown_state(void) | 504 | static int ts_get_pendown_state(struct device *dev) |
505 | { | 505 | { |
506 | int val = 0; | 506 | int val = 0; |
507 | gpio_free(GPIO_FN_INTC_IRQ0); | 507 | gpio_free(GPIO_FN_INTC_IRQ0); |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 0b67ba476b4c..88b150a0b8ee 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -26,6 +26,9 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/i2c/tsc2007.h> | 28 | #include <linux/i2c/tsc2007.h> |
29 | #include <linux/of_device.h> | ||
30 | #include <linux/of.h> | ||
31 | #include <linux/of_gpio.h> | ||
29 | 32 | ||
30 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) | 33 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) |
31 | #define TSC2007_MEASURE_AUX (0x2 << 4) | 34 | #define TSC2007_MEASURE_AUX (0x2 << 4) |
@@ -74,13 +77,17 @@ struct tsc2007 { | |||
74 | u16 max_rt; | 77 | u16 max_rt; |
75 | unsigned long poll_delay; | 78 | unsigned long poll_delay; |
76 | unsigned long poll_period; | 79 | unsigned long poll_period; |
80 | int fuzzx; | ||
81 | int fuzzy; | ||
82 | int fuzzz; | ||
77 | 83 | ||
84 | unsigned gpio; | ||
78 | int irq; | 85 | int irq; |
79 | 86 | ||
80 | wait_queue_head_t wait; | 87 | wait_queue_head_t wait; |
81 | bool stopped; | 88 | bool stopped; |
82 | 89 | ||
83 | int (*get_pendown_state)(void); | 90 | int (*get_pendown_state)(struct device *); |
84 | void (*clear_penirq)(void); | 91 | void (*clear_penirq)(void); |
85 | }; | 92 | }; |
86 | 93 | ||
@@ -161,7 +168,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) | |||
161 | if (!ts->get_pendown_state) | 168 | if (!ts->get_pendown_state) |
162 | return true; | 169 | return true; |
163 | 170 | ||
164 | return ts->get_pendown_state(); | 171 | return ts->get_pendown_state(&ts->client->dev); |
165 | } | 172 | } |
166 | 173 | ||
167 | static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | 174 | static irqreturn_t tsc2007_soft_irq(int irq, void *handle) |
@@ -178,7 +185,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | |||
178 | 185 | ||
179 | rt = tsc2007_calculate_pressure(ts, &tc); | 186 | rt = tsc2007_calculate_pressure(ts, &tc); |
180 | 187 | ||
181 | if (rt == 0 && !ts->get_pendown_state) { | 188 | if (!rt && !ts->get_pendown_state) { |
182 | /* | 189 | /* |
183 | * If pressure reported is 0 and we don't have | 190 | * If pressure reported is 0 and we don't have |
184 | * callback to check pendown state, we have to | 191 | * callback to check pendown state, we have to |
@@ -228,7 +235,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) | |||
228 | { | 235 | { |
229 | struct tsc2007 *ts = handle; | 236 | struct tsc2007 *ts = handle; |
230 | 237 | ||
231 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) | 238 | if (tsc2007_is_pen_down(ts)) |
232 | return IRQ_WAKE_THREAD; | 239 | return IRQ_WAKE_THREAD; |
233 | 240 | ||
234 | if (ts->clear_penirq) | 241 | if (ts->clear_penirq) |
@@ -273,35 +280,74 @@ static void tsc2007_close(struct input_dev *input_dev) | |||
273 | tsc2007_stop(ts); | 280 | tsc2007_stop(ts); |
274 | } | 281 | } |
275 | 282 | ||
276 | static int tsc2007_probe(struct i2c_client *client, | 283 | #ifdef CONFIG_OF |
277 | const struct i2c_device_id *id) | 284 | static int tsc2007_get_pendown_state_gpio(struct device *dev) |
278 | { | 285 | { |
279 | struct tsc2007 *ts; | 286 | struct i2c_client *client = to_i2c_client(dev); |
280 | struct tsc2007_platform_data *pdata = client->dev.platform_data; | 287 | struct tsc2007 *ts = i2c_get_clientdata(client); |
281 | struct input_dev *input_dev; | 288 | |
282 | int err; | 289 | return !gpio_get_value(ts->gpio); |
290 | } | ||
291 | |||
292 | static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) | ||
293 | { | ||
294 | struct device_node *np = client->dev.of_node; | ||
295 | u32 val32; | ||
296 | u64 val64; | ||
283 | 297 | ||
284 | if (!pdata) { | 298 | if (!np) { |
285 | dev_err(&client->dev, "platform data is required!\n"); | 299 | dev_err(&client->dev, "missing device tree data\n"); |
286 | return -EINVAL; | 300 | return -EINVAL; |
287 | } | 301 | } |
288 | 302 | ||
289 | if (!i2c_check_functionality(client->adapter, | 303 | if (!of_property_read_u32(np, "ti,max-rt", &val32)) |
290 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | 304 | ts->max_rt = val32; |
291 | return -EIO; | 305 | else |
306 | ts->max_rt = MAX_12BIT; | ||
292 | 307 | ||
293 | ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); | 308 | if (!of_property_read_u32(np, "ti,fuzzx", &val32)) |
294 | input_dev = input_allocate_device(); | 309 | ts->fuzzx = val32; |
295 | if (!ts || !input_dev) { | 310 | |
296 | err = -ENOMEM; | 311 | if (!of_property_read_u32(np, "ti,fuzzy", &val32)) |
297 | goto err_free_mem; | 312 | ts->fuzzy = val32; |
313 | |||
314 | if (!of_property_read_u32(np, "ti,fuzzz", &val32)) | ||
315 | ts->fuzzz = val32; | ||
316 | |||
317 | if (!of_property_read_u64(np, "ti,poll-period", &val64)) | ||
318 | ts->poll_period = val64; | ||
319 | else | ||
320 | ts->poll_period = 1; | ||
321 | |||
322 | if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { | ||
323 | ts->x_plate_ohms = val32; | ||
324 | } else { | ||
325 | dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); | ||
326 | return -EINVAL; | ||
298 | } | 327 | } |
299 | 328 | ||
300 | ts->client = client; | 329 | ts->gpio = of_get_gpio(np, 0); |
301 | ts->irq = client->irq; | 330 | if (gpio_is_valid(ts->gpio)) |
302 | ts->input = input_dev; | 331 | ts->get_pendown_state = tsc2007_get_pendown_state_gpio; |
303 | init_waitqueue_head(&ts->wait); | 332 | else |
333 | dev_warn(&client->dev, | ||
334 | "GPIO not specified in DT (of_get_gpio returned %d)\n", | ||
335 | ts->gpio); | ||
304 | 336 | ||
337 | return 0; | ||
338 | } | ||
339 | #else | ||
340 | static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) | ||
341 | { | ||
342 | dev_err(&client->dev, "platform data is required!\n"); | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | #endif | ||
346 | |||
347 | static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, | ||
348 | const struct tsc2007_platform_data *pdata, | ||
349 | const struct i2c_device_id *id) | ||
350 | { | ||
305 | ts->model = pdata->model; | 351 | ts->model = pdata->model; |
306 | ts->x_plate_ohms = pdata->x_plate_ohms; | 352 | ts->x_plate_ohms = pdata->x_plate_ohms; |
307 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; | 353 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; |
@@ -309,13 +355,54 @@ static int tsc2007_probe(struct i2c_client *client, | |||
309 | ts->poll_period = pdata->poll_period ? : 1; | 355 | ts->poll_period = pdata->poll_period ? : 1; |
310 | ts->get_pendown_state = pdata->get_pendown_state; | 356 | ts->get_pendown_state = pdata->get_pendown_state; |
311 | ts->clear_penirq = pdata->clear_penirq; | 357 | ts->clear_penirq = pdata->clear_penirq; |
358 | ts->fuzzx = pdata->fuzzx; | ||
359 | ts->fuzzy = pdata->fuzzy; | ||
360 | ts->fuzzz = pdata->fuzzz; | ||
312 | 361 | ||
313 | if (pdata->x_plate_ohms == 0) { | 362 | if (pdata->x_plate_ohms == 0) { |
314 | dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); | 363 | dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); |
315 | err = -EINVAL; | 364 | return -EINVAL; |
316 | goto err_free_mem; | ||
317 | } | 365 | } |
318 | 366 | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int tsc2007_probe(struct i2c_client *client, | ||
371 | const struct i2c_device_id *id) | ||
372 | { | ||
373 | const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); | ||
374 | struct tsc2007 *ts; | ||
375 | struct input_dev *input_dev; | ||
376 | int err; | ||
377 | |||
378 | if (!i2c_check_functionality(client->adapter, | ||
379 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | ||
380 | return -EIO; | ||
381 | |||
382 | ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); | ||
383 | if (!ts) | ||
384 | return -ENOMEM; | ||
385 | |||
386 | if (pdata) | ||
387 | err = tsc2007_probe_pdev(client, ts, pdata, id); | ||
388 | else | ||
389 | err = tsc2007_probe_dt(client, ts); | ||
390 | if (err) | ||
391 | return err; | ||
392 | |||
393 | input_dev = input_allocate_device(); | ||
394 | if (!input_dev) { | ||
395 | err = -ENOMEM; | ||
396 | goto err_free_input; | ||
397 | }; | ||
398 | |||
399 | i2c_set_clientdata(client, ts); | ||
400 | |||
401 | ts->client = client; | ||
402 | ts->irq = client->irq; | ||
403 | ts->input = input_dev; | ||
404 | init_waitqueue_head(&ts->wait); | ||
405 | |||
319 | snprintf(ts->phys, sizeof(ts->phys), | 406 | snprintf(ts->phys, sizeof(ts->phys), |
320 | "%s/input0", dev_name(&client->dev)); | 407 | "%s/input0", dev_name(&client->dev)); |
321 | 408 | ||
@@ -331,19 +418,19 @@ static int tsc2007_probe(struct i2c_client *client, | |||
331 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 418 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
332 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 419 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
333 | 420 | ||
334 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); | 421 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); |
335 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); | 422 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); |
336 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, | 423 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, |
337 | pdata->fuzzz, 0); | 424 | ts->fuzzz, 0); |
338 | 425 | ||
339 | if (pdata->init_platform_hw) | 426 | if (pdata && pdata->init_platform_hw) |
340 | pdata->init_platform_hw(); | 427 | pdata->init_platform_hw(); |
341 | 428 | ||
342 | err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, | 429 | err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, |
343 | IRQF_ONESHOT, client->dev.driver->name, ts); | 430 | IRQF_ONESHOT, client->dev.driver->name, ts); |
344 | if (err < 0) { | 431 | if (err < 0) { |
345 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); | 432 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); |
346 | goto err_free_mem; | 433 | goto err_free_input; |
347 | } | 434 | } |
348 | 435 | ||
349 | tsc2007_stop(ts); | 436 | tsc2007_stop(ts); |
@@ -352,28 +439,25 @@ static int tsc2007_probe(struct i2c_client *client, | |||
352 | if (err) | 439 | if (err) |
353 | goto err_free_irq; | 440 | goto err_free_irq; |
354 | 441 | ||
355 | i2c_set_clientdata(client, ts); | ||
356 | |||
357 | return 0; | 442 | return 0; |
358 | 443 | ||
359 | err_free_irq: | 444 | err_free_irq: |
360 | free_irq(ts->irq, ts); | 445 | free_irq(ts->irq, ts); |
361 | if (pdata->exit_platform_hw) | 446 | if (pdata && pdata->exit_platform_hw) |
362 | pdata->exit_platform_hw(); | 447 | pdata->exit_platform_hw(); |
363 | err_free_mem: | 448 | err_free_input: |
364 | input_free_device(input_dev); | 449 | input_free_device(input_dev); |
365 | kfree(ts); | ||
366 | return err; | 450 | return err; |
367 | } | 451 | } |
368 | 452 | ||
369 | static int tsc2007_remove(struct i2c_client *client) | 453 | static int tsc2007_remove(struct i2c_client *client) |
370 | { | 454 | { |
371 | struct tsc2007 *ts = i2c_get_clientdata(client); | 455 | const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); |
372 | struct tsc2007_platform_data *pdata = client->dev.platform_data; | 456 | struct tsc2007 *ts = i2c_get_clientdata(client); |
373 | 457 | ||
374 | free_irq(ts->irq, ts); | 458 | free_irq(ts->irq, ts); |
375 | 459 | ||
376 | if (pdata->exit_platform_hw) | 460 | if (pdata && pdata->exit_platform_hw) |
377 | pdata->exit_platform_hw(); | 461 | pdata->exit_platform_hw(); |
378 | 462 | ||
379 | input_unregister_device(ts->input); | 463 | input_unregister_device(ts->input); |
@@ -389,10 +473,19 @@ static const struct i2c_device_id tsc2007_idtable[] = { | |||
389 | 473 | ||
390 | MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); | 474 | MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); |
391 | 475 | ||
476 | #ifdef CONFIG_OF | ||
477 | static const struct of_device_id tsc2007_of_match[] = { | ||
478 | { .compatible = "ti,tsc2007" }, | ||
479 | { /* sentinel */ } | ||
480 | }; | ||
481 | MODULE_DEVICE_TABLE(of, tsc2007_of_match); | ||
482 | #endif | ||
483 | |||
392 | static struct i2c_driver tsc2007_driver = { | 484 | static struct i2c_driver tsc2007_driver = { |
393 | .driver = { | 485 | .driver = { |
394 | .owner = THIS_MODULE, | 486 | .owner = THIS_MODULE, |
395 | .name = "tsc2007" | 487 | .name = "tsc2007", |
488 | .of_match_table = of_match_ptr(tsc2007_of_match), | ||
396 | }, | 489 | }, |
397 | .id_table = tsc2007_idtable, | 490 | .id_table = tsc2007_idtable, |
398 | .probe = tsc2007_probe, | 491 | .probe = tsc2007_probe, |
diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h index 506a9f7af51e..041c8e823664 100644 --- a/include/linux/i2c/tsc2007.h +++ b/include/linux/i2c/tsc2007.h | |||
@@ -14,9 +14,9 @@ struct tsc2007_platform_data { | |||
14 | int fuzzy; | 14 | int fuzzy; |
15 | int fuzzz; | 15 | int fuzzz; |
16 | 16 | ||
17 | int (*get_pendown_state)(void); | 17 | int (*get_pendown_state)(struct device *); |
18 | void (*clear_penirq)(void); /* If needed, clear 2nd level | 18 | /* If needed, clear 2nd level interrupt source */ |
19 | interrupt source */ | 19 | void (*clear_penirq)(void); |
20 | int (*init_platform_hw)(void); | 20 | int (*init_platform_hw)(void); |
21 | void (*exit_platform_hw)(void); | 21 | void (*exit_platform_hw)(void); |
22 | }; | 22 | }; |