Skip to content

Commit fa6e3ca

Browse files
agnersdtor
authored andcommitted
Input: ad7879 - add device tree support
Add device tree support for the I2C and SPI variant of AD7879(-1). This allows to specify the touchscreen controller as a I2C client node or SPI slave device. Most of the options available in platform data are also available as device tree properties, the only exception being GPIO capabilities, which can not be activated through device tree currently. Signed-off-by: Stefan Agner <[email protected]> Acked-by: Rob Herring <[email protected]> Acked-by: Michael Hennerich <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 5f2940c commit fa6e3ca

File tree

4 files changed

+163
-58
lines changed

4 files changed

+163
-58
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
* Analog Devices AD7879(-1)/AD7889(-1) touchscreen interface (SPI/I2C)
2+
3+
Required properties:
4+
- compatible : for SPI slave, use "adi,ad7879"
5+
for I2C slave, use "adi,ad7879-1"
6+
- reg : SPI chipselect/I2C slave address
7+
See spi-bus.txt for more SPI slave properties
8+
- interrupt-parent : the phandle for the interrupt controller
9+
- interrupts : touch controller interrupt
10+
- touchscreen-max-pressure : maximum reported pressure
11+
- adi,resistance-plate-x : total resistance of X-plate (for pressure
12+
calculation)
13+
Optional properties:
14+
- touchscreen-swapped-x-y : X and Y axis are swapped (boolean)
15+
- adi,first-conversion-delay : 0-12: In 128us steps (starting with 128us)
16+
13 : 2.560ms
17+
14 : 3.584ms
18+
15 : 4.096ms
19+
This property has to be a '/bits/ 8' value
20+
- adi,acquisition-time : 0: 2us
21+
1: 4us
22+
2: 8us
23+
3: 16us
24+
This property has to be a '/bits/ 8' value
25+
- adi,median-filter-size : 0: disabled
26+
1: 4 measurements
27+
2: 8 measurements
28+
3: 16 measurements
29+
This property has to be a '/bits/ 8' value
30+
- adi,averaging : 0: 2 middle values (1 if median disabled)
31+
1: 4 middle values
32+
2: 8 middle values
33+
3: 16 values
34+
This property has to be a '/bits/ 8' value
35+
- adi,conversion-interval: : 0 : convert one time only
36+
1-255: 515us + val * 35us (up to 9.440ms)
37+
This property has to be a '/bits/ 8' value
38+
39+
Example:
40+
41+
ad7879@2c {
42+
compatible = "adi,ad7879-1";
43+
reg = <0x2c>;
44+
interrupt-parent = <&gpio1>;
45+
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
46+
touchscreen-max-pressure = <4096>;
47+
adi,resistance-plate-x = <120>;
48+
adi,first-conversion-delay = /bits/ 8 <3>;
49+
adi,acquisition-time = /bits/ 8 <1>;
50+
adi,median-filter-size = /bits/ 8 <2>;
51+
adi,averaging = /bits/ 8 <1>;
52+
adi,conversion-interval = /bits/ 8 <255>;
53+
};

drivers/input/touchscreen/ad7879-i2c.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/i2c.h>
1111
#include <linux/module.h>
1212
#include <linux/types.h>
13+
#include <linux/of.h>
1314
#include <linux/pm.h>
1415

1516
#include "ad7879.h"
@@ -91,10 +92,19 @@ static const struct i2c_device_id ad7879_id[] = {
9192
};
9293
MODULE_DEVICE_TABLE(i2c, ad7879_id);
9394

95+
#ifdef CONFIG_OF
96+
static const struct of_device_id ad7879_i2c_dt_ids[] = {
97+
{ .compatible = "adi,ad7879-1", },
98+
{ }
99+
};
100+
MODULE_DEVICE_TABLE(of, ad7879_i2c_dt_ids);
101+
#endif
102+
94103
static struct i2c_driver ad7879_i2c_driver = {
95104
.driver = {
96105
.name = "ad7879",
97106
.pm = &ad7879_pm_ops,
107+
.of_match_table = of_match_ptr(ad7879_i2c_dt_ids),
98108
},
99109
.probe = ad7879_i2c_probe,
100110
.remove = ad7879_i2c_remove,

drivers/input/touchscreen/ad7879-spi.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/pm.h>
1111
#include <linux/spi/spi.h>
1212
#include <linux/module.h>
13+
#include <linux/of.h>
1314

1415
#include "ad7879.h"
1516

@@ -146,10 +147,19 @@ static int ad7879_spi_remove(struct spi_device *spi)
146147
return 0;
147148
}
148149

