aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/sony-laptop.c107
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 */
710struct sony_nc_event {
711 u8 data;
712 u8 event;
713};
714
715static 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 */
720static 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
741static 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 */
758struct 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 */
710static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 774static 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
717static acpi_status sony_walk_callback(acpi_handle handle, u32 level, 811static 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;