aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2013-09-25 08:39:50 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-25 13:40:13 -0400
commitb5c37b798f2d29b9b2926e0abf008a13ce6c91fe (patch)
treeba31343b3f029f4c2d418c45b846480b6b1ee86f /drivers/platform
parent331e0ea243ed15bbf0958f46861505f2065e99f8 (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.c194
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 */
538static int ideapad_platform_init(struct ideapad_private *priv) 538static 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
557fail_sysfs:
558 platform_device_del(priv->platform_device);
559fail_platform_device:
560 platform_device_put(priv->platform_device);
561 return result;
562} 542}
563 543
564static void ideapad_platform_exit(struct ideapad_private *priv) 544static 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 */
784static const struct acpi_device_id ideapad_device_ids[] = {
785 { "VPC2004", 0},
786 { "", 0},
787};
788MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
789
790static void ideapad_sync_touchpad_state(struct ideapad_private *priv) 763static 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
807static int ideapad_acpi_add(struct acpi_device *adev) 780static 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
825static 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 880notification_failed:
881 ideapad_backlight_exit(priv);
852backlight_failed: 882backlight_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:
856input_failed: 886input_failed:
857 ideapad_debugfs_exit(priv); 887 ideapad_debugfs_exit(priv);
858debugfs_failed: 888debugfs_failed:
859 ideapad_platform_exit(priv); 889 ideapad_sysfs_exit(priv);
860platform_failed: 890sysfs_failed:
861 kfree(priv); 891 kfree(priv);
862 return ret; 892 return ret;
863} 893}
864 894
865static int ideapad_acpi_remove(struct acpi_device *adev) 895static 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
882static 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
929static int ideapad_acpi_resume(struct device *device) 915static 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
942static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
943#endif 927#endif
928static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
944 929
945static struct acpi_driver ideapad_acpi_driver = { 930static 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};
957module_acpi_driver(ideapad_acpi_driver); 934MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
935
936static 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
947module_platform_driver(ideapad_acpi_driver);
958 948
959MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 949MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
960MODULE_DESCRIPTION("IdeaPad ACPI Extras"); 950MODULE_DESCRIPTION("IdeaPad ACPI Extras");