diff options
author | Zhang Rui <rui.zhang@intel.com> | 2013-09-25 08:39:50 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-25 13:40:13 -0400 |
commit | b5c37b798f2d29b9b2926e0abf008a13ce6c91fe (patch) | |
tree | ba31343b3f029f4c2d418c45b846480b6b1ee86f /drivers/platform | |
parent | 331e0ea243ed15bbf0958f46861505f2065e99f8 (diff) |
ideapad_laptop: convert ideapad device/driver to platform bus
This patch does two things,
1. enumerate the ideapad device node to platform bus.
2. convert the current driver from ACPI bus to platform bus.
Note, with this patch, the platform device node created by ACPI,
with the name VPC2004:00, is used as the parent device of
the input, backlight, rfkill sysfs class device.
Plus the ideapad_platform private sysfs attributes,
i.e. camera_power and fan_mode, are also moved to the new
platform device node.
The previous platform device node "ideapad" is removed.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
CC: Matthew Garrett <matthew.garrett@nebula.com>
CC: Ike Panhc <ike.pan@canonical.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 194 |
1 files changed, 92 insertions, 102 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index cad48b5cc409..6788acc22ab9 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -500,7 +500,7 @@ static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) | |||
500 | priv->rfk_priv[dev].priv = priv; | 500 | priv->rfk_priv[dev].priv = priv; |
501 | 501 | ||
502 | priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, | 502 | priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, |
503 | &priv->adev->dev, | 503 | &priv->platform_device->dev, |
504 | ideapad_rfk_data[dev].type, | 504 | ideapad_rfk_data[dev].type, |
505 | &ideapad_rfk_ops, | 505 | &ideapad_rfk_ops, |
506 | &priv->rfk_priv[dev]); | 506 | &priv->rfk_priv[dev]); |
@@ -535,37 +535,16 @@ static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) | |||
535 | /* | 535 | /* |
536 | * Platform device | 536 | * Platform device |
537 | */ | 537 | */ |
538 | static int ideapad_platform_init(struct ideapad_private *priv) | 538 | static int ideapad_sysfs_init(struct ideapad_private *priv) |
539 | { | 539 | { |
540 | int result; | 540 | return sysfs_create_group(&priv->platform_device->dev.kobj, |
541 | |||
542 | priv->platform_device = platform_device_alloc("ideapad", -1); | ||
543 | if (!priv->platform_device) | ||
544 | return -ENOMEM; | ||
545 | platform_set_drvdata(priv->platform_device, priv); | ||
546 | |||
547 | result = platform_device_add(priv->platform_device); | ||
548 | if (result) | ||
549 | goto fail_platform_device; | ||
550 | |||
551 | result = sysfs_create_group(&priv->platform_device->dev.kobj, | ||
552 | &ideapad_attribute_group); | 541 | &ideapad_attribute_group); |
553 | if (result) | ||
554 | goto fail_sysfs; | ||
555 | return 0; | ||
556 | |||
557 | fail_sysfs: | ||
558 | platform_device_del(priv->platform_device); | ||
559 | fail_platform_device: | ||
560 | platform_device_put(priv->platform_device); | ||
561 | return result; | ||
562 | } | 542 | } |
563 | 543 | ||
564 | static void ideapad_platform_exit(struct ideapad_private *priv) | 544 | static void ideapad_sysfs_exit(struct ideapad_private *priv) |
565 | { | 545 | { |
566 | sysfs_remove_group(&priv->platform_device->dev.kobj, | 546 | sysfs_remove_group(&priv->platform_device->dev.kobj, |
567 | &ideapad_attribute_group); | 547 | &ideapad_attribute_group); |
568 | platform_device_unregister(priv->platform_device); | ||
569 | } | 548 | } |
570 | 549 | ||
571 | /* | 550 | /* |
@@ -781,12 +760,6 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) | |||
781 | /* | 760 | /* |
782 | * module init/exit | 761 | * module init/exit |
783 | */ | 762 | */ |
784 | static const struct acpi_device_id ideapad_device_ids[] = { | ||
785 | { "VPC2004", 0}, | ||
786 | { "", 0}, | ||
787 | }; | ||
788 | MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); | ||
789 | |||
790 | static void ideapad_sync_touchpad_state(struct ideapad_private *priv) | 763 | static void ideapad_sync_touchpad_state(struct ideapad_private *priv) |
791 | { | 764 | { |
792 | unsigned long value; | 765 | unsigned long value; |
@@ -804,11 +777,61 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) | |||
804 | } | 777 | } |
805 | } | 778 | } |
806 | 779 | ||
807 | static int ideapad_acpi_add(struct acpi_device *adev) | 780 | static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) |
781 | { | ||
782 | struct ideapad_private *priv = data; | ||
783 | unsigned long vpc1, vpc2, vpc_bit; | ||
784 | |||
785 | if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) | ||
786 | return; | ||
787 | if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) | ||
788 | return; | ||
789 | |||
790 | vpc1 = (vpc2 << 8) | vpc1; | ||
791 | for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) { | ||
792 | if (test_bit(vpc_bit, &vpc1)) { | ||
793 | switch (vpc_bit) { | ||
794 | case 9: | ||
795 | ideapad_sync_rfk_state(priv); | ||
796 | break; | ||
797 | case 13: | ||
798 | case 11: | ||
799 | case 7: | ||
800 | case 6: | ||
801 | ideapad_input_report(priv, vpc_bit); | ||
802 | break; | ||
803 | case 5: | ||
804 | ideapad_sync_touchpad_state(priv); | ||
805 | break; | ||
806 | case 4: | ||
807 | ideapad_backlight_notify_brightness(priv); | ||
808 | break; | ||
809 | case 3: | ||
810 | ideapad_input_novokey(priv); | ||
811 | break; | ||
812 | case 2: | ||
813 | ideapad_backlight_notify_power(priv); | ||
814 | break; | ||
815 | case 0: | ||
816 | ideapad_check_special_buttons(priv); | ||
817 | break; | ||
818 | default: | ||
819 | pr_info("Unknown event: %lu\n", vpc_bit); | ||
820 | } | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | |||
825 | static int ideapad_acpi_add(struct platform_device *pdev) | ||
808 | { | 826 | { |
809 | int ret, i; | 827 | int ret, i; |
810 | int cfg; | 828 | int cfg; |
811 | struct ideapad_private *priv; | 829 | struct ideapad_private *priv; |
830 | struct acpi_device *adev; | ||
831 | |||
832 | ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); | ||
833 | if (ret) | ||
834 | return -ENODEV; | ||
812 | 835 | ||
813 | if (read_method_int(adev->handle, "_CFG", &cfg)) | 836 | if (read_method_int(adev->handle, "_CFG", &cfg)) |
814 | return -ENODEV; | 837 | return -ENODEV; |
@@ -816,13 +839,15 @@ static int ideapad_acpi_add(struct acpi_device *adev) | |||
816 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 839 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
817 | if (!priv) | 840 | if (!priv) |
818 | return -ENOMEM; | 841 | return -ENOMEM; |
819 | dev_set_drvdata(&adev->dev, priv); | 842 | |
843 | dev_set_drvdata(&pdev->dev, priv); | ||
820 | priv->cfg = cfg; | 844 | priv->cfg = cfg; |
821 | priv->adev = adev; | 845 | priv->adev = adev; |
846 | priv->platform_device = pdev; | ||
822 | 847 | ||
823 | ret = ideapad_platform_init(priv); | 848 | ret = ideapad_sysfs_init(priv); |
824 | if (ret) | 849 | if (ret) |
825 | goto platform_failed; | 850 | goto sysfs_failed; |
826 | 851 | ||
827 | ret = ideapad_debugfs_init(priv); | 852 | ret = ideapad_debugfs_init(priv); |
828 | if (ret) | 853 | if (ret) |
@@ -846,9 +871,14 @@ static int ideapad_acpi_add(struct acpi_device *adev) | |||
846 | if (ret && ret != -ENODEV) | 871 | if (ret && ret != -ENODEV) |
847 | goto backlight_failed; | 872 | goto backlight_failed; |
848 | } | 873 | } |
874 | ret = acpi_install_notify_handler(adev->handle, | ||
875 | ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv); | ||
876 | if (ret) | ||
877 | goto notification_failed; | ||
849 | 878 | ||
850 | return 0; | 879 | return 0; |
851 | 880 | notification_failed: | |
881 | ideapad_backlight_exit(priv); | ||
852 | backlight_failed: | 882 | backlight_failed: |
853 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 883 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
854 | ideapad_unregister_rfkill(priv, i); | 884 | ideapad_unregister_rfkill(priv, i); |
@@ -856,75 +886,31 @@ backlight_failed: | |||
856 | input_failed: | 886 | input_failed: |
857 | ideapad_debugfs_exit(priv); | 887 | ideapad_debugfs_exit(priv); |
858 | debugfs_failed: | 888 | debugfs_failed: |
859 | ideapad_platform_exit(priv); | 889 | ideapad_sysfs_exit(priv); |
860 | platform_failed: | 890 | sysfs_failed: |
861 | kfree(priv); | 891 | kfree(priv); |
862 | return ret; | 892 | return ret; |
863 | } | 893 | } |
864 | 894 | ||
865 | static int ideapad_acpi_remove(struct acpi_device *adev) | 895 | static int ideapad_acpi_remove(struct platform_device *pdev) |
866 | { | 896 | { |
867 | struct ideapad_private *priv = dev_get_drvdata(&adev->dev); | 897 | struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); |
868 | int i; | 898 | int i; |
869 | 899 | ||
900 | acpi_remove_notify_handler(priv->adev->handle, | ||
901 | ACPI_DEVICE_NOTIFY, ideapad_acpi_notify); | ||
870 | ideapad_backlight_exit(priv); | 902 | ideapad_backlight_exit(priv); |
871 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 903 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
872 | ideapad_unregister_rfkill(priv, i); | 904 | ideapad_unregister_rfkill(priv, i); |
873 | ideapad_input_exit(priv); | 905 | ideapad_input_exit(priv); |
874 | ideapad_debugfs_exit(priv); | 906 | ideapad_debugfs_exit(priv); |
875 | ideapad_platform_exit(priv); | 907 | ideapad_sysfs_exit(priv); |
876 | dev_set_drvdata(&adev->dev, NULL); | 908 | dev_set_drvdata(&pdev->dev, NULL); |
877 | kfree(priv); | 909 | kfree(priv); |
878 | 910 | ||
879 | return 0; | 911 | return 0; |
880 | } | 912 | } |
881 | 913 | ||
882 | static void ideapad_acpi_notify(struct acpi_device *adev, u32 event) | ||
883 | { | ||
884 | struct ideapad_private *priv = dev_get_drvdata(&adev->dev); | ||
885 | acpi_handle handle = adev->handle; | ||
886 | unsigned long vpc1, vpc2, vpc_bit; | ||
887 | |||
888 | if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) | ||
889 | return; | ||
890 | if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) | ||
891 | return; | ||
892 | |||
893 | vpc1 = (vpc2 << 8) | vpc1; | ||
894 | for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) { | ||
895 | if (test_bit(vpc_bit, &vpc1)) { | ||
896 | switch (vpc_bit) { | ||
897 | case 9: | ||
898 | ideapad_sync_rfk_state(priv); | ||
899 | break; | ||
900 | case 13: | ||
901 | case 11: | ||
902 | case 7: | ||
903 | case 6: | ||
904 | ideapad_input_report(priv, vpc_bit); | ||
905 | break; | ||
906 | case 5: | ||
907 | ideapad_sync_touchpad_state(priv); | ||
908 | break; | ||
909 | case 4: | ||
910 | ideapad_backlight_notify_brightness(priv); | ||
911 | break; | ||
912 | case 3: | ||
913 | ideapad_input_novokey(priv); | ||
914 | break; | ||
915 | case 2: | ||
916 | ideapad_backlight_notify_power(priv); | ||
917 | break; | ||
918 | case 0: | ||
919 | ideapad_check_special_buttons(priv); | ||
920 | break; | ||
921 | default: | ||
922 | pr_info("Unknown event: %lu\n", vpc_bit); | ||
923 | } | ||
924 | } | ||
925 | } | ||
926 | } | ||
927 | |||
928 | #ifdef CONFIG_PM_SLEEP | 914 | #ifdef CONFIG_PM_SLEEP |
929 | static int ideapad_acpi_resume(struct device *device) | 915 | static int ideapad_acpi_resume(struct device *device) |
930 | { | 916 | { |
@@ -938,23 +924,27 @@ static int ideapad_acpi_resume(struct device *device) | |||
938 | ideapad_sync_touchpad_state(priv); | 924 | ideapad_sync_touchpad_state(priv); |
939 | return 0; | 925 | return 0; |
940 | } | 926 | } |
941 | |||
942 | static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); | ||
943 | #endif | 927 | #endif |
928 | static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); | ||
944 | 929 | ||
945 | static struct acpi_driver ideapad_acpi_driver = { | 930 | static const struct acpi_device_id ideapad_device_ids[] = { |
946 | .name = "ideapad_acpi", | 931 | { "VPC2004", 0}, |
947 | .class = "IdeaPad", | 932 | { "", 0}, |
948 | .ids = ideapad_device_ids, | ||
949 | .ops.add = ideapad_acpi_add, | ||
950 | .ops.remove = ideapad_acpi_remove, | ||
951 | .ops.notify = ideapad_acpi_notify, | ||
952 | #ifdef CONFIG_PM_SLEEP | ||
953 | .drv.pm = &ideapad_pm, | ||
954 | #endif | ||
955 | .owner = THIS_MODULE, | ||
956 | }; | 933 | }; |
957 | module_acpi_driver(ideapad_acpi_driver); | 934 | MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); |
935 | |||
936 | static struct platform_driver ideapad_acpi_driver = { | ||
937 | .probe = ideapad_acpi_add, | ||
938 | .remove = ideapad_acpi_remove, | ||
939 | .driver = { | ||
940 | .name = "ideapad_acpi", | ||
941 | .owner = THIS_MODULE, | ||
942 | .pm = &ideapad_pm, | ||
943 | .acpi_match_table = ACPI_PTR(ideapad_device_ids), | ||
944 | }, | ||
945 | }; | ||
946 | |||
947 | module_platform_driver(ideapad_acpi_driver); | ||
958 | 948 | ||
959 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 949 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
960 | MODULE_DESCRIPTION("IdeaPad ACPI Extras"); | 950 | MODULE_DESCRIPTION("IdeaPad ACPI Extras"); |