Commit 80c99bcd28617bd534b6f9489857235ee613c797

Authored by Daniel Mack
Committed by Dmitry Torokhov
1 parent ce91953782

Input: rotary-encoder - add DT bindings

This adds devicetree bindings to the rotary encoder driver and some
documentation about how to use them. Tested on a PXA3xx platform.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Showing 2 changed files with 116 additions and 16 deletions Side-by-side Diff

Documentation/devicetree/bindings/input/rotary-encoder.txt
  1 +Rotary encoder DT bindings
  2 +
  3 +Required properties:
  4 +- gpios: a spec for two GPIOs to be used
  5 +
  6 +Optional properties:
  7 +- linux,axis: the input subsystem axis to map to this rotary encoder.
  8 + Defaults to 0 (ABS_X / REL_X)
  9 +- rotary-encoder,steps: Number of steps in a full turnaround of the
  10 + encoder. Only relevant for absolute axis. Defaults to 24 which is a
  11 + typical value for such devices.
  12 +- rotary-encoder,relative-axis: register a relative axis rather than an
  13 + absolute one. Relative axis will only generate +1/-1 events on the input
  14 + device, hence no steps need to be passed.
  15 +- rotary-encoder,rollover: Automatic rollove when the rotary value becomes
  16 + greater than the specified steps or smaller than 0. For absolute axis only.
  17 +- rotary-encoder,half-period: Makes the driver work on half-period mode.
  18 +
  19 +See Documentation/input/rotary-encoder.txt for more information.
  20 +
  21 +Example:
  22 +
  23 + rotary@0 {
  24 + compatible = "rotary-encoder";
  25 + gpios = <&gpio 19 1>, <&gpio 20 0>; /* GPIO19 is inverted */
  26 + linux,axis = <0>; /* REL_X */
  27 + rotary-encoder,relative-axis;
  28 + };
  29 +
  30 + rotary@1 {
  31 + compatible = "rotary-encoder";
  32 + gpios = <&gpio 21 0>, <&gpio 22 0>;
  33 + linux,axis = <1>; /* ABS_Y */
  34 + rotary-encoder,steps = <24>;
  35 + rotary-encoder,rollover;
  36 + };
drivers/input/misc/rotary_encoder.c
... ... @@ -24,6 +24,8 @@
24 24 #include <linux/gpio.h>
25 25 #include <linux/rotary_encoder.h>
26 26 #include <linux/slab.h>
  27 +#include <linux/of_platform.h>
  28 +#include <linux/of_gpio.h>
27 29  
28 30 #define DRV_NAME "rotary-encoder"
29 31  
... ... @@ -140,6 +142,56 @@
140 142 return IRQ_HANDLED;
141 143 }
142 144  
  145 +#ifdef CONFIG_OF
  146 +static struct of_device_id rotary_encoder_of_match[] = {
  147 + { .compatible = "rotary-encoder", },
  148 + { },
  149 +};
  150 +MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
  151 +
  152 +static struct rotary_encoder_platform_data * __devinit
  153 +rotary_encoder_parse_dt(struct device *dev)
  154 +{
  155 + const struct of_device_id *of_id =
  156 + of_match_device(rotary_encoder_of_match, dev);
  157 + struct device_node *np = dev->of_node;
  158 + struct rotary_encoder_platform_data *pdata;
  159 + enum of_gpio_flags flags;
  160 +
  161 + if (!of_id || !np)
  162 + return NULL;
  163 +
  164 + pdata = kzalloc(sizeof(struct rotary_encoder_platform_data),
  165 + GFP_KERNEL);
  166 + if (!pdata)
  167 + return ERR_PTR(-ENOMEM);
  168 +
  169 + of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps);
  170 + of_property_read_u32(np, "linux,axis", &pdata->axis);
  171 +
  172 + pdata->gpio_a = of_get_gpio_flags(np, 0, &flags);
  173 + pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW;
  174 +
  175 + pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
  176 + pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
  177 +
  178 + pdata->relative_axis = !!of_get_property(np,
  179 + "rotary-encoder,relative-axis", NULL);
  180 + pdata->rollover = !!of_get_property(np,
  181 + "rotary-encoder,rollover", NULL);
  182 + pdata->half_period = !!of_get_property(np,
  183 + "rotary-encoder,half-period", NULL);
  184 +
  185 + return pdata;
  186 +}
  187 +#else
  188 +static inline struct rotary_encoder_platform_data *
  189 +rotary_encoder_parse_dt(struct device *dev)
  190 +{
  191 + return NULL;
  192 +}
  193 +#endif
  194 +
