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

Commit 91e67a99 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86

* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (45 commits)
  acer-wmi: replaced the hard coded bitmap by the communication devices bitmap from SMBIOS
  acer-wmi: check the existence of internal wireless device when set capability
  acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks
  sony-laptop:irq: Remove IRQF_DISABLED
  asus-laptop: Add rfkill support for Pegatron Lucid tablet
  asus-laptop: pega_accel - Report accelerometer orientation change through udev
  asus-laptop: fix module description
  asus-laptop: hide leds on Pegatron Lucid
  asus-laptop: Pegatron Lucid accelerometer
  asus-laptop: allow boot time control of Pegatron ALS sensor
  Platform: samsung_laptop: add support for X520 machines.
  platform: samsung_laptop: add dmi information for Samsung R700 laptops
  hp_accel: Add axis-mapping for HP ProBook / EliteBook
  hp_accel: Add a new PNP id
  WMI: properly cleanup devices to avoid crashes
  ideapad: remove sysfs node for cfg
  ideapad: add debugfs support
  ideapad: add event for Novo key
  ideapad: change parameter of ideapad_sync_rfk_state
  ideapad: define vpc commands
  ...
parents 1eb63378 1d1fc8a7
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
What:		/sys/kernel/debug/ideapad/cfg
Date:		Sep 2011
KernelVersion:	3.2
Contact:	Ike Panhc <ike.pan@canonical.com>
Description:

cfg shows the return value of _CFG method in VPC2004 device. It tells machine
capability and what graphic component within the machine.


What:		/sys/kernel/debug/ideapad/status
Date:		Sep 2011
KernelVersion:	3.2
Contact:	Ike Panhc <ike.pan@canonical.com>
Description:

status shows infos we can read and tells its meaning and value.

+0 −15
Original line number Diff line number Diff line
@@ -5,19 +5,4 @@ Contact: "Ike Panhc <ike.pan@canonical.com>"
Description:
		Control the power of camera module. 1 means on, 0 means off.

What:		/sys/devices/platform/ideapad/cfg
Date:		Jun 2011
KernelVersion:	3.1
Contact:	"Ike Panhc <ike.pan@canonical.com>"
Description:
		Ideapad capability bits.
		Bit 8-10: 1 - Intel graphic only
		          2 - ATI graphic only
		          3 - Nvidia graphic only
		          4 - Intel and ATI graphic
		          5 - Intel and Nvidia graphic
		Bit 16: Bluetooth exist (1 for exist)
		Bit 17: 3G exist (1 for exist)
		Bit 18: Wifi exist (1 for exist)
		Bit 19: Camera exist (1 for exist)
+7 −0
Original line number Diff line number Diff line
@@ -3227,6 +3227,13 @@ F: Documentation/ide/
F:	drivers/ide/
F:	include/linux/ide.h

IDEAPAD LAPTOP EXTRAS DRIVER
M:	Ike Panhc <ike.pan@canonical.com>
L:	platform-driver-x86@vger.kernel.org
W:	http://launchpad.net/ideapad-laptop
S:	Maintained
F:	drivers/platform/x86/ideapad-laptop.c

IDE/ATAPI DRIVERS
M:	Borislav Petkov <petkovbb@gmail.com>
L:	linux-ide@vger.kernel.org
+10 −7
Original line number Diff line number Diff line
@@ -61,15 +61,18 @@ config ASUS_LAPTOP
	depends on INPUT
	depends on RFKILL || RFKILL = n
	select INPUT_SPARSEKMAP
	select INPUT_POLLDEV
	---help---
	  This is the new Linux driver for Asus laptops. It may also support some
	  MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
	  standard ACPI events and input events. It also adds
	  support for video output switching, LCD backlight control, Bluetooth and
	  Wlan control, and most importantly, allows you to blink those fancy LEDs.
	  This is a driver for Asus laptops, Lenovo SL and the Pegatron
	  Lucid tablet. It may also support some MEDION, JVC or VICTOR
	  laptops. It makes all the extra buttons generate standard
	  ACPI events and input events, and on the Lucid the built-in
	  accelerometer appears as an input device.  It also adds
	  support for video output switching, LCD backlight control,
	  Bluetooth and Wlan control, and most importantly, allows you
	  to blink those fancy LEDs.

	  For more information and a userspace daemon for handling the extra
	  buttons see <http://acpi4asus.sf.net>.
	  For more information see <http://acpi4asus.sf.net>.

	  If you have an ACPI-compatible ASUS laptop, say Y or M here.

