Commit d1e14dca authored by Henrique de Moraes Holschuh's avatar Henrique de Moraes Holschuh Committed by Matthew Garrett
Browse files

thinkpad-acpi: add support for model-specific keymaps

Use the quirks engine to select model-specific keymaps, which makes
it much easier to extend should we need it.

Keycodes are based on the tables at
http://www.thinkwiki.org/wiki/Default_meanings_of_special_keys

.

Signed-off-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
parent 34a656d2
Loading
Loading
Loading
Loading
+42 −18
Original line number Diff line number Diff line
@@ -3093,6 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = {
	TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */
};

typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];

static int __init hotkey_init(struct ibm_init_struct *iibm)
{
	/* Requirements for changing the default keymaps:
@@ -3124,9 +3126,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
	 * If the above is too much to ask, don't change the keymap.
	 * Ask the thinkpad-acpi maintainer to do it, instead.
	 */
	static u16 ibm_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = {

	enum keymap_index {
		TPACPI_KEYMAP_IBM_GENERIC = 0,
		TPACPI_KEYMAP_LENOVO_GENERIC,
	};

	static const tpacpi_keymap_t tpacpi_keymaps[] __initconst = {
	/* Generic keymap for IBM ThinkPads */
	[TPACPI_KEYMAP_IBM_GENERIC] = {
		/* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
		KEY_FN_F1,	KEY_FN_F2,	KEY_COFFEE,	KEY_SLEEP,
		KEY_FN_F1,	KEY_BATTERY,	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,

@@ -3157,8 +3167,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		/* (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[TPACPI_HOTKEY_MAP_LEN] __initdata = {
		},

	/* Generic keymap for Lenovo ThinkPads */
	[TPACPI_KEYMAP_LENOVO_GENERIC] = {
		/* 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,
@@ -3200,10 +3212,25 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		/* (assignments unknown, please report if found) */
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
		KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
		},
	};

	static const struct tpacpi_quirk tpacpi_keymap_qtable[] __initconst = {
		/* Generic maps (fallback) */
		{
		  .vendor = PCI_VENDOR_ID_IBM,
		  .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
		  .quirks = TPACPI_KEYMAP_IBM_GENERIC,
		},
		{
		  .vendor = PCI_VENDOR_ID_LENOVO,
		  .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
		  .quirks = TPACPI_KEYMAP_LENOVO_GENERIC,
		},
	};

#define TPACPI_HOTKEY_MAP_SIZE		sizeof(ibm_keycode_map)
#define TPACPI_HOTKEY_MAP_TYPESIZE	sizeof(ibm_keycode_map[0])
#define TPACPI_HOTKEY_MAP_SIZE		sizeof(tpacpi_keymap_t)
#define TPACPI_HOTKEY_MAP_TYPESIZE	sizeof(tpacpi_keymap_t[0])

	int res, i;
	int status;
@@ -3212,6 +3239,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
	bool tabletsw_state = false;

	unsigned long quirks;
	unsigned long keymap_id;

	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
			"initializing hotkey subdriver\n");
@@ -3352,7 +3380,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		goto err_exit;

	/* Set up key map */

	hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
					GFP_KERNEL);
	if (!hotkey_keycode_map) {
@@ -3362,17 +3389,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
		goto err_exit;
	}

	if (tpacpi_is_lenovo()) {
		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
			   "using Lenovo default hot key map\n");
		memcpy(hotkey_keycode_map, &lenovo_keycode_map,
			TPACPI_HOTKEY_MAP_SIZE);
	} else {
	keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable,
					ARRAY_SIZE(tpacpi_keymap_qtable));
	BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps));
	dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
			   "using IBM default hot key map\n");
		memcpy(hotkey_keycode_map, &ibm_keycode_map,
		   "using keymap number %lu\n", keymap_id);

	memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id],
		TPACPI_HOTKEY_MAP_SIZE);
	}

	input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
	tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;