diff options
Diffstat (limited to 'drivers/input/misc/rotary_encoder.c')
-rw-r--r-- | drivers/input/misc/rotary_encoder.c | 140 |
1 files changed, 94 insertions, 46 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index f07f784198b9..99a49e4968d2 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -24,12 +24,14 @@ | |||
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 | ||
30 | struct rotary_encoder { | 32 | struct rotary_encoder { |
31 | struct input_dev *input; | 33 | struct input_dev *input; |
32 | struct rotary_encoder_platform_data *pdata; | 34 | const struct rotary_encoder_platform_data *pdata; |
33 | 35 | ||
34 | unsigned int axis; | 36 | unsigned int axis; |
35 | unsigned int pos; | 37 | unsigned int pos; |
@@ -43,7 +45,7 @@ struct rotary_encoder { | |||
43 | char last_stable; | 45 | char last_stable; |
44 | }; | 46 | }; |
45 | 47 | ||
46 | static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) | 48 | static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata) |
47 | { | 49 | { |
48 | int a = !!gpio_get_value(pdata->gpio_a); | 50 | int a = !!gpio_get_value(pdata->gpio_a); |
49 | int b = !!gpio_get_value(pdata->gpio_b); | 51 | int b = !!gpio_get_value(pdata->gpio_b); |
@@ -56,7 +58,7 @@ static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) | |||
56 | 58 | ||
57 | static void rotary_encoder_report_event(struct rotary_encoder *encoder) | 59 | static void rotary_encoder_report_event(struct rotary_encoder *encoder) |
58 | { | 60 | { |
59 | struct rotary_encoder_platform_data *pdata = encoder->pdata; | 61 | const struct rotary_encoder_platform_data *pdata = encoder->pdata; |
60 | 62 | ||
61 | if (pdata->relative_axis) { | 63 | if (pdata->relative_axis) { |
62 | input_report_rel(encoder->input, | 64 | input_report_rel(encoder->input, |
@@ -140,36 +142,89 @@ 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 rotary_encoder_platform_data *pdata = pdev->dev.platform_data; | 197 | struct device *dev = &pdev->dev; |
198 | const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev); | ||
146 | struct rotary_encoder *encoder; | 199 | struct rotary_encoder *encoder; |
147 | struct input_dev *input; | 200 | struct input_dev *input; |
148 | irq_handler_t handler; | 201 | irq_handler_t handler; |
149 | int err; | 202 | int err; |
150 | 203 | ||
151 | if (!pdata) { | 204 | if (!pdata) { |
152 | dev_err(&pdev->dev, "missing platform data\n"); | 205 | pdata = rotary_encoder_parse_dt(dev); |
153 | 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 | } | ||
154 | } | 213 | } |
155 | 214 | ||
156 | encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); | 215 | encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); |
157 | input = input_allocate_device(); | 216 | input = input_allocate_device(); |
158 | if (!encoder || !input) { | 217 | if (!encoder || !input) { |
159 | dev_err(&pdev->dev, "failed to allocate memory for device\n"); | ||
160 | err = -ENOMEM; | 218 | err = -ENOMEM; |
161 | goto exit_free_mem; | 219 | goto exit_free_mem; |
162 | } | 220 | } |
163 | 221 | ||
164 | encoder->input = input; | 222 | encoder->input = input; |
165 | encoder->pdata = pdata; | 223 | encoder->pdata = pdata; |
166 | encoder->irq_a = gpio_to_irq(pdata->gpio_a); | ||
167 | encoder->irq_b = gpio_to_irq(pdata->gpio_b); | ||
168 | 224 | ||
169 | /* create and register the input driver */ | ||
170 | input->name = pdev->name; | 225 | input->name = pdev->name; |
171 | input->id.bustype = BUS_HOST; | 226 | input->id.bustype = BUS_HOST; |
172 | input->dev.parent = &pdev->dev; | 227 | input->dev.parent = dev; |
173 | 228 | ||
174 | if (pdata->relative_axis) { | 229 | if (pdata->relative_axis) { |
175 | input->evbit[0] = BIT_MASK(EV_REL); | 230 | input->evbit[0] = BIT_MASK(EV_REL); |
@@ -180,40 +235,21 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
180 | pdata->axis, 0, pdata->steps, 0, 1); | 235 | pdata->axis, 0, pdata->steps, 0, 1); |
181 | } | 236 | } |
182 | 237 | ||
183 | err = input_register_device(input); | ||
184 | if (err) { | ||
185 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
186 | goto exit_free_mem; | ||
187 | } | ||
188 | |||
189 | /* request the GPIOs */ | 238 | /* request the GPIOs */ |
190 | err = gpio_request(pdata->gpio_a, DRV_NAME); | 239 | err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); |
191 | if (err) { | ||
192 | dev_err(&pdev->dev, "unable to request GPIO %d\n", | ||
193 | pdata->gpio_a); | ||
194 | goto exit_unregister_input; | ||
195 | } | ||
196 | |||
197 | err = gpio_direction_input(pdata->gpio_a); | ||
198 | if (err) { | 240 | if (err) { |
199 | dev_err(&pdev->dev, "unable to set GPIO %d for input\n", | 241 | dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); |
200 | pdata->gpio_a); | 242 | goto exit_free_mem; |
201 | goto exit_unregister_input; | ||
202 | } | 243 | } |
203 | 244 | ||
204 | err = gpio_request(pdata->gpio_b, DRV_NAME); | 245 | err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); |
205 | if (err) { | 246 | if (err) { |
206 | dev_err(&pdev->dev, "unable to request GPIO %d\n", | 247 | dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b); |
207 | pdata->gpio_b); | ||
208 | goto exit_free_gpio_a; | 248 | goto exit_free_gpio_a; |
209 | } | 249 | } |
210 | 250 | ||
211 | err = gpio_direction_input(pdata->gpio_b); | 251 | encoder->irq_a = gpio_to_irq(pdata->gpio_a); |
212 | if (err) { | 252 | encoder->irq_b = gpio_to_irq(pdata->gpio_b); |
213 | dev_err(&pdev->dev, "unable to set GPIO %d for input\n", | ||
214 | pdata->gpio_b); | ||
215 | goto exit_free_gpio_a; | ||
216 | } | ||
217 | 253 | ||
218 | /* request the IRQs */ | 254 | /* request the IRQs */ |
219 | if (pdata->half_period) { | 255 | if (pdata->half_period) { |
@@ -227,8 +263,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
227 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 263 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
228 | DRV_NAME, encoder); | 264 | DRV_NAME, encoder); |
229 | if (err) { | 265 | if (err) { |
230 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | 266 | dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); |
231 | encoder->irq_a); | ||
232 | goto exit_free_gpio_b; | 267 | goto exit_free_gpio_b; |
233 | } | 268 | } |
234 | 269 | ||
@@ -236,43 +271,55 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
236 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 271 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
237 | DRV_NAME, encoder); | 272 | DRV_NAME, encoder); |
238 | if (err) { | 273 | if (err) { |
239 | dev_err(&pdev->dev, "unable to request IRQ %d\n", | 274 | dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); |
240 | encoder->irq_b); | ||
241 | goto exit_free_irq_a; | 275 | goto exit_free_irq_a; |
242 | } | 276 | } |
243 | 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 | |||
244 | platform_set_drvdata(pdev, encoder); | 284 | platform_set_drvdata(pdev, encoder); |
245 | 285 | ||
246 | return 0; | 286 | return 0; |
247 | 287 | ||
288 | exit_free_irq_b: | ||
289 | free_irq(encoder->irq_b, encoder); | ||
248 | exit_free_irq_a: | 290 | exit_free_irq_a: |
249 | free_irq(encoder->irq_a, encoder); | 291 | free_irq(encoder->irq_a, encoder); |
250 | exit_free_gpio_b: | 292 | exit_free_gpio_b: |
251 | gpio_free(pdata->gpio_b); | 293 | gpio_free(pdata->gpio_b); |
252 | exit_free_gpio_a: | 294 | exit_free_gpio_a: |
253 | gpio_free(pdata->gpio_a); | 295 | gpio_free(pdata->gpio_a); |
254 | exit_unregister_input: | ||
255 | input_unregister_device(input); | ||
256 | input = NULL; /* so we don't try to free it */ | ||
257 | exit_free_mem: | 296 | exit_free_mem: |
258 | input_free_device(input); | 297 | input_free_device(input); |
259 | kfree(encoder); | 298 | kfree(encoder); |
299 | if (!dev_get_platdata(&pdev->dev)) | ||
300 | kfree(pdata); | ||
301 | |||
260 | return err; | 302 | return err; |
261 | } | 303 | } |
262 | 304 | ||
263 | static int __devexit rotary_encoder_remove(struct platform_device *pdev) | 305 | static int __devexit rotary_encoder_remove(struct platform_device *pdev) |
264 | { | 306 | { |
265 | struct rotary_encoder *encoder = platform_get_drvdata(pdev); | 307 | struct rotary_encoder *encoder = platform_get_drvdata(pdev); |
266 | struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; | 308 | const struct rotary_encoder_platform_data *pdata = encoder->pdata; |
267 | 309 | ||
268 | free_irq(encoder->irq_a, encoder); | 310 | free_irq(encoder->irq_a, encoder); |
269 | free_irq(encoder->irq_b, encoder); | 311 | free_irq(encoder->irq_b, encoder); |
270 | gpio_free(pdata->gpio_a); | 312 | gpio_free(pdata->gpio_a); |
271 | gpio_free(pdata->gpio_b); | 313 | gpio_free(pdata->gpio_b); |
314 | |||
272 | input_unregister_device(encoder->input); | 315 | input_unregister_device(encoder->input); |
273 | platform_set_drvdata(pdev, NULL); | ||
274 | kfree(encoder); | 316 | kfree(encoder); |
275 | 317 | ||
318 | if (!dev_get_platdata(&pdev->dev)) | ||
319 | kfree(pdata); | ||
320 | |||
321 | platform_set_drvdata(pdev, NULL); | ||
322 | |||
276 | return 0; | 323 | return 0; |
277 | } | 324 | } |
278 | 325 | ||
@@ -282,6 +329,7 @@ static struct platform_driver rotary_encoder_driver = { | |||
282 | .driver = { | 329 | .driver = { |
283 | .name = DRV_NAME, | 330 | .name = DRV_NAME, |
284 | .owner = THIS_MODULE, | 331 | .owner = THIS_MODULE, |
332 | .of_match_table = of_match_ptr(rotary_encoder_of_match), | ||
285 | } | 333 | } |
286 | }; | 334 | }; |
287 | module_platform_driver(rotary_encoder_driver); | 335 | module_platform_driver(rotary_encoder_driver); |