diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-10-01 17:20:58 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-10-01 17:20:58 -0400 |
commit | dde3ada3d0069855eeb353707b2b0f946191cfd6 (patch) | |
tree | bdc2d358f8dc7fc29000149ebc4db949934b15b2 /drivers/input/keyboard/gpio_keys_polled.c | |
parent | 5e056ef4ddeb6129f6bb170f2c26b8f370bbcda7 (diff) | |
parent | fb4f552e895cec29934d94a99cbd1f1f00448a88 (diff) |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.7 merge window.
Diffstat (limited to 'drivers/input/keyboard/gpio_keys_polled.c')
-rw-r--r-- | drivers/input/keyboard/gpio_keys_polled.c | 147 |
1 files changed, 135 insertions, 12 deletions
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 20c8ab172214..f2142de789e7 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
27 | #include <linux/gpio_keys.h> | 27 | #include <linux/gpio_keys.h> |
28 | #include <linux/of_platform.h> | ||
29 | #include <linux/of_gpio.h> | ||
28 | 30 | ||
29 | #define DRV_NAME "gpio-keys-polled" | 31 | #define DRV_NAME "gpio-keys-polled" |
30 | 32 | ||
@@ -38,7 +40,7 @@ struct gpio_keys_button_data { | |||
38 | struct gpio_keys_polled_dev { | 40 | struct gpio_keys_polled_dev { |
39 | struct input_polled_dev *poll_dev; | 41 | struct input_polled_dev *poll_dev; |
40 | struct device *dev; | 42 | struct device *dev; |
41 | struct gpio_keys_platform_data *pdata; | 43 | const struct gpio_keys_platform_data *pdata; |
42 | struct gpio_keys_button_data data[0]; | 44 | struct gpio_keys_button_data data[0]; |
43 | }; | 45 | }; |
44 | 46 | ||
@@ -67,11 +69,11 @@ static void gpio_keys_polled_check_state(struct input_dev *input, | |||
67 | static void gpio_keys_polled_poll(struct input_polled_dev *dev) | 69 | static void gpio_keys_polled_poll(struct input_polled_dev *dev) |
68 | { | 70 | { |
69 | struct gpio_keys_polled_dev *bdev = dev->private; | 71 | struct gpio_keys_polled_dev *bdev = dev->private; |
70 | struct gpio_keys_platform_data *pdata = bdev->pdata; | 72 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
71 | struct input_dev *input = dev->input; | 73 | struct input_dev *input = dev->input; |
72 | int i; | 74 | int i; |
73 | 75 | ||
74 | for (i = 0; i < bdev->pdata->nbuttons; i++) { | 76 | for (i = 0; i < pdata->nbuttons; i++) { |
75 | struct gpio_keys_button_data *bdata = &bdev->data[i]; | 77 | struct gpio_keys_button_data *bdata = &bdev->data[i]; |
76 | 78 | ||
77 | if (bdata->count < bdata->threshold) | 79 | if (bdata->count < bdata->threshold) |
@@ -85,7 +87,7 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) | |||
85 | static void gpio_keys_polled_open(struct input_polled_dev *dev) | 87 | static void gpio_keys_polled_open(struct input_polled_dev *dev) |
86 | { | 88 | { |
87 | struct gpio_keys_polled_dev *bdev = dev->private; | 89 | struct gpio_keys_polled_dev *bdev = dev->private; |
88 | struct gpio_keys_platform_data *pdata = bdev->pdata; | 90 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
89 | 91 | ||
90 | if (pdata->enable) | 92 | if (pdata->enable) |
91 | pdata->enable(bdev->dev); | 93 | pdata->enable(bdev->dev); |
@@ -94,31 +96,139 @@ static void gpio_keys_polled_open(struct input_polled_dev *dev) | |||
94 | static void gpio_keys_polled_close(struct input_polled_dev *dev) | 96 | static void gpio_keys_polled_close(struct input_polled_dev *dev) |
95 | { | 97 | { |
96 | struct gpio_keys_polled_dev *bdev = dev->private; | 98 | struct gpio_keys_polled_dev *bdev = dev->private; |
97 | struct gpio_keys_platform_data *pdata = bdev->pdata; | 99 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
98 | 100 | ||
99 | if (pdata->disable) | 101 | if (pdata->disable) |
100 | pdata->disable(bdev->dev); | 102 | pdata->disable(bdev->dev); |
101 | } | 103 | } |
102 | 104 | ||
105 | #ifdef CONFIG_OF | ||
106 | static struct gpio_keys_platform_data * __devinit | ||
107 | gpio_keys_polled_get_devtree_pdata(struct device *dev) | ||
108 | { | ||
109 | struct device_node *node, *pp; | ||
110 | struct gpio_keys_platform_data *pdata; | ||
111 | struct gpio_keys_button *button; | ||
112 | int error; | ||
113 | int nbuttons; | ||
114 | int i; | ||
115 | |||
116 | node = dev->of_node; | ||
117 | if (!node) | ||
118 | return NULL; | ||
119 | |||
120 | nbuttons = of_get_child_count(node); | ||
121 | if (nbuttons == 0) | ||
122 | return NULL; | ||
123 | |||
124 | pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), | ||
125 | GFP_KERNEL); | ||
126 | if (!pdata) { | ||
127 | error = -ENOMEM; | ||
128 | goto err_out; | ||
129 | } | ||
130 | |||
131 | pdata->buttons = (struct gpio_keys_button *)(pdata + 1); | ||
132 | pdata->nbuttons = nbuttons; | ||
133 | |||
134 | pdata->rep = !!of_get_property(node, "autorepeat", NULL); | ||
135 | of_property_read_u32(node, "poll-interval", &pdata->poll_interval); | ||
136 | |||
137 | i = 0; | ||
138 | for_each_child_of_node(node, pp) { | ||
139 | enum of_gpio_flags flags; | ||
140 | |||
141 | if (!of_find_property(pp, "gpios", NULL)) { | ||
142 | pdata->nbuttons--; | ||
143 | dev_warn(dev, "Found button without gpios\n"); | ||
144 | continue; | ||
145 | } | ||
146 | |||
147 | button = &pdata->buttons[i++]; | ||
148 | |||
149 | button->gpio = of_get_gpio_flags(pp, 0, &flags); | ||
150 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
151 | |||
152 | if (of_property_read_u32(pp, "linux,code", &button->code)) { | ||
153 | dev_err(dev, "Button without keycode: 0x%x\n", | ||
154 | button->gpio); | ||
155 | error = -EINVAL; | ||
156 | goto err_free_pdata; | ||
157 | } | ||
158 | |||
159 | button->desc = of_get_property(pp, "label", NULL); | ||
160 | |||
161 | if (of_property_read_u32(pp, "linux,input-type", &button->type)) | ||
162 | button->type = EV_KEY; | ||
163 | |||
164 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | ||
165 | |||
166 | if (of_property_read_u32(pp, "debounce-interval", | ||
167 | &button->debounce_interval)) | ||
168 | button->debounce_interval = 5; | ||
169 | } | ||
170 | |||
171 | if (pdata->nbuttons == 0) { | ||
172 | error = -EINVAL; | ||
173 | goto err_free_pdata; | ||
174 | } | ||
175 | |||
176 | return pdata; | ||
177 | |||
178 | err_free_pdata: | ||
179 | kfree(pdata); | ||
180 | err_out: | ||
181 | return ERR_PTR(error); | ||
182 | } | ||
183 | |||
184 | static struct of_device_id gpio_keys_polled_of_match[] = { | ||
185 | { .compatible = "gpio-keys-polled", }, | ||
186 | { }, | ||
187 | }; | ||
188 | MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); | ||
189 | |||
190 | #else | ||
191 | |||
192 | static inline struct gpio_keys_platform_data * | ||
193 | gpio_keys_polled_get_devtree_pdata(struct device *dev) | ||
194 | { | ||
195 | return NULL; | ||
196 | } | ||
197 | #endif | ||
198 | |||
103 | static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) | 199 | static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) |
104 | { | 200 | { |
105 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
106 | struct device *dev = &pdev->dev; | 201 | struct device *dev = &pdev->dev; |
202 | const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); | ||
107 | struct gpio_keys_polled_dev *bdev; | 203 | struct gpio_keys_polled_dev *bdev; |
108 | struct input_polled_dev *poll_dev; | 204 | struct input_polled_dev *poll_dev; |
109 | struct input_dev *input; | 205 | struct input_dev *input; |
110 | int error; | 206 | int error; |
111 | int i; | 207 | int i; |
112 | 208 | ||
113 | if (!pdata || !pdata->poll_interval) | 209 | if (!pdata) { |
114 | return -EINVAL; | 210 | pdata = gpio_keys_polled_get_devtree_pdata(dev); |
211 | if (IS_ERR(pdata)) | ||
212 | return PTR_ERR(pdata); | ||
213 | if (!pdata) { | ||
214 | dev_err(dev, "missing platform data\n"); | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | if (!pdata->poll_interval) { | ||
220 | dev_err(dev, "missing poll_interval value\n"); | ||
221 | error = -EINVAL; | ||
222 | goto err_free_pdata; | ||
223 | } | ||
115 | 224 | ||
116 | bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + | 225 | bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + |
117 | pdata->nbuttons * sizeof(struct gpio_keys_button_data), | 226 | pdata->nbuttons * sizeof(struct gpio_keys_button_data), |
118 | GFP_KERNEL); | 227 | GFP_KERNEL); |
119 | if (!bdev) { | 228 | if (!bdev) { |
120 | dev_err(dev, "no memory for private data\n"); | 229 | dev_err(dev, "no memory for private data\n"); |
121 | return -ENOMEM; | 230 | error = -ENOMEM; |
231 | goto err_free_pdata; | ||
122 | } | 232 | } |
123 | 233 | ||
124 | poll_dev = input_allocate_polled_device(); | 234 | poll_dev = input_allocate_polled_device(); |
@@ -197,7 +307,7 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) | |||
197 | /* report initial state of the buttons */ | 307 | /* report initial state of the buttons */ |
198 | for (i = 0; i < pdata->nbuttons; i++) | 308 | for (i = 0; i < pdata->nbuttons; i++) |
199 | gpio_keys_polled_check_state(input, &pdata->buttons[i], | 309 | gpio_keys_polled_check_state(input, &pdata->buttons[i], |
200 | &bdev->data[i]); | 310 | &bdev->data[i]); |
201 | 311 | ||
202 | return 0; | 312 | return 0; |
203 | 313 | ||
@@ -209,15 +319,20 @@ err_free_gpio: | |||
209 | 319 | ||
210 | err_free_bdev: | 320 | err_free_bdev: |
211 | kfree(bdev); | 321 | kfree(bdev); |
212 | |||
213 | platform_set_drvdata(pdev, NULL); | 322 | platform_set_drvdata(pdev, NULL); |
323 | |||
324 | err_free_pdata: | ||
325 | /* If we have no platform_data, we allocated pdata dynamically. */ | ||
326 | if (!dev_get_platdata(&pdev->dev)) | ||
327 | kfree(pdata); | ||
328 | |||
214 | return error; | 329 | return error; |
215 | } | 330 | } |
216 | 331 | ||
217 | static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) | 332 | static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) |
218 | { | 333 | { |
219 | struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); | 334 | struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); |
220 | struct gpio_keys_platform_data *pdata = bdev->pdata; | 335 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
221 | int i; | 336 | int i; |
222 | 337 | ||
223 | input_unregister_polled_device(bdev->poll_dev); | 338 | input_unregister_polled_device(bdev->poll_dev); |
@@ -227,6 +342,13 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) | |||
227 | 342 | ||
228 | input_free_polled_device(bdev->poll_dev); | 343 | input_free_polled_device(bdev->poll_dev); |
229 | 344 | ||
345 | /* | ||
346 | * If we had no platform_data, we allocated pdata dynamically and | ||
347 | * must free it here. | ||
348 | */ | ||
349 | if (!dev_get_platdata(&pdev->dev)) | ||
350 | kfree(pdata); | ||
351 | |||
230 | kfree(bdev); | 352 | kfree(bdev); |
231 | platform_set_drvdata(pdev, NULL); | 353 | platform_set_drvdata(pdev, NULL); |
232 | 354 | ||
@@ -239,6 +361,7 @@ static struct platform_driver gpio_keys_polled_driver = { | |||
239 | .driver = { | 361 | .driver = { |
240 | .name = DRV_NAME, | 362 | .name = DRV_NAME, |
241 | .owner = THIS_MODULE, | 363 | .owner = THIS_MODULE, |
364 | .of_match_table = of_match_ptr(gpio_keys_polled_of_match), | ||
242 | }, | 365 | }, |
243 | }; | 366 | }; |
244 | module_platform_driver(gpio_keys_polled_driver); | 367 | module_platform_driver(gpio_keys_polled_driver); |