1 /*
2  *  Generic DT helper functions for touchscreen devices
3  *
4  *  Copyright (c) 2014 Sebastian Reichel <sre@kernel.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License version 2 as
8  *  published by the Free Software Foundation.
9  *
10  */
11 
12 #include <linux/of.h>
13 #include <linux/input.h>
14 #include <linux/input/mt.h>
15 #include <linux/input/touchscreen.h>
16 
of_get_optional_u32(struct device_node * np,const char * property)17 static u32 of_get_optional_u32(struct device_node *np,
18 			       const char *property)
19 {
20 	u32 val = 0;
21 
22 	of_property_read_u32(np, property, &val);
23 
24 	return val;
25 }
26 
touchscreen_set_params(struct input_dev * dev,unsigned long axis,int max,int fuzz)27 static void touchscreen_set_params(struct input_dev *dev,
28 				   unsigned long axis,
29 				   int max, int fuzz)
30 {
31 	struct input_absinfo *absinfo;
32 
33 	if (!test_bit(axis, dev->absbit)) {
34 		/*
35 		 * Emit a warning only if the axis is not a multitouch
36 		 * axis, which might not be set by the driver.
37 		 */
38 		if (!input_is_mt_axis(axis))
39 			dev_warn(&dev->dev,
40 				 "DT specifies parameters but the axis is not set up\n");
41 		return;
42 	}
43 
44 	absinfo = &dev->absinfo[axis];
45 	absinfo->maximum = max;
46 	absinfo->fuzz = fuzz;
47 }
48 
49 /**
50  * touchscreen_parse_of_params - parse common touchscreen DT properties
51  * @dev: device that should be parsed
52  *
53  * This function parses common DT properties for touchscreens and setups the
54  * input device accordingly. The function keeps previously setuped default
55  * values if no value is specified via DT.
56  */
touchscreen_parse_of_params(struct input_dev * dev)57 void touchscreen_parse_of_params(struct input_dev *dev)
58 {
59 	struct device_node *np = dev->dev.parent->of_node;
60 	u32 maximum, fuzz;
61 
62 	input_alloc_absinfo(dev);
63 	if (!dev->absinfo)
64 		return;
65 
66 	maximum = of_get_optional_u32(np, "touchscreen-size-x");
67 	fuzz = of_get_optional_u32(np, "touchscreen-fuzz-x");
68 	if (maximum || fuzz) {
69 		touchscreen_set_params(dev, ABS_X, maximum, fuzz);
70 		touchscreen_set_params(dev, ABS_MT_POSITION_X, maximum, fuzz);
71 	}
72 
73 	maximum = of_get_optional_u32(np, "touchscreen-size-y");
74 	fuzz = of_get_optional_u32(np, "touchscreen-fuzz-y");
75 	if (maximum || fuzz) {
76 		touchscreen_set_params(dev, ABS_Y, maximum, fuzz);
77 		touchscreen_set_params(dev, ABS_MT_POSITION_Y, maximum, fuzz);
78 	}
79 
80 	maximum = of_get_optional_u32(np, "touchscreen-max-pressure");
81 	fuzz = of_get_optional_u32(np, "touchscreen-fuzz-pressure");
82 	if (maximum || fuzz) {
83 		touchscreen_set_params(dev, ABS_PRESSURE, maximum, fuzz);
84 		touchscreen_set_params(dev, ABS_MT_PRESSURE, maximum, fuzz);
85 	}
86 }
87 EXPORT_SYMBOL(touchscreen_parse_of_params);
88