diff options
| -rw-r--r-- | drivers/platform/x86/eeepc-wmi.c | 102 |
1 files changed, 86 insertions, 16 deletions
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index daed4a476b39..0c9596c97a0f 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c | |||
| @@ -32,9 +32,12 @@ | |||
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/input.h> | 33 | #include <linux/input.h> |
| 34 | #include <linux/input/sparse-keymap.h> | 34 | #include <linux/input/sparse-keymap.h> |
| 35 | #include <linux/platform_device.h> | ||
| 35 | #include <acpi/acpi_bus.h> | 36 | #include <acpi/acpi_bus.h> |
| 36 | #include <acpi/acpi_drivers.h> | 37 | #include <acpi/acpi_drivers.h> |
| 37 | 38 | ||
| 39 | #define EEEPC_WMI_FILE "eeepc-wmi" | ||
| 40 | |||
| 38 | MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); | 41 | MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); |
| 39 | MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); | 42 | MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); |
| 40 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
| @@ -64,7 +67,7 @@ struct eeepc_wmi { | |||
| 64 | struct input_dev *inputdev; | 67 | struct input_dev *inputdev; |
| 65 | }; | 68 | }; |
| 66 | 69 | ||
| 67 | static struct eeepc_wmi *eeepc; | 70 | static struct platform_device *platform_device; |
| 68 | 71 | ||
| 69 | static void eeepc_wmi_notify(u32 value, void *context) | 72 | static void eeepc_wmi_notify(u32 value, void *context) |
| 70 | { | 73 | { |
| @@ -107,8 +110,9 @@ static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc) | |||
| 107 | return -ENOMEM; | 110 | return -ENOMEM; |
| 108 | 111 | ||
| 109 | eeepc->inputdev->name = "Eee PC WMI hotkeys"; | 112 | eeepc->inputdev->name = "Eee PC WMI hotkeys"; |
| 110 | eeepc->inputdev->phys = "wmi/input0"; | 113 | eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0"; |
| 111 | eeepc->inputdev->id.bustype = BUS_HOST; | 114 | eeepc->inputdev->id.bustype = BUS_HOST; |
| 115 | eeepc->inputdev->dev.parent = &platform_device->dev; | ||
| 112 | 116 | ||
| 113 | err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL); | 117 | err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL); |
| 114 | if (err) | 118 | if (err) |
| @@ -137,11 +141,60 @@ static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc) | |||
| 137 | eeepc->inputdev = NULL; | 141 | eeepc->inputdev = NULL; |
| 138 | } | 142 | } |
| 139 | 143 | ||
| 140 | static int __init eeepc_wmi_init(void) | 144 | static int __devinit eeepc_wmi_platform_probe(struct platform_device *device) |
| 141 | { | 145 | { |
| 146 | struct eeepc_wmi *eeepc; | ||
| 142 | int err; | 147 | int err; |
| 143 | acpi_status status; | 148 | acpi_status status; |
| 144 | 149 | ||
| 150 | eeepc = platform_get_drvdata(device); | ||
| 151 | |||
| 152 | err = eeepc_wmi_input_init(eeepc); | ||
| 153 | if (err) | ||
| 154 | return err; | ||
| 155 | |||
| 156 | status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, | ||
| 157 | eeepc_wmi_notify, eeepc); | ||
| 158 | if (ACPI_FAILURE(status)) { | ||
| 159 | pr_err("Unable to register notify handler - %d\n", | ||
| 160 | status); | ||
| 161 | err = -ENODEV; | ||
| 162 | goto error_wmi; | ||
| 163 | } | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | |||
| 167 | error_wmi: | ||
| 168 | eeepc_wmi_input_exit(eeepc); | ||
| 169 | |||
| 170 | return err; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int __devexit eeepc_wmi_platform_remove(struct platform_device *device) | ||
| 174 | { | ||
| 175 | struct eeepc_wmi *eeepc; | ||
| 176 | |||
| 177 | eeepc = platform_get_drvdata(device); | ||
| 178 | wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); | ||
| 179 | eeepc_wmi_input_exit(eeepc); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static struct platform_driver platform_driver = { | ||
| 185 | .driver = { | ||
| 186 | .name = EEEPC_WMI_FILE, | ||
| 187 | .owner = THIS_MODULE, | ||
| 188 | }, | ||
| 189 | .probe = eeepc_wmi_platform_probe, | ||
| 190 | .remove = __devexit_p(eeepc_wmi_platform_remove), | ||
| 191 | }; | ||
| 192 | |||
| 193 | static int __init eeepc_wmi_init(void) | ||
| 194 | { | ||
| 195 | struct eeepc_wmi *eeepc; | ||
| 196 | int err; | ||
| 197 | |||
| 145 | if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) { | 198 | if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) { |
| 146 | pr_warning("No known WMI GUID found\n"); | 199 | pr_warning("No known WMI GUID found\n"); |
| 147 | return -ENODEV; | 200 | return -ENODEV; |
| @@ -151,29 +204,46 @@ static int __init eeepc_wmi_init(void) | |||
| 151 | if (!eeepc) | 204 | if (!eeepc) |
| 152 | return -ENOMEM; | 205 | return -ENOMEM; |
| 153 | 206 | ||
| 154 | err = eeepc_wmi_input_init(eeepc); | 207 | platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1); |
| 208 | if (!platform_device) { | ||
| 209 | pr_warning("Unable to allocate platform device\n"); | ||
| 210 | err = -ENOMEM; | ||
| 211 | goto fail_platform; | ||
| 212 | } | ||
| 213 | |||
| 214 | err = platform_device_add(platform_device); | ||
| 155 | if (err) { | 215 | if (err) { |
| 156 | kfree(eeepc); | 216 | pr_warning("Unable to add platform device\n"); |
| 157 | return err; | 217 | goto put_dev; |
| 158 | } | 218 | } |
| 159 | 219 | ||
| 160 | status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, | 220 | platform_set_drvdata(platform_device, eeepc); |
| 161 | eeepc_wmi_notify, eeepc); | 221 | |
| 162 | if (ACPI_FAILURE(status)) { | 222 | err = platform_driver_register(&platform_driver); |
| 163 | pr_err("Unable to register notify handler - %d\n", | 223 | if (err) { |
| 164 | status); | 224 | pr_warning("Unable to register platform driver\n"); |
| 165 | eeepc_wmi_input_exit(eeepc); | 225 | goto del_dev; |
| 166 | kfree(eeepc); | ||
| 167 | return -ENODEV; | ||
| 168 | } | 226 | } |
| 169 | 227 | ||
| 170 | return 0; | 228 | return 0; |
| 229 | |||
| 230 | del_dev: | ||
| 231 | platform_device_del(platform_device); | ||
| 232 | put_dev: | ||
| 233 | platform_device_put(platform_device); | ||
| 234 | fail_platform: | ||
| 235 | kfree(eeepc); | ||
| 236 | |||
| 237 | return err; | ||
| 171 | } | 238 | } |
| 172 | 239 | ||
| 173 | static void __exit eeepc_wmi_exit(void) | 240 | static void __exit eeepc_wmi_exit(void) |
| 174 | { | 241 | { |
| 175 | wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); | 242 | struct eeepc_wmi *eeepc; |
| 176 | eeepc_wmi_input_exit(eeepc); | 243 | |
| 244 | eeepc = platform_get_drvdata(platform_device); | ||
| 245 | platform_driver_unregister(&platform_driver); | ||
| 246 | platform_device_unregister(platform_device); | ||
| 177 | kfree(eeepc); | 247 | kfree(eeepc); |
| 178 | } | 248 | } |
| 179 | 249 | ||
