diff options
author | Daniel Mack <zonque@gmail.com> | 2012-08-01 01:08:50 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-08-22 01:29:51 -0400 |
commit | 80c99bcd28617bd534b6f9489857235ee613c797 (patch) | |
tree | cd6c9bd5d05962927e2f21632ca60529fb4c1b54 /drivers/input/misc/rotary_encoder.c | |
parent | ce9195378299ff2f3d703937de46bdd338e780eb (diff) |
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>
Diffstat (limited to 'drivers/input/misc/rotary_encoder.c')
-rw-r--r-- | drivers/input/misc/rotary_encoder.c | 96 |
1 files changed, 80 insertions, 16 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index ea51265d4e04..99a49e4968d2 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/rotary_encoder.h> | 25 | #include <linux/rotary_encoder.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/of_platform.h> | ||
28 | #include <linux/of_gpio.h> | ||
27 | 29 | ||
28 | #define DRV_NAME "rotary-encoder" | 30 | #define DRV_NAME "rotary-encoder" |
29 | 31 | ||
@@ -140,6 +142,56 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) | |||
140 | return IRQ_HANDLED; | 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 | static int __devinit rotary_encoder_probe(struct platform_device *pdev) | 195 | static int __devinit rotary_encoder_probe(struct platform_device *pdev) |
144 | { | 196 | { |
145 | struct device *dev = &pdev->dev; | 197 | struct device *dev = &pdev->dev; |
@@ -150,14 +202,19 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
150 | int err; | 202 | int err; |
151 | 203 | ||
152 | if (!pdata) { | 204 | if (!pdata) { |
153 | dev_err(&pdev->dev, "missing platform data\n"); | 205 | pdata = rotary_encoder_parse_dt(dev); |
154 | return -ENOENT; | 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 | encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); | 215 | encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); |
158 | input = input_allocate_device(); | 216 | input = input_allocate_device(); |
159 | if (!encoder || !input) { | 217 | if (!encoder || !input) { |
160 | dev_err(&pdev->dev, "failed to allocate memory for device\n"); | ||
161 | err = -ENOMEM; | 218 | err = -ENOMEM; |
162 | goto exit_free_mem; | 219 | goto exit_free_mem; |
163 | } | 220 | } |
@@ -165,10 +222,9 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
165 | encoder->input = input; | 222 | encoder->input = input; |
166 | encoder->pdata = pdata; | 223 | encoder->pdata = pdata; |
167 | 224 | ||
168 | /* create and register the input driver */ | ||
169 | input->name = pdev->name; | 225 | input->name = pdev->name; |
170 | input->id.bustype = BUS_HOST; | 226 | input->id.bustype = BUS_HOST; |
171 | input->dev.parent = &pdev->dev; | 227 | input->dev.parent = dev; |
172 | 228 | ||
173 | if (pdata->relative_axis) { | 229 | if (pdata->relative_axis) { |
174 | input->evbit[0] = BIT_MASK(EV_REL); | 230 | input->evbit[0] = BIT_MASK(EV_REL); |
@@ -179,17 +235,11 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
179 | pdata->axis, 0, pdata->steps, 0, 1); | 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 | /* request the GPIOs */ | 238 | /* request the GPIOs */ |
189 | err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); | 239 | err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); |
190 | if (err) { | 240 | if (err) { |
191 | dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); | 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 | err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); | 245 | err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); |
@@ -225,22 +275,30 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
225 | goto exit_free_irq_a; | 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 | platform_set_drvdata(pdev, encoder); | 284 | platform_set_drvdata(pdev, encoder); |
229 | 285 | ||
230 | return 0; | 286 | return 0; |
231 | 287 | ||
288 | exit_free_irq_b: | ||
289 | free_irq(encoder->irq_b, encoder); | ||
232 | exit_free_irq_a: | 290 | exit_free_irq_a: |
233 | free_irq(encoder->irq_a, encoder); | 291 | free_irq(encoder->irq_a, encoder); |
234 | exit_free_gpio_b: | 292 | exit_free_gpio_b: |
235 | gpio_free(pdata->gpio_b); | 293 | gpio_free(pdata->gpio_b); |
236 | exit_free_gpio_a: | 294 | exit_free_gpio_a: |
237 | gpio_free(pdata->gpio_a); | 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 | exit_free_mem: | 296 | exit_free_mem: |
242 | input_free_device(input); | 297 | input_free_device(input); |
243 | kfree(encoder); | 298 | kfree(encoder); |
299 | if (!dev_get_platdata(&pdev->dev)) | ||
300 | kfree(pdata); | ||
301 | |||
244 | return err; | 302 | return err; |
245 | } | 303 | } |
246 | 304 | ||
@@ -253,10 +311,15 @@ static int __devexit rotary_encoder_remove(struct platform_device *pdev) | |||
253 | free_irq(encoder->irq_b, encoder); | 311 | free_irq(encoder->irq_b, encoder); |
254 | gpio_free(pdata->gpio_a); | 312 | gpio_free(pdata->gpio_a); |
255 | gpio_free(pdata->gpio_b); | 313 | gpio_free(pdata->gpio_b); |
314 | |||
256 | input_unregister_device(encoder->input); | 315 | input_unregister_device(encoder->input); |
257 | platform_set_drvdata(pdev, NULL); | ||
258 | kfree(encoder); | 316 | kfree(encoder); |
259 | 317 | ||
318 | if (!dev_get_platdata(&pdev->dev)) | ||
319 | kfree(pdata); | ||
320 | |||
321 | platform_set_drvdata(pdev, NULL); | ||
322 | |||
260 | return 0; | 323 | return 0; |
261 | } | 324 | } |
262 | 325 | ||
@@ -266,6 +329,7 @@ static struct platform_driver rotary_encoder_driver = { | |||
266 | .driver = { | 329 | .driver = { |
267 | .name = DRV_NAME, | 330 | .name = DRV_NAME, |
268 | .owner = THIS_MODULE, | 331 | .owner = THIS_MODULE, |
332 | .of_match_table = of_match_ptr(rotary_encoder_of_match), | ||
269 | } | 333 | } |
270 | }; | 334 | }; |
271 | module_platform_driver(rotary_encoder_driver); | 335 | module_platform_driver(rotary_encoder_driver); |