Commit badf26f0 authored by Matthew Garrett's avatar Matthew Garrett Committed by Len Brown

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: default avatarMatthew Garrett <mjg@redhat.com>
Signed-off-by: default avatarMattia Dongili <malattia@linux.it>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 8e0ee43b
...@@ -689,6 +689,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, ...@@ -689,6 +689,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
return -1; return -1;
} }
static int sony_find_snc_handle(int handle)
{
int i;
int result;
for (i = 0x20; i < 0x30; i++) {
acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
if (result == handle)
return i-0x20;
}
return -1;
}
static int sony_call_snc_handle(int handle, int argument, int *result)
{
int offset = sony_find_snc_handle(handle);
if (offset < 0)
return -1;
return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
result);
}
/* /*
* sony_nc_values input/output validate functions * sony_nc_values input/output validate functions
*/ */
...@@ -809,32 +834,6 @@ struct sony_nc_event { ...@@ -809,32 +834,6 @@ struct sony_nc_event {
u8 event; u8 event;
}; };
static struct sony_nc_event *sony_nc_events;
/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence
* for Fn keys
*/
static int sony_nc_C_enable(const struct dmi_system_id *id)
{
int result = 0;
printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident);
sony_nc_events = id->driver_data;
if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0
|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0
|| acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0
|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0
|| acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0
|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) {
printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some "
"functionalities may be missing\n");
return 1;
}
return 0;
}
static struct sony_nc_event sony_C_events[] = { static struct sony_nc_event sony_C_events[] = {
{ 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x81, SONYPI_EVENT_FNKEY_F1 },
{ 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
...@@ -851,57 +850,17 @@ static struct sony_nc_event sony_C_events[] = { ...@@ -851,57 +850,17 @@ static struct sony_nc_event sony_C_events[] = {
{ 0, 0 }, { 0, 0 },
}; };
/* SNC-only model map */
static const struct dmi_system_id sony_nc_ids[] = {
{
.ident = "Sony Vaio FE Series",
.callback = sony_nc_C_enable,
.driver_data = sony_C_events,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"),
},
},
{
.ident = "Sony Vaio FZ Series",
.callback = sony_nc_C_enable,
.driver_data = sony_C_events,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"),
},
},
{
.ident = "Sony Vaio C Series",
.callback = sony_nc_C_enable,
.driver_data = sony_C_events,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"),
},
},
{
.ident = "Sony Vaio N Series",
.callback = sony_nc_C_enable,
.driver_data = sony_C_events,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"),
},
},
{ }
};
/* /*
* ACPI callbacks * ACPI callbacks
*/ */
static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
{ {
struct sony_nc_event *evmap; int i;
u32 ev = event; u32 ev = event;
int result; int result;
if (ev == 0x92) { if (ev == 0x92 || ev == 0x90) {
int origev = ev;
/* read the key pressed from EC.GECR /* read the key pressed from EC.GECR
* A call to SN07 with 0x0202 will do it as well respecting * A call to SN07 with 0x0202 will do it as well respecting
* the current protocol on different OSes * the current protocol on different OSes
...@@ -913,20 +872,23 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) ...@@ -913,20 +872,23 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
* TODO: we may want to do the same for the older GHKE -need * TODO: we may want to do the same for the older GHKE -need
* dmi list- so this snippet may become one more callback. * dmi list- so this snippet may become one more callback.
*/ */
if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) if (sony_call_snc_handle(0x100, 0x200, &result))
dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev);
else else
ev = result & 0xFF; ev = result & 0xFF;
}
if (sony_nc_events) for (i = 0; sony_C_events[i].data; i++) {
for (evmap = sony_nc_events; evmap->event; evmap++) { if (sony_C_events[i].data == ev) {
if (evmap->data == ev) { ev = sony_C_events[i].event;
ev = evmap->event;
break; break;
} }
} }
if (!sony_C_events[i].data)
printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n",
origev, ev);
}
dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
sony_laptop_report_input_event(ev); sony_laptop_report_input_event(ev);
acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); 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,9 +915,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
/* /*
* ACPI device * ACPI device
*/ */
static int sony_nc_function_setup(struct acpi_device *device)
{
int result;
/* Enable all events */
acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
/* Setup hotkeys */
sony_call_snc_handle(0x0100, 0, &result);
sony_call_snc_handle(0x0101, 0, &result);
sony_call_snc_handle(0x0102, 0x100, &result);
return 0;
}
static int sony_nc_resume(struct acpi_device *device) static int sony_nc_resume(struct acpi_device *device)
{ {
struct sony_nc_value *item; struct sony_nc_value *item;
acpi_handle handle;
for (item = sony_nc_values; item->name; item++) { for (item = sony_nc_values; item->name; item++) {
int ret; int ret;
...@@ -970,14 +948,17 @@ static int sony_nc_resume(struct acpi_device *device) ...@@ -970,14 +948,17 @@ static int sony_nc_resume(struct acpi_device *device)
} }
} }
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
&handle))) {
dprintk("Doing SNC setup\n");
sony_nc_function_setup(device);
}
/* set the last requested brightness level */ /* set the last requested brightness level */
if (sony_backlight_device && if (sony_backlight_device &&
!sony_backlight_update_status(sony_backlight_device)) !sony_backlight_update_status(sony_backlight_device))
printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
/* re-initialize models with specific requirements */
dmi_check_system(sony_nc_ids);
return 0; return 0;
} }
...@@ -1024,6 +1005,12 @@ static int sony_nc_add(struct acpi_device *device) ...@@ -1024,6 +1005,12 @@ static int sony_nc_add(struct acpi_device *device)
dprintk("_INI Method failed\n"); dprintk("_INI Method failed\n");
} }
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
&handle))) {
dprintk("Doing SNC setup\n");
sony_nc_function_setup(device);
}
/* setup input devices and helper fifo */ /* setup input devices and helper fifo */
result = sony_laptop_setup_input(device); result = sony_laptop_setup_input(device);
if (result) { if (result) {
...@@ -1063,9 +1050,6 @@ static int sony_nc_add(struct acpi_device *device) ...@@ -1063,9 +1050,6 @@ static int sony_nc_add(struct acpi_device *device)
} }
/* initialize models with specific requirements */
dmi_check_system(sony_nc_ids);
result = sony_pf_add(); result = sony_pf_add();
if (result) if (result)
goto outbacklight; goto outbacklight;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment