diff mbox

[07/28] asus-laptop: change initialization order

Message ID 1265096351-15239-8-git-send-email-corentincj@iksaif.net (mailing list archive)
State Accepted
Delegated to: Len Brown
Headers show

Commit Message

Corentin Chary Feb. 2, 2010, 7:38 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 74463a0..8834405 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -201,6 +201,8 @@  ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB");
  */
 struct asus_hotk {
 	char *name;		/* laptop name */
+
+	struct platform_device *platform_device;
 	struct acpi_device *device;	/* the device we are in */
 	acpi_handle handle;	/* the handle of the hotk device */
 	char status;		/* status of the hotk, for LEDs, ... */
@@ -222,33 +224,6 @@  static struct acpi_table_header *asus_info;
 /* The actual device the driver binds to */
 static struct asus_hotk *hotk;
 
-/*
- * The hotkey driver declaration
- */
-static const struct acpi_device_id asus_device_ids[] = {
-	{"ATK0100", 0},
-	{"ATK0101", 0},
-	{"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-
-static int asus_hotk_add(struct acpi_device *device);
-static int asus_hotk_remove(struct acpi_device *device, int type);
-static void asus_hotk_notify(struct acpi_device *device, u32 event);
-
-static struct acpi_driver asus_hotk_driver = {
-	.name = ASUS_HOTK_NAME,
-	.class = ASUS_HOTK_CLASS,
-	.owner = THIS_MODULE,
-	.ids = asus_device_ids,
-	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-	.ops = {
-		.add = asus_hotk_add,
-		.remove = asus_hotk_remove,
-		.notify = asus_hotk_notify,
-		},
-};
-
 /* The backlight device /sys/class/backlight */
 static struct backlight_device *asus_backlight_device;
 
@@ -936,7 +911,7 @@  static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
 	return -EINVAL;
 }
 
-static void asus_hotk_notify(struct acpi_device *device, u32 event)
+static void asus_acpi_notify(struct acpi_device *device, u32 event)
 {
 	static struct key_entry *key;
 	u16 count;
@@ -1013,19 +988,49 @@  static struct attribute *asuspf_attributes[] = {
 	NULL
 };
 
-static struct attribute_group asuspf_attribute_group = {
+static struct attribute_group platform_attribute_group = {
 	.attrs = asuspf_attributes
 };
 
-static struct platform_driver asuspf_driver = {
+static int asus_platform_init(void)
+{
+	int result;
+
+	hotk->platform_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
+	if (!hotk->platform_device)
+		return -ENOMEM;
+
+	result = platform_device_add(hotk->platform_device);
+	if (result)
+		goto fail_platform_device;
+
+	result = sysfs_create_group(&hotk->platform_device->dev.kobj,
+				    &platform_attribute_group);
+	if (result)
+		goto fail_sysfs;
+	return 0;
+
+fail_sysfs:
+	platform_device_del(hotk->platform_device);
+fail_platform_device:
+	platform_device_put(hotk->platform_device);
+	return result;
+}
+
+static void asus_platform_exit(void)
+{
+	sysfs_remove_group(&hotk->platform_device->dev.kobj,
+			   &platform_attribute_group);
+	platform_device_unregister(hotk->platform_device);
+}
+
+static struct platform_driver platform_driver = {
 	.driver = {
 		   .name = ASUS_HOTK_FILE,
 		   .owner = THIS_MODULE,
 		   }
 };
 
-static struct platform_device *asuspf_device;
-
 static void asus_hotk_add_fs(void)
 {
 	ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
@@ -1196,7 +1201,7 @@  static int asus_hotk_get_info(void)
 	return AE_OK;
 }
 
-static int asus_input_init(void)
+static int asus_input_init(struct device *dev)
 {
 	const struct key_entry *key;
 	int result;
@@ -1207,6 +1212,7 @@  static int asus_input_init(void)
 		return 0;
 	}
 	hotk->inputdev->name = "Asus Laptop extra buttons";
+	hotk->inputdev->dev.parent = dev;
 	hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
 	hotk->inputdev->id.bustype = BUS_HOST;
 	hotk->inputdev->getkeycode = asus_getkeycode;
@@ -1228,101 +1234,6 @@  static int asus_input_init(void)
 	return result;
 }
 
-static int asus_hotk_check(void)
-{
-	int result = 0;
-
-	result = acpi_bus_get_status(hotk->device);
-	if (result)
-		return result;
-
-	if (hotk->device->status.present) {
-		result = asus_hotk_get_info();
-	} else {
-		pr_err("Hotkey device not present, aborting\n");
-		return -EINVAL;
-	}
-
-	return result;
-}
-
-static int asus_hotk_found;
-
-static int asus_hotk_add(struct acpi_device *device)
-{
-	int result;
-
-	pr_notice("Asus Laptop Support version %s\n",
-	       ASUS_LAPTOP_VERSION);
-
-	hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
-	if (!hotk)
-		return -ENOMEM;
-
-	hotk->handle = device->handle;
-	strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
-	device->driver_data = hotk;
-	hotk->device = device;
-
-	result = asus_hotk_check();
-	if (result)
-		goto end;
-
-	asus_hotk_add_fs();
-
-	asus_hotk_found = 1;
-
-	/* WLED and BLED are on by default */
-	if (bluetooth_status != -1)
-		write_status(bt_switch_handle, !!bluetooth_status, BT_ON);
-	if (wireless_status != -1)
-		write_status(wl_switch_handle, !!wireless_status, WL_ON);
-
-	/* If the h/w switch is off, we need to check the real status */
-	write_status(NULL, read_status(BT_ON), BT_ON);
-	write_status(NULL, read_status(WL_ON), WL_ON);
-
-	/* LCD Backlight is on by default */
-	write_status(NULL, 1, LCD_ON);
-
-	/* Keyboard Backlight is on by default */
-	if (kled_set_handle)
-		set_kled_lvl(1);
-
-	/* LED display is off by default */
-	hotk->ledd_status = 0xFFF;
-
-	/* Set initial values of light sensor and level */
-	hotk->light_switch = 0;	/* Default to light sensor disabled */
-	hotk->light_level = 5;	/* level 5 for sensor sensitivity */
-
-	if (ls_switch_handle)
-		set_light_sens_switch(hotk->light_switch);
-
-	if (ls_level_handle)
-		set_light_sens_level(hotk->light_level);
-
-	/* GPS is on by default */
-	write_status(NULL, 1, GPS_ON);
-
-end:
-	if (result) {
-		kfree(hotk->name);
-		kfree(hotk);
-	}
-
-	return result;
-}
-
-static int asus_hotk_remove(struct acpi_device *device, int type)
-{
-	kfree(hotk->name);
-	kfree(hotk);
-
-	return 0;
-}
-
 static void asus_backlight_exit(void)
 {
 	if (asus_backlight_device)
@@ -1350,18 +1261,6 @@  static void asus_input_exit(void)
 		input_unregister_device(hotk->inputdev);
 }
 
-static void __exit asus_laptop_exit(void)
-{
-	asus_backlight_exit();
-	asus_led_exit();
-	asus_input_exit();
-
-	acpi_bus_unregister_driver(&asus_hotk_driver);
-	sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
-	platform_device_unregister(asuspf_device);
-	platform_driver_unregister(&asuspf_driver);
-}
-
 static int asus_backlight_init(struct device *dev)
 {
 	struct backlight_device *bd;
@@ -1448,87 +1347,179 @@  out:
 	return rv;
 }
 
-static int __init asus_laptop_init(void)
+
+static bool asus_device_present;
+
+static int __devinit asus_acpi_init(struct acpi_device *device)
 {
-	int result;
+	int result = 0;
 
-	result = acpi_bus_register_driver(&asus_hotk_driver);
-	if (result < 0)
+	result = acpi_bus_get_status(hotk->device);
+	if (result)
 		return result;
-
-	/*
-	 * This is a bit of a kludge.  We only want this module loaded
-	 * for ASUS systems, but there's currently no way to probe the
-	 * ACPI namespace for ASUS HIDs.  So we just return failure if
-	 * we didn't find one, which will cause the module to be
-	 * unloaded.
-	 */
-	if (!asus_hotk_found) {
-		acpi_bus_unregister_driver(&asus_hotk_driver);
+	if (!hotk->device->status.present) {
+		pr_err("Hotkey device not present, aborting\n");
 		return -ENODEV;
 	}
 
-	result = asus_input_init();
+	result = asus_hotk_get_info();
 	if (result)
-		goto fail_input;
+		return result;
 
-	/* Register platform stuff */
-	result = platform_driver_register(&asuspf_driver);
-	if (result)
-		goto fail_platform_driver;
+	asus_hotk_add_fs();
 
-	asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
-	if (!asuspf_device) {
-		result = -ENOMEM;
-		goto fail_platform_device1;
-	}
+	/* WLED and BLED are on by default */
+	write_status(bt_switch_handle, 1, BT_ON);
+	write_status(wl_switch_handle, 1, WL_ON);
 
-	result = platform_device_add(asuspf_device);
-	if (result)
-		goto fail_platform_device2;
+	/* If the h/w switch is off, we need to check the real status */
+	write_status(NULL, read_status(BT_ON), BT_ON);
+	write_status(NULL, read_status(WL_ON), WL_ON);
+
+	/* LCD Backlight is on by default */
+	write_status(NULL, 1, LCD_ON);
 
-	result = sysfs_create_group(&asuspf_device->dev.kobj,
-				    &asuspf_attribute_group);
+	/* Keyboard Backlight is on by default */
+	if (kled_set_handle)
+		set_kled_lvl(1);
+
+	/* LED display is off by default */
+	hotk->ledd_status = 0xFFF;
+
+	/* Set initial values of light sensor and level */
+	hotk->light_switch = 0;	/* Default to light sensor disabled */
+	hotk->light_level = 5;	/* level 5 for sensor sensitivity */
+
+	if (ls_switch_handle)
+		set_light_sens_switch(hotk->light_switch);
+
+	if (ls_level_handle)
+		set_light_sens_level(hotk->light_level);
+
+	/* GPS is on by default */
+	write_status(NULL, 1, GPS_ON);
+	return result;
+}
+
+static int __devinit asus_acpi_add(struct acpi_device *device)
+{
+	int result;
+
+	pr_notice("Asus Laptop Support version %s\n",
+		  ASUS_LAPTOP_VERSION);
+	hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+	if (!hotk)
+		return -ENOMEM;
+	hotk->handle = device->handle;
+	strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
+	device->driver_data = hotk;
+	hotk->device = device;
+
+	result = asus_acpi_init(device);
 	if (result)
-		goto fail_sysfs;
+		goto fail_platform;
 
-	result = asus_led_init(&asuspf_device->dev);
+	/*
+	 * Register the platform device first.  It is used as a parent for the
+	 * sub-devices below.
+	 */
+	result = asus_platform_init();
 	if (result)
-		goto fail_led;
+		goto fail_platform;
 
 	if (!acpi_video_backlight_support()) {
-		result = asus_backlight_init(&asuspf_device->dev);
+		result = asus_backlight_init(&hotk->platform_device->dev);
 		if (result)
 			goto fail_backlight;
 	} else
-		pr_info("Brightness ignored, must be controlled by "
-		       "ACPI video driver\n");
+		pr_info("Backlight controlled by ACPI video driver\n");
 
+	result = asus_input_init(&hotk->platform_device->dev);
+	if (result)
+		goto fail_input;
+
+	result = asus_led_init(&hotk->platform_device->dev);
+	if (result)
+		goto fail_led;
+
+	asus_device_present = true;
 	return 0;
 
+fail_led:
+	asus_input_exit();
+fail_input:
+	asus_backlight_exit();
 fail_backlight:
-       asus_led_exit();
+	asus_platform_exit();
+fail_platform:
+	kfree(hotk->name);
+	kfree(hotk);
 
-fail_led:
-       sysfs_remove_group(&asuspf_device->dev.kobj,
-			  &asuspf_attribute_group);
+	return result;
+}
 
-fail_sysfs:
-	platform_device_del(asuspf_device);
+static int asus_acpi_remove(struct acpi_device *device, int type)
+{
+	asus_backlight_exit();
+	asus_led_exit();
+	asus_input_exit();
+	asus_platform_exit();
+
+	kfree(hotk->name);
+	kfree(hotk);
+	return 0;
+}
+
+static const struct acpi_device_id asus_device_ids[] = {
+	{"ATK0100", 0},
+	{"ATK0101", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, asus_device_ids);
 
-fail_platform_device2:
-	platform_device_put(asuspf_device);
+static struct acpi_driver asus_acpi_driver = {
+	.name = ASUS_HOTK_NAME,
+	.class = ASUS_HOTK_CLASS,
+	.owner = THIS_MODULE,
+	.ids = asus_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+	.ops = {
+		.add = asus_acpi_add,
+		.remove = asus_acpi_remove,
+		.notify = asus_acpi_notify,
+		},
+};
 
-fail_platform_device1:
-	platform_driver_unregister(&asuspf_driver);
+static int __init asus_laptop_init(void)
+{
+	int result;
 
-fail_platform_driver:
-	asus_input_exit();
+	result = platform_driver_register(&platform_driver);
+	if (result < 0)
+		return result;
 
-fail_input:
+	result = acpi_bus_register_driver(&asus_acpi_driver);
+	if (result < 0)
+		goto fail_acpi_driver;
+	if (!asus_device_present) {
+		result = -ENODEV;
+		goto fail_no_device;
+	}
+	return 0;
 
+fail_no_device:
+	acpi_bus_unregister_driver(&asus_acpi_driver);
+fail_acpi_driver:
+	platform_driver_unregister(&platform_driver);
 	return result;
 }
 
+static void __exit asus_laptop_exit(void)
+{
+	acpi_bus_unregister_driver(&asus_acpi_driver);
+	platform_driver_unregister(&platform_driver);
+}
+
 module_init(asus_laptop_init);
 module_exit(asus_laptop_exit);