+264 −224
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ enum interface_flags {
	ACER_AMW0,
	ACER_AMW0_V2,
	ACER_WMID,
	ACER_WMID_v2,
};

#define ACER_DEFAULT_WIRELESS  0
@@ -205,6 +206,7 @@ static int threeg = -1;
static int force_series;
static bool ec_raw_mode;
static bool has_type_aa;
static u16 commun_func_bitmap;

module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
@@ -464,6 +466,15 @@ static struct dmi_system_id acer_quirks[] = {
		},
		.driver_data = &quirk_lenovo_ideapad_s205,
	},
	{
		.callback = dmi_matched,
		.ident = "Lenovo 3000 N200",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
			DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
		},
		.driver_data = &quirk_fujitsu_amilo_li_1718,
	},
	{}
};

@@ -868,6 +879,174 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
	return WMI_execute_u32(method_id, (u32)value, NULL);
}

static acpi_status wmid3_get_device_status(u32 *value, u16 device)
{
	struct wmid3_gds_return_value return_value;
	acpi_status status;
	union acpi_object *obj;
	struct wmid3_gds_input_param params = {
		.function_num = 0x1,
		.hotkey_number = 0x01,
		.devices = device,
	};
	struct acpi_buffer input = {
		sizeof(struct wmid3_gds_input_param),
		&params
	};
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
	if (ACPI_FAILURE(status))
		return status;

	obj = output.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 8) {
		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value)
		pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
			device,
			return_value.error_code,
			return_value.ec_return_value);
	else
		*value = !!(return_value.devices & device);

	return status;
}

static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
{
	u16 device;

	switch (cap) {
	case ACER_CAP_WIRELESS:
		device = ACER_WMID3_GDS_WIRELESS;
		break;
	case ACER_CAP_BLUETOOTH:
		device = ACER_WMID3_GDS_BLUETOOTH;
		break;
	case ACER_CAP_THREEG:
		device = ACER_WMID3_GDS_THREEG;
		break;
	default:
		return AE_ERROR;
	}
	return wmid3_get_device_status(value, device);
}

static acpi_status wmid3_set_device_status(u32 value, u16 device)
{
	struct wmid3_gds_return_value return_value;
	acpi_status status;
	union acpi_object *obj;
	u16 devices;
	struct wmid3_gds_input_param params = {
		.function_num = 0x1,
		.hotkey_number = 0x01,
		.devices = commun_func_bitmap,
	};
	struct acpi_buffer input = {
		sizeof(struct wmid3_gds_input_param),
		&params
	};
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
	if (ACPI_FAILURE(status))
		return status;

	obj = output.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 8) {
		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value) {
		pr_warning("Get Current Device Status failed: "
			"0x%x - 0x%x\n", return_value.error_code,
			return_value.ec_return_value);
		return status;
	}

	devices = return_value.devices;
	params.function_num = 0x2;
	params.hotkey_number = 0x01;
	params.devices = (value) ? (devices | device) : (devices & ~device);

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
	if (ACPI_FAILURE(status))
		return status;

	obj = output2.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 4) {
		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value)
		pr_warning("Set Device Status failed: "
			"0x%x - 0x%x\n", return_value.error_code,
			return_value.ec_return_value);

	return status;
}

static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
{
	u16 device;

	switch (cap) {
	case ACER_CAP_WIRELESS:
		device = ACER_WMID3_GDS_WIRELESS;
		break;
	case ACER_CAP_BLUETOOTH:
		device = ACER_WMID3_GDS_BLUETOOTH;
		break;
	case ACER_CAP_THREEG:
		device = ACER_WMID3_GDS_THREEG;
		break;
	default:
		return AE_ERROR;
	}
	return wmid3_set_device_status(value, device);
}