150+
#ifdef CONFIG_OF
151+
static const struct of_device_id ad7879_spi_dt_ids[] = {
152+
{ .compatible = "adi,ad7879", },
153+
{ }
154+
};
155+
MODULE_DEVICE_TABLE(of, ad7879_spi_dt_ids);
156+
#endif
157+
149158
static struct spi_driver ad7879_spi_driver = {
150159
.driver = {
151160
.name = "ad7879",
152161
.pm = &ad7879_pm_ops,
162+
.of_match_table = of_match_ptr(ad7879_spi_dt_ids),
153163
},
154164
.probe = ad7879_spi_probe,
155165
.remove = ad7879_spi_remove,

drivers/input/touchscreen/ad7879.c

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/i2c.h>
3232
#include <linux/gpio.h>
3333

34+
#include <linux/input/touchscreen.h>
3435
#include <linux/platform_data/ad7879.h>
3536
#include <linux/module.h>
3637
#include "ad7879.h"
@@ -126,7 +127,6 @@ struct ad7879 {
126127
u8 pen_down_acc_interval;
127128
u8 median;
128129
u16 x_plate_ohms;
129-
u16 pressure_max;
130130
u16 cmd_crtl1;
131131
u16 cmd_crtl2;
132132
u16 cmd_crtl3;
@@ -186,7 +186,7 @@ static int ad7879_report(struct ad7879 *ts)
186186
* Sample found inconsistent, pressure is beyond
187187
* the maximum. Don't report it to user space.
188188
*/
189-
if (Rt > ts->pressure_max)
189+
if (Rt > input_abs_get_max(input_dev, ABS_PRESSURE))
190190
return -EINVAL;
191191

192192
/*
@@ -469,7 +469,7 @@ static void ad7879_gpio_remove(struct ad7879 *ts)
469469
{
470470
const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev);
471471

472-
if (pdata->gpio_export)
472+
if (pdata && pdata->gpio_export)
473473
gpiochip_remove(&ts->gc);
474474

475475
}
@@ -485,6 +485,32 @@ static inline void ad7879_gpio_remove(struct ad7879 *ts)
485485
}
486486
#endif
487487

488+
static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts)
489+
{
490+
int err;
491+
u32 tmp;
492+
493+
err = device_property_read_u32(dev, "adi,resistance-plate-x", &tmp);
494+
if (err) {
495+
dev_err(dev, "failed to get resistance-plate-x property\n");
496+
return err;
497+
}
498+
ts->x_plate_ohms = (u16)tmp;
499+
500+
device_property_read_u8(dev, "adi,first-conversion-delay",
501+
&ts->first_conversion_delay);
502+
device_property_read_u8(dev, "adi,acquisition-time",
503+
&ts->acquisition_time);
504+
device_property_read_u8(dev, "adi,median-filter-size", &ts->median);
505+
device_property_read_u8(dev, "adi,averaging", &ts->averaging);
506+
device_property_read_u8(dev, "adi,conversion-interval",
507+
&ts->pen_down_acc_interval);
508+
509+
ts->swap_xy = device_property_read_bool(dev, "touchscreen-swapped-x-y");
510+
511+
return 0;
512+
}
513+
488514
struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
489515
const struct ad7879_bus_ops *bops)
490516
{
@@ -495,43 +521,44 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
495521
u16 revid;
496522

497523
if (!irq) {
498-
dev_err(dev, "no IRQ?\n");
499-
err = -EINVAL;
500-
goto err_out;
524+
dev_err(dev, "No IRQ specified\n");
525+
return ERR_PTR(-EINVAL);
501526
}
502527

503-
if (!pdata) {
504-
dev_err(dev, "no platform data?\n");
505-
err = -EINVAL;
506-
goto err_out;
528+
ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
529+
if (!ts)
530+
return ERR_PTR(-ENOMEM);
531+
532+
if (pdata) {
533+
/* Platform data use swapped axis (backward compatibility) */
534+
ts->swap_xy = !pdata->swap_xy;
535+
536+
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
537+
538+
ts->first_conversion_delay = pdata->first_conversion_delay;
539+
ts->acquisition_time = pdata->acquisition_time;
540+
ts->averaging = pdata->averaging;
541+
ts->pen_down_acc_interval = pdata->pen_down_acc_interval;
542+
ts->median = pdata->median;
543+
} else if (dev->of_node) {
544+
ad7879_parse_dt(dev, ts);
545+
} else {
546+
dev_err(dev, "No platform data\n");
547+
return ERR_PTR(-EINVAL);
507548
}
508549

509-
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
510-
input_dev = input_allocate_device();
511-
if (!ts || !input_dev) {
512-
err = -ENOMEM;
513-
goto err_free_mem;
550+
input_dev = devm_input_allocate_device(dev);
551+
if (!input_dev) {
552+
dev_err(dev, "Failed to allocate input device\n");
553+
return ERR_PTR(-ENOMEM);
514554
}
515555

516556
ts->bops = bops;
517557
ts->dev = dev;
518558
ts->input = input_dev;
519559
ts->irq = irq;
520560

521-
/* Use swapped axis by default (backward compatibility) */
522-
ts->swap_xy = !pdata->swap_xy;
523-
524561
setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts);
525-
526-
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
527-
ts->pressure_max = pdata->pressure_max ? : ~0;
528-
529-
ts->first_conversion_delay = pdata->first_conversion_delay;
530-
ts->acquisition_time = pdata->acquisition_time;
531-
ts->averaging = pdata->averaging;
532-
ts->pen_down_acc_interval = pdata->pen_down_acc_interval;
533-
ts->median = pdata->median;
534-
535562
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
536563

537564
input_dev->name = "AD7879 Touchscreen";
@@ -552,21 +579,33 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
552579
__set_bit(EV_KEY, input_dev->evbit);
553580
__set_bit(BTN_TOUCH, input_dev->keybit);
554581

555-
input_set_abs_params(input_dev, ABS_X,
556-
pdata->x_min ? : 0,
557-
pdata->x_max ? : MAX_12BIT,
558-
0, 0);
559-
input_set_abs_params(input_dev, ABS_Y,
560-
pdata->y_min ? : 0,
561-
pdata->y_max ? : MAX_12BIT,
562-
0, 0);
563-
input_set_abs_params(input_dev, ABS_PRESSURE,
564-
pdata->pressure_min, pdata->pressure_max, 0, 0);
582+
if (pdata) {
583+
input_set_abs_params(input_dev, ABS_X,
584+
pdata->x_min ? : 0,
585+
pdata->x_max ? : MAX_12BIT,
586+
0, 0);
587+
input_set_abs_params(input_dev, ABS_Y,
588+
pdata->y_min ? : 0,
589+
pdata->y_max ? : MAX_12BIT,
590+
0, 0);
591+
input_set_abs_params(input_dev, ABS_PRESSURE,
592+
pdata->pressure_min,
593+
pdata->pressure_max ? : ~0,
594+
0, 0);
595+
} else {
596+
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
597+
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
598+
touchscreen_parse_properties(input_dev, false);
599+
if (!input_abs_get_max(input_dev, ABS_PRESSURE)) {
600+
dev_err(dev, "Touchscreen pressure is not specified\n");
601+
return ERR_PTR(-EINVAL);
602+
}
603+
}
565604

566605
err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET);
567606
if (err < 0) {
568607
dev_err(dev, "Failed to write %s\n", input_dev->name);
569-
goto err_free_mem;
608+
return ERR_PTR(err);
570609
}
571610

