Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+65 −81
Original line number Original line Diff line number Diff line
@@ -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 {
	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[] = {
	{ 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)
		 * 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,
/*
/*
 * 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)
		}
		}
	}
	}


	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)
			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)


	}
	}


	/* 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;