static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
{
	struct hotkey_function_type_aa *type_aa;
@@ -881,6 +1060,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)

	pr_info("Function bitmap for Communication Button: 0x%x\n",
		type_aa->commun_func_bitmap);
	commun_func_bitmap = type_aa->commun_func_bitmap;

	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
		interface->capability |= ACER_CAP_WIRELESS;
@@ -913,17 +1093,13 @@ static acpi_status WMID_set_capabilities(void)
		return AE_ERROR;
	}

	dmi_walk(type_aa_dmi_decode, NULL);
	if (!has_type_aa) {
	pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
	if (devices & 0x07)
		interface->capability |= ACER_CAP_WIRELESS;
	if (devices & 0x40)
		interface->capability |= ACER_CAP_THREEG;
	if (devices & 0x10)
		interface->capability |= ACER_CAP_BLUETOOTH;
	}

	/* WMID always provides brightness methods */
	interface->capability |= ACER_CAP_BRIGHTNESS;

	if (!(devices & 0x20))
		max_brightness = 0x9;
@@ -936,6 +1112,10 @@ static struct wmi_interface wmid_interface = {
	.type = ACER_WMID,
};

static struct wmi_interface wmid_v2_interface = {
	.type = ACER_WMID_v2,
};

/*
 * Generic Device (interface-independent)
 */
@@ -956,6 +1136,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
	case ACER_WMID:
		status = WMID_get_u32(value, cap, interface);
		break;
	case ACER_WMID_v2:
		if (cap & (ACER_CAP_WIRELESS |
			   ACER_CAP_BLUETOOTH |
			   ACER_CAP_THREEG))
			status = wmid_v2_get_u32(value, cap);
		else if (wmi_has_guid(WMID_GUID2))
			status = WMID_get_u32(value, cap, interface);
		break;
	}

	return status;
@@ -989,6 +1177,13 @@ static acpi_status set_u32(u32 value, u32 cap)
			}
		case ACER_WMID:
			return WMID_set_u32(value, cap, interface);
		case ACER_WMID_v2:
			if (cap & (ACER_CAP_WIRELESS |
				   ACER_CAP_BLUETOOTH |
				   ACER_CAP_THREEG))
				return wmid_v2_set_u32(value, cap);
			else if (wmi_has_guid(WMID_GUID2))
				return WMID_set_u32(value, cap, interface);
		default:
			return AE_BAD_PARAMETER;
		}
@@ -1095,186 +1290,6 @@ static void acer_backlight_exit(void)
	backlight_device_unregister(acer_backlight_device);
}

static acpi_status wmid3_get_device_status(u32 *value, u16 device)
{
	struct wmid3_gds_return_value return_value;
	acpi_status status;
	union acpi_object *obj;
	struct wmid3_gds_input_param params = {
		.function_num = 0x1,
		.hotkey_number = 0x01,
		.devices = device,
	};
	struct acpi_buffer input = {
		sizeof(struct wmid3_gds_input_param),
		&params
	};
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
	if (ACPI_FAILURE(status))
		return status;

	obj = output.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 8) {
		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value)
		pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
			return_value.error_code,
			return_value.ec_return_value);
	else
		*value = !!(return_value.devices & device);

	return status;
}

static acpi_status get_device_status(u32 *value, u32 cap)
{
	if (wmi_has_guid(WMID_GUID3)) {
		u16 device;

		switch (cap) {
		case ACER_CAP_WIRELESS:
			device = ACER_WMID3_GDS_WIRELESS;
			break;
		case ACER_CAP_BLUETOOTH:
			device = ACER_WMID3_GDS_BLUETOOTH;
			break;
		case ACER_CAP_THREEG:
			device = ACER_WMID3_GDS_THREEG;
			break;
		default:
			return AE_ERROR;
		}
		return wmid3_get_device_status(value, device);

	} else {
		return get_u32(value, cap);
	}
}

