diff options
author | Ike Panhc <ike.pan@canonical.com> | 2010-12-13 05:00:15 -0500 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2011-01-07 17:03:45 -0500 |
commit | 98ee69191d3af68e2292528cbb16dcba3d8e2b81 (patch) | |
tree | d363de22466fd93f486323c4507aeef6a01db2c6 /drivers/platform | |
parent | 9c23225006b695ceba31c035b287f5a7a0b0304e (diff) |
ideapad: add platform driver for ideapad
Create /sys/devices/platform/ideapad for nodes of ideapad landing.
Signed-off-by: Ike Panhc <ike.pan@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 5ff12205aa6b..5998ae14a220 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <acpi/acpi_bus.h> | 27 | #include <acpi/acpi_bus.h> |
28 | #include <acpi/acpi_drivers.h> | 28 | #include <acpi/acpi_drivers.h> |
29 | #include <linux/rfkill.h> | 29 | #include <linux/rfkill.h> |
30 | #include <linux/platform_device.h> | ||
30 | 31 | ||
31 | #define IDEAPAD_DEV_CAMERA 0 | 32 | #define IDEAPAD_DEV_CAMERA 0 |
32 | #define IDEAPAD_DEV_WLAN 1 | 33 | #define IDEAPAD_DEV_WLAN 1 |
@@ -37,6 +38,7 @@ | |||
37 | struct ideapad_private { | 38 | struct ideapad_private { |
38 | acpi_handle handle; | 39 | acpi_handle handle; |
39 | struct rfkill *rfk[5]; | 40 | struct rfkill *rfk[5]; |
41 | struct platform_device *platform_device; | ||
40 | } *ideapad_priv; | 42 | } *ideapad_priv; |
41 | 43 | ||
42 | static struct { | 44 | static struct { |
@@ -277,6 +279,35 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev) | |||
277 | rfkill_destroy(priv->rfk[dev]); | 279 | rfkill_destroy(priv->rfk[dev]); |
278 | } | 280 | } |
279 | 281 | ||
282 | /* | ||
283 | * Platform device | ||
284 | */ | ||
285 | static int __devinit ideapad_platform_init(void) | ||
286 | { | ||
287 | int result; | ||
288 | |||
289 | ideapad_priv->platform_device = platform_device_alloc("ideapad", -1); | ||
290 | if (!ideapad_priv->platform_device) | ||
291 | return -ENOMEM; | ||
292 | platform_set_drvdata(ideapad_priv->platform_device, ideapad_priv); | ||
293 | |||
294 | result = platform_device_add(ideapad_priv->platform_device); | ||
295 | if (result) | ||
296 | goto fail_platform_device; | ||
297 | |||
298 | return 0; | ||
299 | |||
300 | fail_platform_device: | ||
301 | platform_device_put(ideapad_priv->platform_device); | ||
302 | return result; | ||
303 | } | ||
304 | |||
305 | static void ideapad_platform_exit(void) | ||
306 | { | ||
307 | platform_device_unregister(ideapad_priv->platform_device); | ||
308 | } | ||
309 | /* the above is platform device */ | ||
310 | |||
280 | static const struct acpi_device_id ideapad_device_ids[] = { | 311 | static const struct acpi_device_id ideapad_device_ids[] = { |
281 | { "VPC2004", 0}, | 312 | { "VPC2004", 0}, |
282 | { "", 0}, | 313 | { "", 0}, |
@@ -285,7 +316,7 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); | |||
285 | 316 | ||
286 | static int ideapad_acpi_add(struct acpi_device *adevice) | 317 | static int ideapad_acpi_add(struct acpi_device *adevice) |
287 | { | 318 | { |
288 | int i, cfg; | 319 | int ret, i, cfg; |
289 | int devs_present[5]; | 320 | int devs_present[5]; |
290 | struct ideapad_private *priv; | 321 | struct ideapad_private *priv; |
291 | 322 | ||
@@ -305,18 +336,20 @@ static int ideapad_acpi_add(struct acpi_device *adevice) | |||
305 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 336 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
306 | if (!priv) | 337 | if (!priv) |
307 | return -ENOMEM; | 338 | return -ENOMEM; |
339 | ideapad_priv = priv; | ||
340 | |||
341 | ret = ideapad_platform_init(); | ||
342 | if (ret) | ||
343 | goto platform_failed; | ||
308 | 344 | ||
309 | if (devs_present[IDEAPAD_DEV_CAMERA]) { | 345 | if (devs_present[IDEAPAD_DEV_CAMERA]) { |
310 | int ret = device_create_file(&adevice->dev, &dev_attr_camera_power); | 346 | ret = device_create_file(&adevice->dev, &dev_attr_camera_power); |
311 | if (ret) { | 347 | if (ret) |
312 | kfree(priv); | 348 | goto camera_failed; |
313 | return ret; | ||
314 | } | ||
315 | } | 349 | } |
316 | 350 | ||
317 | priv->handle = adevice->handle; | 351 | priv->handle = adevice->handle; |
318 | dev_set_drvdata(&adevice->dev, priv); | 352 | dev_set_drvdata(&adevice->dev, priv); |
319 | ideapad_priv = priv; | ||
320 | for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) { | 353 | for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) { |
321 | if (!devs_present[i]) | 354 | if (!devs_present[i]) |
322 | continue; | 355 | continue; |
@@ -325,6 +358,12 @@ static int ideapad_acpi_add(struct acpi_device *adevice) | |||
325 | } | 358 | } |
326 | ideapad_sync_rfk_state(adevice); | 359 | ideapad_sync_rfk_state(adevice); |
327 | return 0; | 360 | return 0; |
361 | |||
362 | camera_failed: | ||
363 | ideapad_platform_exit(); | ||
364 | platform_failed: | ||
365 | kfree(priv); | ||
366 | return ret; | ||
328 | } | 367 | } |
329 | 368 | ||
330 | static int ideapad_acpi_remove(struct acpi_device *adevice, int type) | 369 | static int ideapad_acpi_remove(struct acpi_device *adevice, int type) |
@@ -337,6 +376,7 @@ static int ideapad_acpi_remove(struct acpi_device *adevice, int type) | |||
337 | for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) | 376 | for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) |
338 | ideapad_unregister_rfkill(adevice, i); | 377 | ideapad_unregister_rfkill(adevice, i); |
339 | 378 | ||
379 | ideapad_platform_exit(); | ||
340 | dev_set_drvdata(&adevice->dev, NULL); | 380 | dev_set_drvdata(&adevice->dev, NULL); |
341 | kfree(priv); | 381 | kfree(priv); |
342 | return 0; | 382 | return 0; |