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
17static 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
27static 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 */
57void 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}
87EXPORT_SYMBOL(touchscreen_parse_of_params);
88