aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@srcf.ucam.org>2009-03-26 08:58:12 -0400
committerLen Brown <len.brown@intel.com>2009-03-27 12:17:45 -0400
commitbadf26f00f2ed80615206d07bcfc2e3b78af5441 (patch)
tree73d0ebc2c0f8bae2f8a055ec059b8521d65b95c7 /drivers/platform/x86/sony-laptop.c
parent8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (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/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c146
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
692static 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
706static 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
812static 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 */
817static 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
838static struct sony_nc_event sony_C_events[] = { 837static 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 */
855static 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 */
898static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 856static 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 */
918static 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
956static int sony_nc_resume(struct acpi_device *device) 933static 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;