diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/sony-laptop.c | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 142d660b46c8..43315be3dc11 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -705,13 +705,107 @@ static struct backlight_ops sony_backlight_ops = { | |||
705 | }; | 705 | }; |
706 | 706 | ||
707 | /* | 707 | /* |
708 | * New SNC-only Vaios event mapping to driver known keys | ||
709 | */ | ||
710 | struct sony_nc_event { | ||
711 | u8 data; | ||
712 | u8 event; | ||
713 | }; | ||
714 | |||
715 | static struct sony_nc_event *sony_nc_events; | ||
716 | |||
717 | /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence | ||
718 | * for Fn keys | ||
719 | */ | ||
720 | static int sony_nc_C_enable(struct dmi_system_id *id) | ||
721 | { | ||
722 | int result = 0; | ||
723 | |||
724 | printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); | ||
725 | |||
726 | sony_nc_events = id->driver_data; | ||
727 | |||
728 | if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 | ||
729 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 | ||
730 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 | ||
731 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 | ||
732 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 | ||
733 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { | ||
734 | printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " | ||
735 | "functionalities may be missing\n"); | ||
736 | return 1; | ||
737 | } | ||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static struct sony_nc_event sony_C_events[] = { | ||
742 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, | ||
743 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, | ||
744 | { 0x85, SONYPI_EVENT_FNKEY_F5 }, | ||
745 | { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, | ||
746 | { 0x86, SONYPI_EVENT_FNKEY_F6 }, | ||
747 | { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, | ||
748 | { 0x87, SONYPI_EVENT_FNKEY_F7 }, | ||
749 | { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, | ||
750 | { 0x8A, SONYPI_EVENT_FNKEY_F10 }, | ||
751 | { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, | ||
752 | { 0x8C, SONYPI_EVENT_FNKEY_F12 }, | ||
753 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | ||
754 | { 0, 0 }, | ||
755 | }; | ||
756 | |||
757 | /* SNC-only model map */ | ||
758 | struct dmi_system_id sony_nc_ids[] = { | ||
759 | { | ||
760 | .ident = "Sony Vaio C Series", | ||
761 | .callback = sony_nc_C_enable, | ||
762 | .driver_data = sony_C_events, | ||
763 | .matches = { | ||
764 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
765 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | ||
766 | }, | ||
767 | }, | ||
768 | { } | ||
769 | }; | ||
770 | |||
771 | /* | ||
708 | * ACPI callbacks | 772 | * ACPI callbacks |
709 | */ | 773 | */ |
710 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | 774 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) |
711 | { | 775 | { |
712 | dprintk("sony_acpi_notify, event: %d\n", event); | 776 | struct sony_nc_event *evmap; |
713 | sony_laptop_report_input_event(event); | 777 | u32 ev = event; |
714 | acpi_bus_generate_event(sony_nc_acpi_device, 1, event); | 778 | int result; |
779 | |||
780 | if (ev == 0x92) { | ||
781 | /* read the key pressed from EC.GECR | ||
782 | * A call to SN07 with 0x0202 will do it as well respecting | ||
783 | * the current protocol on different OSes | ||
784 | * | ||
785 | * Note: the path for GECR may be | ||
786 | * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) | ||
787 | * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) | ||
788 | * | ||
789 | * TODO: we may want to do the same for the older GHKE -need | ||
790 | * dmi list- so this snippet may become one more callback. | ||
791 | */ | ||
792 | if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) | ||
793 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); | ||
794 | else | ||
795 | ev = result & 0xFF; | ||
796 | } | ||
797 | |||
798 | if (sony_nc_events) | ||
799 | for (evmap = sony_nc_events; evmap->event; evmap++) { | ||
800 | if (evmap->data == ev) { | ||
801 | ev = evmap->event; | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); | ||
807 | sony_laptop_report_input_event(ev); | ||
808 | acpi_bus_generate_event(sony_nc_acpi_device, 1, ev); | ||
715 | } | 809 | } |
716 | 810 | ||
717 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | 811 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, |
@@ -748,6 +842,10 @@ static int sony_nc_resume(struct acpi_device *device) | |||
748 | break; | 842 | break; |
749 | } | 843 | } |
750 | } | 844 | } |
845 | |||
846 | /* re-initialize models with specific requirements */ | ||
847 | dmi_check_system(sony_nc_ids); | ||
848 | |||
751 | return 0; | 849 | return 0; |
752 | } | 850 | } |
753 | 851 | ||
@@ -811,6 +909,9 @@ static int sony_nc_add(struct acpi_device *device) | |||
811 | 909 | ||
812 | } | 910 | } |
813 | 911 | ||
912 | /* initialize models with specific requirements */ | ||
913 | dmi_check_system(sony_nc_ids); | ||
914 | |||
814 | result = sony_pf_add(); | 915 | result = sony_pf_add(); |
815 | if (result) | 916 | if (result) |
816 | goto outbacklight; | 917 | goto outbacklight; |