static acpi_status wmid3_set_device_status(u32 value, u16 device)
{
	struct wmid3_gds_return_value return_value;
	acpi_status status;
	union acpi_object *obj;
	u16 devices;
	struct wmid3_gds_input_param params = {
		.function_num = 0x1,
		.hotkey_number = 0x01,
		.devices = ACER_WMID3_GDS_WIRELESS |
				ACER_WMID3_GDS_THREEG |
				ACER_WMID3_GDS_WIMAX |
				ACER_WMID3_GDS_BLUETOOTH,
	};
	struct acpi_buffer input = {
		sizeof(struct wmid3_gds_input_param),
		&params
	};
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
	if (ACPI_FAILURE(status))
		return status;

	obj = output.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 8) {
		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value) {
		pr_warning("Get Current Device Status failed: "
			"0x%x - 0x%x\n", return_value.error_code,
			return_value.ec_return_value);
		return status;
	}

	devices = return_value.devices;
	params.function_num = 0x2;
	params.hotkey_number = 0x01;
	params.devices = (value) ? (devices | device) : (devices & ~device);

	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
	if (ACPI_FAILURE(status))
		return status;

	obj = output2.pointer;

	if (!obj)
		return AE_ERROR;
	else if (obj->type != ACPI_TYPE_BUFFER) {
		kfree(obj);
		return AE_ERROR;
	}
	if (obj->buffer.length != 4) {
		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return AE_ERROR;
	}

	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
	kfree(obj);

	if (return_value.error_code || return_value.ec_return_value)
		pr_warning("Set Device Status failed: "
			"0x%x - 0x%x\n", return_value.error_code,
			return_value.ec_return_value);

	return status;
}

static acpi_status set_device_status(u32 value, u32 cap)
{
	if (wmi_has_guid(WMID_GUID3)) {
		u16 device;

		switch (cap) {
		case ACER_CAP_WIRELESS:
			device = ACER_WMID3_GDS_WIRELESS;
			break;
		case ACER_CAP_BLUETOOTH:
			device = ACER_WMID3_GDS_BLUETOOTH;
			break;
		case ACER_CAP_THREEG:
			device = ACER_WMID3_GDS_THREEG;
			break;
		default:
			return AE_ERROR;
		}
		return wmid3_set_device_status(value, device);

	} else {
		return set_u32(value, cap);
	}
}

/*
 * Rfkill devices
 */
@@ -1285,11 +1300,12 @@ static void acer_rfkill_update(struct work_struct *ignored)
	u32 state;
	acpi_status status;

	if (has_cap(ACER_CAP_WIRELESS)) {
		status = get_u32(&state, ACER_CAP_WIRELESS);
		if (ACPI_SUCCESS(status)) {
		if (quirks->wireless == 3) {
			if (quirks->wireless == 3)
				rfkill_set_hw_state(wireless_rfkill, !state);
		} else {
			else
				rfkill_set_sw_state(wireless_rfkill, !state);
		}
	}
@@ -1301,8 +1317,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
	}

	if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
		status = wmid3_get_device_status(&state,
				ACER_WMID3_GDS_THREEG);
		status = get_u32(&state, ACER_WMID3_GDS_THREEG);
		if (ACPI_SUCCESS(status))
			rfkill_set_sw_state(threeg_rfkill, !state);
	}
@@ -1316,7 +1331,7 @@ static int acer_rfkill_set(void *data, bool blocked)
	u32 cap = (unsigned long)data;

	if (rfkill_inited) {
		status = set_device_status(!blocked, cap);
		status = set_u32(!blocked, cap);
		if (ACPI_FAILURE(status))
			return -ENODEV;
	}