572611
revid = ad7879_read(ts, AD7879_REG_REVID);
@@ -575,8 +614,7 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
575614
if (input_dev->id.product != devid) {
576615
dev_err(dev, "Failed to probe %s (%x vs %x)\n",
577616
input_dev->name, devid, revid);
578-
err = -ENODEV;
579-
goto err_free_mem;
617+
return ERR_PTR(-ENODEV);
580618
}
581619

582620
ts->cmd_crtl3 = AD7879_YPLUS_BIT |
@@ -596,23 +634,25 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
596634
AD7879_ACQ(ts->acquisition_time) |
597635
AD7879_TMR(ts->pen_down_acc_interval);
598636

599-
err = request_threaded_irq(ts->irq, NULL, ad7879_irq,
600-
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
601-
dev_name(dev), ts);
637+
err = devm_request_threaded_irq(dev, ts->irq, NULL, ad7879_irq,
638+
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
639+
dev_name(dev), ts);
602640
if (err) {
603-
dev_err(dev, "irq %d busy?\n", ts->irq);
604-
goto err_free_mem;
641+
dev_err(dev, "Failed to request IRQ: %d\n", err);
642+
return ERR_PTR(err);
605643
}
606644

607645
__ad7879_disable(ts);
608646

609647
err = sysfs_create_group(&dev->kobj, &ad7879_attr_group);
610648
if (err)
611-
goto err_free_irq;
649+
goto err_out;
612650

613-
err = ad7879_gpio_add(ts, pdata);
614-
if (err)
615-
goto err_remove_attr;
651+
if (pdata) {
652+
err = ad7879_gpio_add(ts, pdata);
653+
if (err)
654+
goto err_remove_attr;
655+
}
616656

617657
err = input_register_device(input_dev);
618658
if (err)
@@ -624,11 +664,6 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
624664
ad7879_gpio_remove(ts);
625665
err_remove_attr:
626666
sysfs_remove_group(&dev->kobj, &ad7879_attr_group);
627-
err_free_irq:
628-
free_irq(ts->irq, ts);
629-
err_free_mem:
630-
input_free_device(input_dev);
631-
kfree(ts);
632667
err_out:
633668
return ERR_PTR(err);
634669
}
@@ -638,9 +673,6 @@ void ad7879_remove(struct ad7879 *ts)
638673
{
639674
ad7879_gpio_remove(ts);
640675
sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);
641-
free_irq(ts->irq, ts);
642-
input_unregister_device(ts->input);
643-
kfree(ts);
644676
}
645677
EXPORT_SYMBOL(ad7879_remove);
646678

0 commit comments

Comments
 (0)