diff options
author | Matthew Garrett <mjg59@srcf.ucam.org> | 2009-03-26 08:58:12 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-27 12:17:45 -0400 |
commit | badf26f00f2ed80615206d07bcfc2e3b78af5441 (patch) | |
tree | 73d0ebc2c0f8bae2f8a055ec059b8521d65b95c7 /drivers | |
parent | 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff) |
sony-laptop: Add support for new Sony platform API
Newer Sony Vaios provide a new API for accessing platform functionality. It
consists of a set of standardised methods for enabling events and performing
queries. These are each identified by a unique handle. This patch adds
support for calling functions based on their handle and ports the existing
code for these machines over to it.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 146 |
1 files changed, 65 insertions, 81 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 537959d07148..3c52ec9548ab 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -689,6 +689,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, | |||
689 | return -1; | 689 | return -1; |
690 | } | 690 | } |
691 | 691 | ||
692 | static int sony_find_snc_handle(int handle) | ||
693 | { | ||
694 | int i; | ||
695 | int result; | ||
696 | |||
697 | for (i = 0x20; i < 0x30; i++) { | ||
698 | acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); | ||
699 | if (result == handle) | ||
700 | return i-0x20; | ||
701 | } | ||
702 | |||
703 | return -1; | ||
704 | } | ||
705 | |||
706 | static int sony_call_snc_handle(int handle, int argument, int *result) | ||
707 | { | ||
708 | int offset = sony_find_snc_handle(handle); | ||
709 | |||
710 | if (offset < 0) | ||
711 | return -1; | ||
712 | |||
713 | return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, | ||
714 | result); | ||
715 | } | ||
716 | |||
692 | /* | 717 | /* |
693 | * sony_nc_values input/output validate functions | 718 | * sony_nc_values input/output validate functions |
694 | */ | 719 | */ |
@@ -809,32 +834,6 @@ struct sony_nc_event { | |||
809 | u8 event; | 834 | u8 event; |
810 | }; | 835 | }; |
811 | 836 | ||
812 | static struct sony_nc_event *sony_nc_events; | ||
813 | |||
814 | /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence | ||
815 | * for Fn keys | ||
816 | */ | ||
817 | static int sony_nc_C_enable(const struct dmi_system_id *id) | ||
818 | { | ||
819 | int result = 0; | ||
820 | |||
821 | printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); | ||
822 | |||
823 | sony_nc_events = id->driver_data; | ||
824 | |||
825 | if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 | ||
826 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 | ||
827 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 | ||
828 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 | ||
829 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 | ||
830 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { | ||
831 | printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " | ||
832 | "functionalities may be missing\n"); | ||
833 | return 1; | ||
834 | } | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static struct sony_nc_event sony_C_events[] = { | 837 | static struct sony_nc_event sony_C_events[] = { |
839 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, | 838 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, |
840 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, | 839 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, |
@@ -851,57 +850,17 @@ static struct sony_nc_event sony_C_events[] = { | |||
851 | { 0, 0 }, | 850 | { 0, 0 }, |
852 | }; | 851 | }; |
853 | 852 | ||
854 | /* SNC-only model map */ | ||
855 | static const struct dmi_system_id sony_nc_ids[] = { | ||
856 | { | ||
857 | .ident = "Sony Vaio FE Series", | ||
858 | .callback = sony_nc_C_enable, | ||
859 | .driver_data = sony_C_events, | ||
860 | .matches = { | ||
861 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
862 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), | ||
863 | }, | ||
864 | }, | ||
865 | { | ||
866 | .ident = "Sony Vaio FZ Series", | ||
867 | .callback = sony_nc_C_enable, | ||
868 | .driver_data = sony_C_events, | ||
869 | .matches = { | ||
870 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
871 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), | ||
872 | }, | ||
873 | }, | ||
874 | { | ||
875 | .ident = "Sony Vaio C Series", | ||
876 | .callback = sony_nc_C_enable, | ||
877 | .driver_data = sony_C_events, | ||
878 | .matches = { | ||
879 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
880 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | ||
881 | }, | ||
882 | }, | ||
883 | { | ||
884 | .ident = "Sony Vaio N Series", | ||
885 | .callback = sony_nc_C_enable, | ||
886 | .driver_data = sony_C_events, | ||
887 | .matches = { | ||
888 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
889 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), | ||
890 | }, | ||
891 | }, | ||
892 | { } | ||
893 | }; | ||
894 | |||
895 | /* | 853 | /* |
896 | * ACPI callbacks | 854 | * ACPI callbacks |
897 | */ | 855 | */ |
898 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | 856 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) |
899 | { | 857 | { |
900 | struct sony_nc_event *evmap; | 858 | int i; |
901 | u32 ev = event; | 859 | u32 ev = event; |
902 | int result; | 860 | int result; |
903 | 861 | ||
904 | if (ev == 0x92) { | 862 | if (ev == 0x92 || ev == 0x90) { |
863 | int origev = ev; | ||
905 | /* read the key pressed from EC.GECR | 864 | /* read the key pressed from EC.GECR |
906 | * A call to SN07 with 0x0202 will do it as well respecting | 865 | * A call to SN07 with 0x0202 will do it as well respecting |
907 | * the current protocol on different OSes | 866 | * the current protocol on different OSes |
@@ -913,20 +872,23 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | |||
913 | * TODO: we may want to do the same for the older GHKE -need | 872 | * TODO: we may want to do the same for the older GHKE -need |
914 | * dmi list- so this snippet may become one more callback. | 873 | * dmi list- so this snippet may become one more callback. |
915 | */ | 874 | */ |
916 | if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) | 875 | if (sony_call_snc_handle(0x100, 0x200, &result)) |
917 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); | 876 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); |
918 | else | 877 | else |
919 | ev = result & 0xFF; | 878 | ev = result & 0xFF; |
920 | } | ||
921 | 879 | ||
922 | if (sony_nc_events) | 880 | for (i = 0; sony_C_events[i].data; i++) { |
923 | for (evmap = sony_nc_events; evmap->event; evmap++) { | 881 | if (sony_C_events[i].data == ev) { |
924 | if (evmap->data == ev) { | 882 | ev = sony_C_events[i].event; |
925 | ev = evmap->event; | ||
926 | break; | 883 | break; |
927 | } | 884 | } |
928 | } | 885 | } |
929 | 886 | ||
887 | if (!sony_C_events[i].data) | ||
888 | printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n", | ||
889 | origev, ev); | ||
890 | } | ||
891 | |||
930 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); | 892 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); |
931 | sony_laptop_report_input_event(ev); | 893 | sony_laptop_report_input_event(ev); |
932 | acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); | 894 | acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); |
@@ -953,9 +915,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | |||
953 | /* | 915 | /* |
954 | * ACPI device | 916 | * ACPI device |
955 | */ | 917 | */ |
918 | static int sony_nc_function_setup(struct acpi_device *device) | ||
919 | { | ||
920 | int result; | ||
921 | |||
922 | /* Enable all events */ | ||
923 | acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); | ||
924 | |||
925 | /* Setup hotkeys */ | ||
926 | sony_call_snc_handle(0x0100, 0, &result); | ||
927 | sony_call_snc_handle(0x0101, 0, &result); | ||
928 | sony_call_snc_handle(0x0102, 0x100, &result); | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
956 | static int sony_nc_resume(struct acpi_device *device) | 933 | static int sony_nc_resume(struct acpi_device *device) |
957 | { | 934 | { |
958 | struct sony_nc_value *item; | 935 | struct sony_nc_value *item; |
936 | acpi_handle handle; | ||
959 | 937 | ||
960 | for (item = sony_nc_values; item->name; item++) { | 938 | for (item = sony_nc_values; item->name; item++) { |
961 | int ret; | 939 | int ret; |
@@ -970,14 +948,17 @@ static int sony_nc_resume(struct acpi_device *device) | |||
970 | } | 948 | } |
971 | } | 949 | } |
972 | 950 | ||
951 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", | ||
952 | &handle))) { | ||
953 | dprintk("Doing SNC setup\n"); | ||
954 | sony_nc_function_setup(device); | ||
955 | } | ||
956 | |||
973 | /* set the last requested brightness level */ | 957 | /* set the last requested brightness level */ |
974 | if (sony_backlight_device && | 958 | if (sony_backlight_device && |
975 | !sony_backlight_update_status(sony_backlight_device)) | 959 | !sony_backlight_update_status(sony_backlight_device)) |
976 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); | 960 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); |
977 | 961 | ||
978 | /* re-initialize models with specific requirements */ | ||
979 | dmi_check_system(sony_nc_ids); | ||
980 | |||
981 | return 0; | 962 | return 0; |
982 | } | 963 | } |
983 | 964 | ||
@@ -1024,6 +1005,12 @@ static int sony_nc_add(struct acpi_device *device) | |||
1024 | dprintk("_INI Method failed\n"); | 1005 | dprintk("_INI Method failed\n"); |
1025 | } | 1006 | } |
1026 | 1007 | ||
1008 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", | ||
1009 | &handle))) { | ||
1010 | dprintk("Doing SNC setup\n"); | ||
1011 | sony_nc_function_setup(device); | ||
1012 | } | ||
1013 | |||
1027 | /* setup input devices and helper fifo */ | 1014 | /* setup input devices and helper fifo */ |
1028 | result = sony_laptop_setup_input(device); | 1015 | result = sony_laptop_setup_input(device); |
1029 | if (result) { | 1016 | if (result) { |
@@ -1063,9 +1050,6 @@ static int sony_nc_add(struct acpi_device *device) | |||
1063 | 1050 | ||
1064 | } | 1051 | } |
1065 | 1052 | ||
1066 | /* initialize models with specific requirements */ | ||
1067 | dmi_check_system(sony_nc_ids); | ||
1068 | |||
1069 | result = sony_pf_add(); | 1053 | result = sony_pf_add(); |
1070 | if (result) | 1054 | if (result) |
1071 | goto outbacklight; | 1055 | goto outbacklight; |