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 | |
| 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')
| -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); |
