Commit | Line | Data |
---|---|---|
69464161 V |
1 | /* |
2 | * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License as | |
6 | * published by the Free Software Foundation version 2. | |
7 | * | |
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
9 | * kind, whether express or implied; without even the implied warranty | |
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * A generic driver to read multiple gpio lines and translate the | |
14 | * encoded numeric value into an input event. | |
15 | */ | |
16 | ||
17 | #include <linux/device.h> | |
18 | #include <linux/gpio/consumer.h> | |
19 | #include <linux/input.h> | |
20 | #include <linux/input-polldev.h> | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/module.h> | |
23 | #include <linux/of.h> | |
24 | #include <linux/platform_device.h> | |
25 | ||
26 | struct gpio_decoder { | |
27 | struct input_polled_dev *poll_dev; | |
28 | struct gpio_descs *input_gpios; | |
29 | struct device *dev; | |
30 | u32 axis; | |
31 | u32 last_stable; | |
32 | }; | |
33 | ||
34 | static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder) | |
35 | { | |
36 | struct gpio_descs *gpios = decoder->input_gpios; | |
37 | unsigned int ret = 0; | |
38 | int i, val; | |
39 | ||
40 | for (i = 0; i < gpios->ndescs; i++) { | |
41 | val = gpiod_get_value_cansleep(gpios->desc[i]); | |
42 | if (val < 0) { | |
43 | dev_err(decoder->dev, | |
44 | "Error reading gpio %d: %d\n", | |
45 | desc_to_gpio(gpios->desc[i]), val); | |
46 | return val; | |
47 | } | |
48 | ||
49 | val = !!val; | |
50 | ret = (ret << 1) | val; | |
51 | } | |
52 | ||
53 | return ret; | |
54 | } | |
55 | ||
56 | static void gpio_decoder_poll_gpios(struct input_polled_dev *poll_dev) | |
57 | { | |
58 | struct gpio_decoder *decoder = poll_dev->private; | |
59 | int state; | |
60 | ||
61 | state = gpio_decoder_get_gpios_state(decoder); | |
62 | if (state >= 0 && state != decoder->last_stable) { | |
63 | input_report_abs(poll_dev->input, decoder->axis, state); | |
64 | input_sync(poll_dev->input); | |
65 | decoder->last_stable = state; | |
66 | } | |
67 | } | |
68 | ||
69 | static int gpio_decoder_probe(struct platform_device *pdev) | |
70 | { | |
71 | struct device *dev = &pdev->dev; | |
72 | struct gpio_decoder *decoder; | |
73 | struct input_polled_dev *poll_dev; | |
74 | u32 max; | |
75 | int err; | |
76 | ||
77 | decoder = devm_kzalloc(dev, sizeof(struct gpio_decoder), GFP_KERNEL); | |
78 | if (!decoder) | |
79 | return -ENOMEM; | |
80 | ||
81 | device_property_read_u32(dev, "linux,axis", &decoder->axis); | |
82 | decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); | |
83 | if (IS_ERR(decoder->input_gpios)) { | |
84 | dev_err(dev, "unable to acquire input gpios\n"); | |
85 | return PTR_ERR(decoder->input_gpios); | |
86 | } | |
87 | if (decoder->input_gpios->ndescs < 2) { | |
88 | dev_err(dev, "not enough gpios found\n"); | |
89 | return -EINVAL; | |
90 | } | |
91 | ||
92 | if (device_property_read_u32(dev, "decoder-max-value", &max)) | |
93 | max = (1U << decoder->input_gpios->ndescs) - 1; | |
94 | ||
95 | decoder->dev = dev; | |
96 | poll_dev = devm_input_allocate_polled_device(decoder->dev); | |
97 | if (!poll_dev) | |
98 | return -ENOMEM; | |
99 | ||
100 | poll_dev->private = decoder; | |
101 | poll_dev->poll = gpio_decoder_poll_gpios; | |
102 | decoder->poll_dev = poll_dev; | |
103 | ||
104 | poll_dev->input->name = pdev->name; | |
105 | poll_dev->input->id.bustype = BUS_HOST; | |
106 | input_set_abs_params(poll_dev->input, decoder->axis, 0, max, 0, 0); | |
107 | ||
108 | err = input_register_polled_device(poll_dev); | |
109 | if (err) { | |
110 | dev_err(dev, "failed to register polled device\n"); | |
111 | return err; | |
112 | } | |
113 | platform_set_drvdata(pdev, decoder); | |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | #ifdef CONFIG_OF | |
119 | static const struct of_device_id gpio_decoder_of_match[] = { | |
120 | { .compatible = "gpio-decoder", }, | |
121 | { }, | |
122 | }; | |
123 | MODULE_DEVICE_TABLE(of, gpio_decoder_of_match); | |
124 | #endif | |
125 | ||
126 | static struct platform_driver gpio_decoder_driver = { | |
127 | .probe = gpio_decoder_probe, | |
128 | .driver = { | |
129 | .name = "gpio-decoder", | |
130 | .of_match_table = of_match_ptr(gpio_decoder_of_match), | |
131 | } | |
132 | }; | |
133 | module_platform_driver(gpio_decoder_driver); | |
134 | ||
135 | MODULE_DESCRIPTION("GPIO decoder input driver"); | |
136 | MODULE_AUTHOR("Vignesh R <vigneshr@ti.com>"); | |
137 | MODULE_LICENSE("GPL v2"); |