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

Commit edf0e0e5 authored by Henrique de Moraes Holschuh's avatar Henrique de Moraes Holschuh Committed by Len Brown
Browse files

ACPI: thinkpad-acpi: react to Lenovo ThinkPad differences in hot key



Lenovo ThinkPads have a slightly different key map layout from IBM
ThinkPads (fn+f2 and fn+f3 are swapped).  Knowing which one we are dealing
with, we can properly set a few more hot keys up by default.

Also, export the correct vendor in the input device, as that information
might be useful to userspace.

Signed-off-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 24d3b774
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -270,7 +270,8 @@ remapping KEY_UNKNOWN keys.
The events are available in an input device, with the following id:

	Bus:		BUS_HOST
	vendor:		0x1014 (PCI_VENDOR_ID_IBM)
	vendor:		0x1014 (PCI_VENDOR_ID_IBM)  or
			0x17aa (PCI_VENDOR_ID_LENOVO)
	product:	0x5054 ("TP")
	version:	0x4101

@@ -290,12 +291,15 @@ ACPI Scan
event	code	Key		Notes

0x1001	0x00	FN+F1		-
0x1002	0x01	FN+F2		-
0x1002	0x01	FN+F2		IBM: battery (rare)
				Lenovo: Screen lock

0x1003	0x02	FN+F3		Many models always report this
				hot key, even with hot keys
0x1003	0x02	FN+F3		Many IBM models always report
				this hot key, even with hot keys
				disabled or with Fn+F3 masked
				off
				IBM: screen lock
				Lenovo: battery

0x1004	0x03	FN+F4		Sleep button (ACPI sleep button
				semanthics, i.e. sleep-to-RAM).
@@ -313,13 +317,19 @@ event code Key Notes
				and W-WAN card if left in control
				of the firmware.  Does not affect
				the WLAN card.
				Should be used to turn on/off all
				radios (bluetooth+W-WAN+WLAN),
				really.

0x1006	0x05	FN+F6		-

0x1007	0x06	FN+F7		Video output cycle.
				Do you feel lucky today?

0x1008	0x07	FN+F8		-
0x1008	0x07	FN+F8		IBM: toggle screen expand
				Lenovo: configure ultranav

0x1009	0x08	FN+F9		-
	..	..		..
0x100B	0x0A	FN+F11		-

@@ -338,13 +348,15 @@ event code Key Notes
0x100F	0x0E	FN+DELETE	-

0x1010	0x0F	FN+HOME		Brightness up.  This key is
				always handled by the firmware,
				even when unmasked.  Just leave
				it alone.
0x1011	0x10	FN+END		Brightness down. This key is
				always handled by the firmware,
				even when unmasked.  Just leave
				it alone.
				always handled by the firmware
				in IBM ThinkPads, even when
				unmasked.  Just leave it alone.
				For Lenovo ThinkPads with a new
				BIOS, it has to be handled either
				by the ACPI OSI, or by userspace.
0x1011	0x10	FN+END		Brightness down.  See brightness
				up for details.

0x1012	0x11	FN+PGUP		Thinklight toggle.  This key is
				always handled by the firmware,
				even when unmasked.
@@ -356,9 +368,13 @@ event code Key Notes
0x1015	0x14	VOLUME UP	Internal mixer volume up. This
				key is always handled by the
				firmware, even when unmasked.
				NOTE: Lenovo seems to be changing
				this.
0x1016	0x15	VOLUME DOWN	Internal mixer volume up. This
				key is always handled by the
				firmware, even when unmasked.
				NOTE: Lenovo seems to be changing
				this.
0x1017	0x16	MUTE		Mute internal mixer. This
				key is always handled by the
				firmware, even when unmasked.
+81 −28
Original line number Diff line number Diff line
@@ -758,29 +758,7 @@ static u32 hotkey_orig_mask;
static u32 hotkey_all_mask;
static u32 hotkey_reserved_mask;

static u16 hotkey_keycode_map[] = {
	/* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
	KEY_FN_F1,	KEY_FN_F2,	KEY_FN_F3,	KEY_SLEEP,
	KEY_FN_F5,	KEY_FN_F6,	KEY_FN_F7,	KEY_FN_F8,
	KEY_FN_F9,	KEY_FN_F10,	KEY_FN_F11,	KEY_SUSPEND,
	/* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
	KEY_UNKNOWN,	/* 0x0C: FN+BACKSPACE */
	KEY_UNKNOWN,	/* 0x0D: FN+INSERT */
	KEY_UNKNOWN,	/* 0x0E: FN+DELETE */
	KEY_RESERVED,	/* 0x0F: FN+HOME (brightness up) */
	/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
	KEY_RESERVED,	/* 0x10: FN+END (brightness down) */
	KEY_RESERVED,	/* 0x11: FN+PGUP (thinklight toggle) */
	KEY_UNKNOWN,	/* 0x12: FN+PGDOWN */
	KEY_ZOOM,	/* 0x13: FN+SPACE (zoom) */
	KEY_RESERVED,	/* 0x14: VOLUME UP */
	KEY_RESERVED,	/* 0x15: VOLUME DOWN */
	KEY_RESERVED,	/* 0x16: MUTE */
	KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
	/* (assignments unknown, please report if found) */
	KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
	KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
};
static u16 *hotkey_keycode_map;

