Commit d1e14dca6a18aa40394316c872993ae3bc7e311a

Authored by Henrique de Moraes Holschuh
Committed by Matthew Garrett
1 parent 34a656d22f

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: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Matthew Garrett <mjg@redhat.com>

Showing 1 changed file with 42 additions and 18 deletions Side-by-side Diff

drivers/platform/x86/thinkpad_acpi.c
... ... @@ -3093,6 +3093,8 @@
3093 3093 TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */
3094 3094 };
3095 3095  
  3096 +typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];
  3097 +
3096 3098 static int __init hotkey_init(struct ibm_init_struct *iibm)
3097 3099 {
3098 3100 /* Requirements for changing the default keymaps:
3099 3101  
... ... @@ -3124,9 +3126,17 @@
3124 3126 * If the above is too much to ask, don't change the keymap.
3125 3127 * Ask the thinkpad-acpi maintainer to do it, instead.
3126 3128 */
3127   - static u16 ibm_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = {
  3129 +
  3130 + enum keymap_index {
  3131 + TPACPI_KEYMAP_IBM_GENERIC = 0,
  3132 + TPACPI_KEYMAP_LENOVO_GENERIC,
  3133 + };
  3134 +
  3135 + static const tpacpi_keymap_t tpacpi_keymaps[] __initconst = {
  3136 + /* Generic keymap for IBM ThinkPads */
  3137 + [TPACPI_KEYMAP_IBM_GENERIC] = {
3128 3138 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
3129   - KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP,
  3139 + KEY_FN_F1, KEY_BATTERY, KEY_COFFEE, KEY_SLEEP,
3130 3140 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3131 3141 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
3132 3142  
... ... @@ -3157,8 +3167,10 @@
3157 3167 /* (assignments unknown, please report if found) */
3158 3168 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3159 3169 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3160   - };
3161   - static u16 lenovo_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = {
  3170 + },
  3171 +
  3172 + /* Generic keymap for Lenovo ThinkPads */
  3173 + [TPACPI_KEYMAP_LENOVO_GENERIC] = {
3162 3174 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
3163 3175 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
3164 3176 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3165 3177  
3166 3178  
... ... @@ -3200,11 +3212,26 @@
3200 3212 /* (assignments unknown, please report if found) */
3201 3213 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3202 3214 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
  3215 + },
3203 3216 };
3204 3217  
3205   -#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)
3206   -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
  3218 + static const struct tpacpi_quirk tpacpi_keymap_qtable[] __initconst = {
  3219 + /* Generic maps (fallback) */
  3220 + {
  3221 + .vendor = PCI_VENDOR_ID_IBM,
  3222 + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
  3223 + .quirks = TPACPI_KEYMAP_IBM_GENERIC,
  3224 + },
  3225 + {
  3226 + .vendor = PCI_VENDOR_ID_LENOVO,
  3227 + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
  3228 + .quirks = TPACPI_KEYMAP_LENOVO_GENERIC,
  3229 + },
  3230 + };
3207 3231  
  3232 +#define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t)
  3233 +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0])
  3234 +
3208 3235 int res, i;
3209 3236 int status;
3210 3237 int hkeyv;
... ... @@ -3212,6 +3239,7 @@
3212 3239 bool tabletsw_state = false;
3213 3240  
3214 3241 unsigned long quirks;
  3242 + unsigned long keymap_id;
3215 3243  
3216 3244 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3217 3245 "initializing hotkey subdriver\n");
... ... @@ -3352,7 +3380,6 @@
3352 3380 goto err_exit;
3353 3381  
3354 3382 /* Set up key map */
3355   -
3356 3383 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
3357 3384 GFP_KERNEL);
3358 3385 if (!hotkey_keycode_map) {
... ... @@ -3362,17 +3389,14 @@
3362 3389 goto err_exit;
3363 3390 }
3364 3391  
3365   - if (tpacpi_is_lenovo()) {
3366   - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3367   - "using Lenovo default hot key map\n");
3368   - memcpy(hotkey_keycode_map, &lenovo_keycode_map,
3369   - TPACPI_HOTKEY_MAP_SIZE);
3370   - } else {
3371   - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3372   - "using IBM default hot key map\n");
3373   - memcpy(hotkey_keycode_map, &ibm_keycode_map,
3374   - TPACPI_HOTKEY_MAP_SIZE);
3375   - }
  3392 + keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable,
  3393 + ARRAY_SIZE(tpacpi_keymap_qtable));
  3394 + BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps));
  3395 + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
  3396 + "using keymap number %lu\n", keymap_id);
  3397 +
  3398 + memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id],
  3399 + TPACPI_HOTKEY_MAP_SIZE);
3376 3400  
3377 3401 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
3378 3402 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;