aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorMattia Dongili <malattia@linux.it>2007-07-15 13:34:35 -0400
committerLen Brown <len.brown@intel.com>2007-07-22 00:34:58 -0400
commit6315fd1c9cd6870a253699f07c5ada85cfe8fecb (patch)
treeb6d01a07e42a023c73aa32d77a49a1c0b45d7753 /drivers/misc
parent8538c3686c895f9334a3c22997b51b5a82de7550 (diff)
sony-laptop: Add support for recent Vaios Fn keys (C series for now)
Recent Vaios (C, AR, N, FE) need some special initialization sequence to enable Fn keys interrupts through the Embedded Controller. Moreover Fn keys have to be decoded internally using ACPI methods to get the key code. Thus a new DMI table to add SNC init time callbacks and new mappings for model-specific key code to generic sony-laptop code have been added. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
-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;