static struct attribute_set *hotkey_dev_attributes;

@@ -939,6 +917,58 @@ static struct attribute *hotkey_mask_attributes[] = {

static int __init hotkey_init(struct ibm_init_struct *iibm)
{

	static u16 ibm_keycode_map[] __initdata = {
		/* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
		KEY_FN_F1,	KEY_FN_F2,	KEY_COFFEE,	KEY_SLEEP,
		KEY_WLAN,	KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
		KEY_FN_F9,	KEY_FN_F10,	KEY_FN_F11,	KEY_SUSPEND,
		/* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
		KEY_UNKNOWN,	/* 0x0C: FN+BACKSPACE */
		KEY_UNKNOWN,	/* 0x0D: FN+INSERT */
		KEY_UNKNOWN,	/* 0x0E: FN+DELETE */
		KEY_RESERVED,	/* 0x0F: FN+HOME (brightness up) */
		/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
		KEY_RESERVED,	/* 0x10: FN+END (brightness down) */
		KEY_RESERVED,	/* 0x11: FN+PGUP (thinklight toggle) */
		KEY_UNKNOWN,	/* 0x12: FN+PGDOWN */
		KEY_ZOOM,	/* 0x13: FN+SPACE (zoom) */
		KEY_RESERVED,	/* 0x14: VOLUME UP */
		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
		KEY_RESERVED,	/* 0x16: MUTE */
		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
		/* (assignments unknown, please report if found) */
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
	};
	static u16 lenovo_keycode_map[] __initdata = {
		/* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
		KEY_FN_F1,	KEY_COFFEE,	KEY_BATTERY,	KEY_SLEEP,
		KEY_WLAN,	KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
		KEY_FN_F9,	KEY_FN_F10,	KEY_FN_F11,	KEY_SUSPEND,
		/* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
		KEY_UNKNOWN,	/* 0x0C: FN+BACKSPACE */
		KEY_UNKNOWN,	/* 0x0D: FN+INSERT */
		KEY_UNKNOWN,	/* 0x0E: FN+DELETE */
		KEY_BRIGHTNESSUP,	/* 0x0F: FN+HOME (brightness up) */
		/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
		KEY_BRIGHTNESSDOWN,	/* 0x10: FN+END (brightness down) */
		KEY_RESERVED,	/* 0x11: FN+PGUP (thinklight toggle) */
		KEY_UNKNOWN,	/* 0x12: FN+PGDOWN */
		KEY_ZOOM,	/* 0x13: FN+SPACE (zoom) */
		KEY_RESERVED,	/* 0x14: VOLUME UP */
		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
		KEY_RESERVED,	/* 0x16: MUTE */
		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
		/* (assignments unknown, please report if found) */
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
	};

#define TPACPI_HOTKEY_MAP_LEN		ARRAY_SIZE(ibm_keycode_map)
#define TPACPI_HOTKEY_MAP_SIZE		sizeof(ibm_keycode_map)
#define TPACPI_HOTKEY_MAP_TYPESIZE	sizeof(ibm_keycode_map[0])

	int res, i;
	int status;

@@ -1003,6 +1033,27 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		if (res)
			return res;

		/* Set up key map */

		hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
						GFP_KERNEL);
		if (!hotkey_keycode_map) {
			printk(IBM_ERR "failed to allocate memory for key map\n");
			return -ENOMEM;
		}

		if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
			dbg_printk(TPACPI_DBG_INIT,
				   "using Lenovo default hot key map\n");
			memcpy(hotkey_keycode_map, &lenovo_keycode_map,
				TPACPI_HOTKEY_MAP_SIZE);
		} else {
			dbg_printk(TPACPI_DBG_INIT,
				   "using IBM default hot key map\n");
			memcpy(hotkey_keycode_map, &ibm_keycode_map,
				TPACPI_HOTKEY_MAP_SIZE);
		}

#ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
		for (i = 0; i < 12; i++)
			hotkey_keycode_map[i] = KEY_UNKNOWN;
@@ -1011,10 +1062,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		set_bit(EV_KEY, tpacpi_inputdev->evbit);
		set_bit(EV_MSC, tpacpi_inputdev->evbit);
		set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
		tpacpi_inputdev->keycodesize = sizeof(hotkey_keycode_map[0]);
		tpacpi_inputdev->keycodemax = ARRAY_SIZE(hotkey_keycode_map);
		tpacpi_inputdev->keycode = &hotkey_keycode_map;
		for (i = 0; i < ARRAY_SIZE(hotkey_keycode_map); i++) {
		tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
		tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
		tpacpi_inputdev->keycode = hotkey_keycode_map;
		for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
			if (hotkey_keycode_map[i] != KEY_RESERVED) {
				set_bit(hotkey_keycode_map[i],
					tpacpi_inputdev->keybit);
@@ -4618,7 +4669,9 @@ static int __init thinkpad_acpi_module_init(void)
		tpacpi_inputdev->name = "ThinkPad Extra Buttons";
		tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
		tpacpi_inputdev->id.bustype = BUS_HOST;
		tpacpi_inputdev->id.vendor = TPACPI_HKEY_INPUT_VENDOR;
		tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
						thinkpad_id.vendor :
						PCI_VENDOR_ID_IBM;
		tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
		tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
	}