1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpigen.h>
4 #include <acpi/acpigen_ps2_keybd.h>
5 #include <console/console.h>
6 #include <input-event-codes.h>
10 #define KEYMAP(scancode, keycode) (((uint32_t)(scancode) << 16) | (keycode & 0xFFFF))
11 #define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
13 /* Possible keymaps for function keys in the top row */
14 static const uint32_t function_keymaps
[] = {
24 KEYMAP(0x44, KEY_F10
),
25 KEYMAP(0x57, KEY_F11
),
26 KEYMAP(0x58, KEY_F12
),
27 KEYMAP(0x59, KEY_F13
),
28 KEYMAP(0x5a, KEY_F14
),
29 KEYMAP(0x5b, KEY_F15
),
33 * Possible keymaps for action keys in the top row. This is a superset of
34 * possible keys. Individual keyboards will have a subset of these keys.
35 * The scancodes are true / condensed 1 byte scancodes from set-1
37 static const uint32_t action_keymaps
[] = {
38 [PS2_KEY_BACK
] = KEYMAP(0xea, KEY_BACK
), /* e06a */
39 [PS2_KEY_FORWARD
] = KEYMAP(0xe9, KEY_FORWARD
), /* e069 */
40 [PS2_KEY_REFRESH
] = KEYMAP(0xe7, KEY_REFRESH
), /* e067 */
41 [PS2_KEY_FULLSCREEN
] = KEYMAP(0x91, KEY_FULL_SCREEN
), /* e011 */
42 [PS2_KEY_OVERVIEW
] = KEYMAP(0x92, KEY_SCALE
), /* e012 */
43 [PS2_KEY_VOL_MUTE
] = KEYMAP(0xa0, KEY_MUTE
), /* e020 */
44 [PS2_KEY_VOL_DOWN
] = KEYMAP(0xae, KEY_VOLUMEDOWN
), /* e02e */
45 [PS2_KEY_VOL_UP
] = KEYMAP(0xb0, KEY_VOLUMEUP
), /* e030 */
46 [PS2_KEY_PLAY_PAUSE
] = KEYMAP(0x9a, KEY_PLAYPAUSE
), /* e01a */
47 [PS2_KEY_NEXT_TRACK
] = KEYMAP(0x99, KEY_NEXTSONG
), /* e019 */
48 [PS2_KEY_PREV_TRACK
] = KEYMAP(0x90, KEY_PREVIOUSSONG
), /* e010 */
49 [PS2_KEY_SNAPSHOT
] = KEYMAP(0x93, KEY_SYSRQ
), /* e013 */
50 [PS2_KEY_BRIGHTNESS_DOWN
] = KEYMAP(0x94, KEY_BRIGHTNESSDOWN
), /* e014 */
51 [PS2_KEY_BRIGHTNESS_UP
] = KEYMAP(0x95, KEY_BRIGHTNESSUP
), /* e015 */
52 [PS2_KEY_KBD_BKLIGHT_DOWN
] = KEYMAP(0x97, KEY_KBDILLUMDOWN
), /* e017 */
53 [PS2_KEY_KBD_BKLIGHT_UP
] = KEYMAP(0x98, KEY_KBDILLUMUP
), /* e018 */
54 [PS2_KEY_PRIVACY_SCRN_TOGGLE
] = KEYMAP(0x96, /* e016 */
55 KEY_PRIVACY_SCREEN_TOGGLE
),
56 [PS2_KEY_MICMUTE
] = KEYMAP(0x9b, KEY_MICMUTE
), /* e01b */
57 [PS2_KEY_KBD_BKLIGHT_TOGGLE
] = KEYMAP(0x9e, KEY_KBDILLUMTOGGLE
), /* e01e */
58 [PS2_KEY_MENU
] = KEYMAP(0xdd, KEY_CONTROLPANEL
), /* e0d5 */
59 [PS2_KEY_DICTATE
] = KEYMAP(0xa7, KEY_DICTATE
), /* e027*/
60 [PS2_KEY_ACCESSIBILITY
] = KEYMAP(0xa9, KEY_ACCESSIBILITY
), /* e029 */
61 [PS2_KEY_DO_NOT_DISTURB
] = KEYMAP(0xa8, KEY_DO_NOT_DISTURB
), /* e028 */
64 /* Keymap for numeric keypad keys */
65 static uint32_t numeric_keypad_keymaps
[] = {
67 KEYMAP(0xc9, KEY_PAGEUP
),
68 KEYMAP(0xd1, KEY_PAGEDOWN
),
69 KEYMAP(0xc7, KEY_HOME
),
70 KEYMAP(0xcf, KEY_END
),
72 KEYMAP(0xb5, KEY_KPSLASH
),
73 KEYMAP(0x37, KEY_KPASTERISK
),
74 KEYMAP(0x4a, KEY_KPMINUS
),
76 KEYMAP(0x47, KEY_KP7
),
77 KEYMAP(0x48, KEY_KP8
),
78 KEYMAP(0x49, KEY_KP9
),
79 KEYMAP(0x4e, KEY_KPPLUS
),
81 KEYMAP(0x4b, KEY_KP4
),
82 KEYMAP(0x4c, KEY_KP5
),
83 KEYMAP(0x4d, KEY_KP6
),
85 KEYMAP(0x4f, KEY_KP1
),
86 KEYMAP(0x50, KEY_KP2
),
87 KEYMAP(0x51, KEY_KP3
),
88 KEYMAP(0x9c, KEY_KPENTER
),
90 KEYMAP(0x52, KEY_KP0
),
91 KEYMAP(0x53, KEY_KPDOT
),
95 * Keymap for rest of non-top-row keys. This is a superset of all the possible
96 * keys that any chromeos keyboards can have.
98 static uint32_t rest_of_keymaps
[] = {
100 KEYMAP(0x01, KEY_ESC
),
101 KEYMAP(0xd3, KEY_DELETE
),
103 KEYMAP(0x29, KEY_GRAVE
),
114 KEYMAP(0x0c, KEY_MINUS
),
115 KEYMAP(0x0d, KEY_EQUAL
),
116 KEYMAP(0x7d, KEY_YEN
), /* JP keyboards only */
117 KEYMAP(0x0e, KEY_BACKSPACE
),
119 KEYMAP(0x0f, KEY_TAB
),
130 KEYMAP(0x1a, KEY_LEFTBRACE
),
131 KEYMAP(0x1b, KEY_RIGHTBRACE
),
132 KEYMAP(0x2b, KEY_BACKSLASH
),
134 KEYMAP(0xdb, KEY_LEFTMETA
), /* Search Key */
144 KEYMAP(0x27, KEY_SEMICOLON
),
145 KEYMAP(0x28, KEY_APOSTROPHE
),
146 KEYMAP(0x1c, KEY_ENTER
),
148 KEYMAP(0x2a, KEY_LEFTSHIFT
),
149 KEYMAP(0x56, KEY_102ND
), /* UK keyboards only */
157 KEYMAP(0x33, KEY_COMMA
),
158 KEYMAP(0x34, KEY_DOT
),
159 KEYMAP(0x35, KEY_SLASH
),
160 KEYMAP(0x73, KEY_RO
), /* JP keyboards only */
161 KEYMAP(0x36, KEY_RIGHTSHIFT
),
163 KEYMAP(0x1d, KEY_LEFTCTRL
),
164 KEYMAP(0x38, KEY_LEFTALT
),
165 KEYMAP(0x7b, KEY_MUHENKAN
), /* JP keyboards only */
166 KEYMAP(0x39, KEY_SPACE
),
167 KEYMAP(0x79, KEY_HENKAN
), /* JP keyboards only */
168 KEYMAP(0xb8, KEY_RIGHTALT
),
169 KEYMAP(0x9d, KEY_RIGHTCTRL
),
171 KEYMAP(0xcb, KEY_LEFT
),
172 KEYMAP(0xd0, KEY_DOWN
),
173 KEYMAP(0xcd, KEY_RIGHT
),
174 KEYMAP(0xc8, KEY_UP
),
176 KEYMAP(0xde, KEY_POWER
),
179 static void ssdt_generate_physmap(struct acpi_dp
*dp
, uint8_t num_top_row_keys
,
180 enum ps2_action_key action_keys
[])
182 struct acpi_dp
*dp_array
;
183 enum ps2_action_key key
;
186 dp_array
= acpi_dp_new_table("function-row-physmap");
188 printk(BIOS_ERR
, "PS2K: couldn't write function-row-physmap\n");
192 printk(BIOS_INFO
, "PS2K: Physmap: [");
193 for (i
= 0; i
< num_top_row_keys
; i
++) {
194 key
= action_keys
[i
];
195 if (key
&& key
< ARRAY_SIZE(action_keymaps
)) {
196 keymap
= action_keymaps
[key
];
200 "PS2K: invalid top-action-key-%u: %u(skipped)\n",
203 acpi_dp_add_integer(dp_array
, NULL
, SCANCODE(keymap
));
204 printk(BIOS_INFO
, " %X", SCANCODE(keymap
));
207 printk(BIOS_INFO
, " ]\n");
208 acpi_dp_add_array(dp
, dp_array
);
211 static void ssdt_generate_keymap(struct acpi_dp
*dp
, uint8_t num_top_row_keys
,
212 enum ps2_action_key action_keys
[],
213 bool can_send_function_keys
,
214 bool has_numeric_keypad
,
215 bool has_scrnlock_key
,
216 bool has_assistant_key
,
217 bool has_alpha_num_punct_keys
)
219 struct acpi_dp
*dp_array
;
220 enum ps2_action_key key
;
222 unsigned int i
, total
= 0;
224 dp_array
= acpi_dp_new_table("linux,keymap");
226 printk(BIOS_ERR
, "PS2K: couldn't write linux,keymap\n");
230 /* Write out keymap for top row action keys */
231 for (i
= 0; i
< num_top_row_keys
; i
++) {
232 key
= action_keys
[i
];
233 if (!key
|| key
>= ARRAY_SIZE(action_keymaps
)) {
235 "PS2K: invalid top-action-key-%u: %u\n", i
, key
);
238 keymap
= action_keymaps
[key
];
239 acpi_dp_add_integer(dp_array
, NULL
, keymap
);
243 /* Write out keymap for function keys, if keyboard can send them */
244 if (can_send_function_keys
) {
245 for (i
= 0; i
< num_top_row_keys
; i
++) {
246 keymap
= function_keymaps
[i
];
247 acpi_dp_add_integer(dp_array
, NULL
, keymap
);
251 if (CONFIG_ACPI_FNKEY_GEN_SCANCODE
!= 0) {
252 acpi_dp_add_integer(dp_array
, NULL
, KEYMAP(CONFIG_ACPI_FNKEY_GEN_SCANCODE
,
257 total
+= num_top_row_keys
;
260 /* Write out keymap for numeric keypad, if the keyboard has it */
261 if (has_numeric_keypad
) {
262 for (i
= 0; i
< ARRAY_SIZE(numeric_keypad_keymaps
); i
++) {
263 keymap
= numeric_keypad_keymaps
[i
];
264 acpi_dp_add_integer(dp_array
, NULL
, keymap
);
267 total
+= ARRAY_SIZE(numeric_keypad_keymaps
);
270 /* Provide keymap for screenlock only if it is present */
271 if (has_scrnlock_key
) {
272 acpi_dp_add_integer(dp_array
, NULL
, KEYMAP(0x5d, KEY_SLEEP
));
276 /* Add the keymap for the assistant key if present */
277 if (has_assistant_key
) {
278 acpi_dp_add_integer(dp_array
, NULL
, KEYMAP(0x5c, KEY_ASSISTANT
));
282 /* Provide alphanumeric and punctuation keys (rest of the keyboard) if
285 if (has_alpha_num_punct_keys
) {
286 for (i
= 0; i
< ARRAY_SIZE(rest_of_keymaps
); i
++) {
287 keymap
= rest_of_keymaps
[i
];
288 acpi_dp_add_integer(dp_array
, NULL
, keymap
);
291 total
+= ARRAY_SIZE(rest_of_keymaps
);
294 printk(BIOS_INFO
, "PS2K: Passing %u keymaps to kernel\n", total
);
296 acpi_dp_add_array(dp
, dp_array
);
299 void acpigen_ps2_keyboard_dsd(const char *scope
, uint8_t num_top_row_keys
,
300 enum ps2_action_key action_keys
[],
301 bool can_send_function_keys
,
302 bool has_numeric_keypad
,
303 bool has_scrnlock_key
,
304 bool has_assistant_key
,
305 bool has_alpha_num_punct_keys
)
310 num_top_row_keys
< PS2_MIN_TOP_ROW_KEYS
||
311 num_top_row_keys
> PS2_MAX_TOP_ROW_KEYS
) {
312 printk(BIOS_ERR
, "PS2K: %s: invalid args\n", __func__
);
316 dsd
= acpi_dp_new_table("_DSD");
318 printk(BIOS_ERR
, "PS2K: couldn't write _DSD\n");
322 acpigen_write_scope(scope
);
323 ssdt_generate_physmap(dsd
, num_top_row_keys
, action_keys
);
324 ssdt_generate_keymap(dsd
, num_top_row_keys
, action_keys
,
325 can_send_function_keys
, has_numeric_keypad
,
326 has_scrnlock_key
, has_assistant_key
,
327 has_alpha_num_punct_keys
);
329 acpigen_pop_len(); /* Scope */