drm/radeon/kms: enable use of unmappable VRAM V2
[pandora-kernel.git] / drivers / staging / dream / gpio_event.c
1 /* drivers/input/misc/gpio_event.c
2  *
3  * Copyright (C) 2007 Google, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16
17 #include <linux/module.h>
18 #include <linux/input.h>
19 #include <linux/gpio_event.h>
20 #include <linux/hrtimer.h>
21 #include <linux/platform_device.h>
22
23 struct gpio_event {
24         struct input_dev *input_dev;
25         const struct gpio_event_platform_data *info;
26         void *state[0];
27 };
28
29 static int gpio_input_event(
30         struct input_dev *dev, unsigned int type, unsigned int code, int value)
31 {
32         int i;
33         int ret = 0;
34         int tmp_ret;
35         struct gpio_event_info **ii;
36         struct gpio_event *ip = input_get_drvdata(dev);
37
38         for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
39                 if ((*ii)->event) {
40                         tmp_ret = (*ii)->event(ip->input_dev, *ii,
41                                         &ip->state[i], type, code, value);
42                         if (tmp_ret)
43                                 ret = tmp_ret;
44                 }
45         }
46         return ret;
47 }
48
49 static int gpio_event_call_all_func(struct gpio_event *ip, int func)
50 {
51         int i;
52         int ret;
53         struct gpio_event_info **ii;
54
55         if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
56                 ii = ip->info->info;
57                 for (i = 0; i < ip->info->info_count; i++, ii++) {
58                         if ((*ii)->func == NULL) {
59                                 ret = -ENODEV;
60                                 pr_err("gpio_event_probe: Incomplete pdata, "
61                                         "no function\n");
62                                 goto err_no_func;
63                         }
64                         ret = (*ii)->func(ip->input_dev, *ii, &ip->state[i],
65                                           func);
66                         if (ret) {
67                                 pr_err("gpio_event_probe: function failed\n");
68                                 goto err_func_failed;
69                         }
70                 }
71                 return 0;
72         }
73
74         ret = 0;
75         i = ip->info->info_count;
76         ii = ip->info->info + i;
77         while (i > 0) {
78                 i--;
79                 ii--;
80                 (*ii)->func(ip->input_dev, *ii, &ip->state[i], func & ~1);
81 err_func_failed:
82 err_no_func:
83                 ;
84         }
85         return ret;
86 }
87
88 #ifdef CONFIG_HAS_EARLYSUSPEND
89 void gpio_event_suspend(struct early_suspend *h)
90 {
91         struct gpio_event *ip;
92         ip = container_of(h, struct gpio_event, early_suspend);
93         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
94         ip->info->power(ip->info, 0);
95 }
96
97 void gpio_event_resume(struct early_suspend *h)
98 {
99         struct gpio_event *ip;
100         ip = container_of(h, struct gpio_event, early_suspend);
101         ip->info->power(ip->info, 1);
102         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
103 }
104 #endif
105
106 static int __init gpio_event_probe(struct platform_device *pdev)
107 {
108         int err;
109         struct gpio_event *ip;
110         struct input_dev *input_dev;
111         struct gpio_event_platform_data *event_info;
112
113         event_info = pdev->dev.platform_data;
114         if (event_info == NULL) {
115                 pr_err("gpio_event_probe: No pdata\n");
116                 return -ENODEV;
117         }
118         if (event_info->name == NULL ||
119            event_info->info == NULL ||
120            event_info->info_count == 0) {
121                 pr_err("gpio_event_probe: Incomplete pdata\n");
122                 return -ENODEV;
123         }
124         ip = kzalloc(sizeof(*ip) +
125                      sizeof(ip->state[0]) * event_info->info_count, GFP_KERNEL);
126         if (ip == NULL) {
127                 err = -ENOMEM;
128                 pr_err("gpio_event_probe: Failed to allocate private data\n");
129                 goto err_kp_alloc_failed;
130         }
131         platform_set_drvdata(pdev, ip);
132
133         input_dev = input_allocate_device();
134         if (input_dev == NULL) {
135                 err = -ENOMEM;
136                 pr_err("gpio_event_probe: Failed to allocate input device\n");
137                 goto err_input_dev_alloc_failed;
138         }
139         input_set_drvdata(input_dev, ip);
140         ip->input_dev = input_dev;
141         ip->info = event_info;
142         if (event_info->power) {
143 #ifdef CONFIG_HAS_EARLYSUSPEND
144                 ip->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
145                 ip->early_suspend.suspend = gpio_event_suspend;
146                 ip->early_suspend.resume = gpio_event_resume;
147                 register_early_suspend(&ip->early_suspend);
148 #endif
149                 ip->info->power(ip->info, 1);
150         }
151
152         input_dev->name = ip->info->name;
153         input_dev->event = gpio_input_event;
154
155         err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
156         if (err)
157                 goto err_call_all_func_failed;
158
159         err = input_register_device(input_dev);
160         if (err) {
161                 pr_err("gpio_event_probe: Unable to register %s input device\n",
162                         input_dev->name);
163                 goto err_input_register_device_failed;
164         }
165
166         return 0;
167
168 err_input_register_device_failed:
169         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
170 err_call_all_func_failed:
171         if (event_info->power) {
172 #ifdef CONFIG_HAS_EARLYSUSPEND
173                 unregister_early_suspend(&ip->early_suspend);
174 #endif
175                 ip->info->power(ip->info, 0);
176         }
177         input_free_device(input_dev);
178 err_input_dev_alloc_failed:
179         kfree(ip);
180 err_kp_alloc_failed:
181         return err;
182 }
183
184 static int gpio_event_remove(struct platform_device *pdev)
185 {
186         struct gpio_event *ip = platform_get_drvdata(pdev);
187
188         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
189         if (ip->info->power) {
190 #ifdef CONFIG_HAS_EARLYSUSPEND
191                 unregister_early_suspend(&ip->early_suspend);
192 #endif
193                 ip->info->power(ip->info, 0);
194         }
195         input_unregister_device(ip->input_dev);
196         kfree(ip);
197         return 0;
198 }
199
200 static struct platform_driver gpio_event_driver = {
201         .probe          = gpio_event_probe,
202         .remove         = gpio_event_remove,
203         .driver         = {
204                 .name   = GPIO_EVENT_DEV_NAME,
205         },
206 };
207
208 static int __devinit gpio_event_init(void)
209 {
210         return platform_driver_register(&gpio_event_driver);
211 }
212
213 static void __exit gpio_event_exit(void)
214 {
215         platform_driver_unregister(&gpio_event_driver);
216 }
217
218 module_init(gpio_event_init);
219 module_exit(gpio_event_exit);
220
221 MODULE_DESCRIPTION("GPIO Event Driver");
222 MODULE_LICENSE("GPL");
223