@@ -1343,7 +1358,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
	if (!rfkill_dev)
		return ERR_PTR(-ENOMEM);

	status = get_device_status(&state, cap);
	status = get_u32(&state, cap);

	err = rfkill_register(rfkill_dev);
	if (err) {
@@ -1359,19 +1374,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev,

static int acer_rfkill_init(struct device *dev)
{
	int err;

	if (has_cap(ACER_CAP_WIRELESS)) {
		wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
			"acer-wireless", ACER_CAP_WIRELESS);
	if (IS_ERR(wireless_rfkill))
		return PTR_ERR(wireless_rfkill);
		if (IS_ERR(wireless_rfkill)) {
			err = PTR_ERR(wireless_rfkill);
			goto error_wireless;
		}
	}

	if (has_cap(ACER_CAP_BLUETOOTH)) {
		bluetooth_rfkill = acer_rfkill_register(dev,
			RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
			ACER_CAP_BLUETOOTH);
		if (IS_ERR(bluetooth_rfkill)) {
			rfkill_unregister(wireless_rfkill);
			rfkill_destroy(wireless_rfkill);
			return PTR_ERR(bluetooth_rfkill);
			err = PTR_ERR(bluetooth_rfkill);
			goto error_bluetooth;
		}
	}

@@ -1380,30 +1400,44 @@ static int acer_rfkill_init(struct device *dev)
			RFKILL_TYPE_WWAN, "acer-threeg",
			ACER_CAP_THREEG);
		if (IS_ERR(threeg_rfkill)) {
			rfkill_unregister(wireless_rfkill);
			rfkill_destroy(wireless_rfkill);
			rfkill_unregister(bluetooth_rfkill);
			rfkill_destroy(bluetooth_rfkill);
			return PTR_ERR(threeg_rfkill);
			err = PTR_ERR(threeg_rfkill);
			goto error_threeg;
		}
	}

	rfkill_inited = true;

	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
		schedule_delayed_work(&acer_rfkill_work,
			round_jiffies_relative(HZ));

	return 0;

error_threeg:
	if (has_cap(ACER_CAP_BLUETOOTH)) {
		rfkill_unregister(bluetooth_rfkill);
		rfkill_destroy(bluetooth_rfkill);
	}
error_bluetooth:
	if (has_cap(ACER_CAP_WIRELESS)) {
		rfkill_unregister(wireless_rfkill);
		rfkill_destroy(wireless_rfkill);
	}
error_wireless:
	return err;
}

static void acer_rfkill_exit(void)
{
	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
		cancel_delayed_work_sync(&acer_rfkill_work);

	if (has_cap(ACER_CAP_WIRELESS)) {
		rfkill_unregister(wireless_rfkill);
		rfkill_destroy(wireless_rfkill);
	}

	if (has_cap(ACER_CAP_BLUETOOTH)) {
		rfkill_unregister(bluetooth_rfkill);
@@ -1428,10 +1462,6 @@ static ssize_t show_bool_threeg(struct device *dev,

	pr_info("This threeg sysfs will be removed in 2012"
		" - used by: %s\n", current->comm);
	if (wmi_has_guid(WMID_GUID3))
		status = wmid3_get_device_status(&result,
				ACER_WMID3_GDS_THREEG);
	else
	status = get_u32(&result, ACER_CAP_THREEG);
	if (ACPI_SUCCESS(status))
		return sprintf(buf, "%u\n", result);
@@ -1464,6 +1494,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
		return sprintf(buf, "AMW0 v2\n");
	case ACER_WMID:
		return sprintf(buf, "WMID\n");
	case ACER_WMID_v2:
		return sprintf(buf, "WMID v2\n");
	default:
		return sprintf(buf, "Error!\n");
	}
@@ -1883,12 +1915,20 @@ static int __init acer_wmi_init(void)
	if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
		interface = &wmid_interface;

	if (wmi_has_guid(WMID_GUID3))
		interface = &wmid_v2_interface;

	if (interface)
		dmi_walk(type_aa_dmi_decode, NULL);

	if (wmi_has_guid(WMID_GUID2) && interface) {
		if (ACPI_FAILURE(WMID_set_capabilities())) {
		if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
			pr_err("Unable to detect available WMID devices\n");
			return -ENODEV;
		}
	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
		/* WMID always provides brightness methods */
		interface->capability |= ACER_CAP_BRIGHTNESS;
	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
		pr_err("No WMID device detection method found\n");
		return -ENODEV;
	}
@@ -1912,7 +1952,7 @@ static int __init acer_wmi_init(void)

	set_quirks();

	if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
	if (acpi_video_backlight_support()) {
		interface->capability &= ~ACER_CAP_BRIGHTNESS;
		pr_info("Brightness must be controlled by "
		       "generic video driver\n");
Loading