143 195 static int __devinit rotary_encoder_probe(struct platform_device *pdev)
144 196 {
145 197 struct device *dev = &pdev->dev;
146 198  
... ... @@ -150,14 +202,19 @@
150 202 int err;
151 203  
152 204 if (!pdata) {
153   - dev_err(&pdev->dev, "missing platform data\n");
154   - return -ENOENT;
  205 + pdata = rotary_encoder_parse_dt(dev);
  206 + if (IS_ERR(pdata))
  207 + return PTR_ERR(pdata);
  208 +
  209 + if (!pdata) {
  210 + dev_err(dev, "missing platform data\n");
  211 + return -EINVAL;
  212 + }
155 213 }
156 214  
157 215 encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL);
158 216 input = input_allocate_device();
159 217 if (!encoder || !input) {
160   - dev_err(&pdev->dev, "failed to allocate memory for device\n");
161 218 err = -ENOMEM;
162 219 goto exit_free_mem;
163 220 }
164 221  
... ... @@ -165,10 +222,9 @@
165 222 encoder->input = input;
166 223 encoder->pdata = pdata;
167 224  
168   - /* create and register the input driver */
169 225 input->name = pdev->name;
170 226 input->id.bustype = BUS_HOST;
171   - input->dev.parent = &pdev->dev;
  227 + input->dev.parent = dev;
172 228  
173 229 if (pdata->relative_axis) {
174 230 input->evbit[0] = BIT_MASK(EV_REL);
175 231  
... ... @@ -179,17 +235,11 @@
179 235 pdata->axis, 0, pdata->steps, 0, 1);
180 236 }
181 237  
182   - err = input_register_device(input);
183   - if (err) {
184   - dev_err(dev, "failed to register input device\n");
185   - goto exit_free_mem;
186   - }
187   -
188 238 /* request the GPIOs */
189 239 err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev));
190 240 if (err) {
191 241 dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a);
192   - goto exit_unregister_input;
  242 + goto exit_free_mem;
193 243 }
194 244  
195 245 err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev));
196 246  
197 247  
198 248  
... ... @@ -225,22 +275,30 @@
225 275 goto exit_free_irq_a;
226 276 }
227 277  
  278 + err = input_register_device(input);
  279 + if (err) {
  280 + dev_err(dev, "failed to register input device\n");
  281 + goto exit_free_irq_b;
  282 + }
  283 +
228 284 platform_set_drvdata(pdev, encoder);
229 285  
230 286 return 0;
231 287  
  288 +exit_free_irq_b:
  289 + free_irq(encoder->irq_b, encoder);
232 290 exit_free_irq_a:
233 291 free_irq(encoder->irq_a, encoder);
234 292 exit_free_gpio_b:
235 293 gpio_free(pdata->gpio_b);
236 294 exit_free_gpio_a:
237 295 gpio_free(pdata->gpio_a);
238   -exit_unregister_input:
239   - input_unregister_device(input);
240   - input = NULL; /* so we don't try to free it */
241 296 exit_free_mem:
242 297 input_free_device(input);
243 298 kfree(encoder);
  299 + if (!dev_get_platdata(&pdev->dev))
  300 + kfree(pdata);
  301 +
244 302 return err;
245 303 }
246 304  
247 305  
248 306  
... ... @@ -253,10 +311,15 @@
253 311 free_irq(encoder->irq_b, encoder);
254 312 gpio_free(pdata->gpio_a);
255 313 gpio_free(pdata->gpio_b);
  314 +
256 315 input_unregister_device(encoder->input);
257   - platform_set_drvdata(pdev, NULL);
258 316 kfree(encoder);
259 317  
  318 + if (!dev_get_platdata(&pdev->dev))
  319 + kfree(pdata);
  320 +
  321 + platform_set_drvdata(pdev, NULL);
  322 +
260 323 return 0;
261 324 }
262 325  
... ... @@ -266,6 +329,7 @@
266 329 .driver = {
267 330 .name = DRV_NAME,
268 331 .owner = THIS_MODULE,
  332 + .of_match_table = of_match_ptr(rotary_encoder_of_match),
269 333 }
270 334 };
271 335 module_platform_driver(rotary_encoder_driver);