summaryrefslogtreecommitdiff
path: root/src/acpi/acpigen_ps2_keybd.c
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@google.com>2020-04-30 19:13:47 -0700
committerFurquan Shaikh <furquan@google.com>2020-05-02 18:39:40 +0000
commit6cc1e9e81efe794eb4ef0d0586fa7b8351577aba (patch)
tree6e0f8bd29c4ee6303a66ad964b993b08930f2f93 /src/acpi/acpigen_ps2_keybd.c
parenta298668b99d0c8ac3b2d801e5ddce936062f0e9b (diff)
acpi: Move ACPI table support out of arch/x86 (1/5)
This change moves all ACPI table support in coreboot currently living under arch/x86 into common code to make it architecture independent. ACPI table generation is not really tied to any architecture and hence it makes sense to move this to its own directory. In order to make it easier to review, this change is being split into multiple CLs. This is change 1/5 which moves .c files from arch/x86 to acpi/. The only acpi files that are still retained under arch/x86 are: a. acpi_s3.c: This doesn't really deal with ACPI tables. Also, there are some assumptions in there about SMM which will have to be resolved if this file needs to be moved to common code. b. acpi_bert_storage.c/bert_storage.h: This file is currently written specifically with x86 in mind. So, not moving the file for now. Motivation for this change: Not all stages on Picasso SoC are targeted for the same architecture. For example, verstage (if runs before bootblock) will be targeted for non-x86. This makes it difficult to add device tree to verstage which would be required to get to SoC configs from the tree. This is because the device tree on x86 platforms currently contains a lot of devices that require ACPI related enums and structs (like acpi_gpio, acpi_pld, acpi_dp and so on). Hence, this change removes all ACPI table support out of arch/x86. BUG=b:155428745 Change-Id: Icc6b793c52c86483a8c52e0555619e36869a869e Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/40930 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'src/acpi/acpigen_ps2_keybd.c')
-rw-r--r--src/acpi/acpigen_ps2_keybd.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/acpi/acpigen_ps2_keybd.c b/src/acpi/acpigen_ps2_keybd.c
new file mode 100644
index 0000000000..7943f9a158
--- /dev/null
+++ b/src/acpi/acpigen_ps2_keybd.c
@@ -0,0 +1,302 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <arch/acpigen_ps2_keybd.h>
+#include <console/console.h>
+#include <input-event-codes.h>
+
+#define KEYMAP(scancode, keycode) (((uint32_t)(scancode) << 16) | (keycode & 0xFFFF))
+#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
+
+/* Possible keymaps for function keys in the top row */
+static const uint32_t function_keymaps[] = {
+ KEYMAP(0x3b, KEY_F1),
+ KEYMAP(0x3c, KEY_F2),
+ KEYMAP(0x3d, KEY_F3),
+ KEYMAP(0x3e, KEY_F4),
+ KEYMAP(0x3f, KEY_F5),
+ KEYMAP(0x40, KEY_F6),
+ KEYMAP(0x41, KEY_F7),
+ KEYMAP(0x42, KEY_F8),
+ KEYMAP(0x43, KEY_F9),
+ KEYMAP(0x44, KEY_F10),
+ KEYMAP(0x57, KEY_F11),
+ KEYMAP(0x58, KEY_F12),
+ KEYMAP(0x59, KEY_F13),
+ KEYMAP(0x5a, KEY_F14),
+ KEYMAP(0x5b, KEY_F15),
+};
+
+/*
+ * Possible keymaps for action keys in the top row. This is a superset of
+ * possible keys. Individual keyboards will have a subset of these keys.
+ * The scancodes are true / condensed 1 byte scancodes from set-1
+ */
+static const uint32_t action_keymaps[] = {
+ [PS2_KEY_BACK] = KEYMAP(0xea, KEY_BACK), /* e06a */
+ [PS2_KEY_FORWARD] = KEYMAP(0xe9, KEY_FORWARD), /* e069 */
+ [PS2_KEY_REFRESH] = KEYMAP(0xe7, KEY_REFRESH), /* e067 */
+ [PS2_KEY_FULLSCREEN] = KEYMAP(0x91, KEY_FULL_SCREEN), /* e011 */
+ [PS2_KEY_OVERVIEW] = KEYMAP(0x92, KEY_SCALE), /* e012 */
+ [PS2_KEY_VOL_MUTE] = KEYMAP(0xa0, KEY_MUTE), /* e020 */
+ [PS2_KEY_VOL_DOWN] = KEYMAP(0xae, KEY_VOLUMEDOWN), /* e02e */
+ [PS2_KEY_VOL_UP] = KEYMAP(0xb0, KEY_VOLUMEUP), /* e030 */
+ [PS2_KEY_PLAY_PAUSE] = KEYMAP(0x9a, KEY_PLAYPAUSE), /* e01a */
+ [PS2_KEY_NEXT_TRACK] = KEYMAP(0x99, KEY_NEXTSONG), /* e019 */
+ [PS2_KEY_PREV_TRACK] = KEYMAP(0x90, KEY_PREVIOUSSONG), /* e010 */
+ [PS2_KEY_SNAPSHOT] = KEYMAP(0x93, KEY_SYSRQ), /* e013 */
+ [PS2_KEY_BRIGHTNESS_DOWN] = KEYMAP(0x94, KEY_BRIGHTNESSDOWN),/* e014 */
+ [PS2_KEY_BRIGHTNESS_UP] = KEYMAP(0x95, KEY_BRIGHTNESSUP), /* e015 */
+ [PS2_KEY_KBD_BKLIGHT_DOWN] = KEYMAP(0x97, KEY_KBDILLUMDOWN), /* e017 */
+ [PS2_KEY_KBD_BKLIGHT_UP] = KEYMAP(0x98, KEY_KBDILLUMUP), /* e018 */
+ [PS2_KEY_PRIVACY_SCRN_TOGGLE] = KEYMAP(0x96, /* e016 */
+ KEY_PRIVACY_SCREEN_TOGGLE),
+};
+
+/* Keymap for numeric keypad keys */
+static uint32_t numeric_keypad_keymaps[] = {
+ /* Row-0 */
+ KEYMAP(0xc9, KEY_PAGEUP),
+ KEYMAP(0xd1, KEY_PAGEDOWN),
+ KEYMAP(0xc7, KEY_HOME),
+ KEYMAP(0xcf, KEY_END),
+ /* Row-1 */
+ KEYMAP(0xd3, KEY_DELETE),
+ KEYMAP(0xb5, KEY_KPSLASH),
+ KEYMAP(0x37, KEY_KPASTERISK),
+ KEYMAP(0x4a, KEY_KPMINUS),
+ /* Row-2 */
+ KEYMAP(0x47, KEY_KP7),
+ KEYMAP(0x48, KEY_KP8),
+ KEYMAP(0x49, KEY_KP9),
+ KEYMAP(0x4e, KEY_KPPLUS),
+ /* Row-3 */
+ KEYMAP(0x4b, KEY_KP4),
+ KEYMAP(0x4c, KEY_KP5),
+ KEYMAP(0x4d, KEY_KP6),
+ /* Row-4 */
+ KEYMAP(0x4f, KEY_KP1),
+ KEYMAP(0x50, KEY_KP2),
+ KEYMAP(0x51, KEY_KP3),
+ KEYMAP(0x9c, KEY_KPENTER),
+ /* Row-5 */
+ KEYMAP(0x52, KEY_KP0),
+ KEYMAP(0x53, KEY_KPDOT),
+};
+
+/*
+ * Keymap for rest of non-top-row keys. This is a superset of all the possible
+ * keys that any chromeos keyboards can have.
+ */
+static uint32_t rest_of_keymaps[] = {
+ /* Row-0 */
+ KEYMAP(0x01, KEY_ESC),
+ /* Row-1 */
+ KEYMAP(0x29, KEY_GRAVE),
+ KEYMAP(0x02, KEY_1),
+ KEYMAP(0x03, KEY_2),
+ KEYMAP(0x04, KEY_3),
+ KEYMAP(0x05, KEY_4),
+ KEYMAP(0x06, KEY_5),
+ KEYMAP(0x07, KEY_6),
+ KEYMAP(0x08, KEY_7),
+ KEYMAP(0x09, KEY_8),
+ KEYMAP(0x0a, KEY_9),
+ KEYMAP(0x0b, KEY_0),
+ KEYMAP(0x0c, KEY_MINUS),
+ KEYMAP(0x0d, KEY_EQUAL),
+ KEYMAP(0x7d, KEY_YEN), /* JP keyboards only */
+ KEYMAP(0x0e, KEY_BACKSPACE),
+ /* Row-2 */
+ KEYMAP(0x0f, KEY_TAB),
+ KEYMAP(0x10, KEY_Q),
+ KEYMAP(0x11, KEY_W),
+ KEYMAP(0x12, KEY_E),
+ KEYMAP(0x13, KEY_R),
+ KEYMAP(0x14, KEY_T),
+ KEYMAP(0x15, KEY_Y),
+ KEYMAP(0x16, KEY_U),
+ KEYMAP(0x17, KEY_I),
+ KEYMAP(0x18, KEY_O),
+ KEYMAP(0x19, KEY_P),
+ KEYMAP(0x1a, KEY_LEFTBRACE),
+ KEYMAP(0x1b, KEY_RIGHTBRACE),
+ KEYMAP(0x2b, KEY_BACKSLASH),
+ /* Row-3 */
+ KEYMAP(0xdb, KEY_LEFTMETA), /* Search Key */
+ KEYMAP(0x1e, KEY_A),
+ KEYMAP(0x1f, KEY_S),
+ KEYMAP(0x20, KEY_D),
+ KEYMAP(0x21, KEY_F),
+ KEYMAP(0x22, KEY_G),
+ KEYMAP(0x23, KEY_H),
+ KEYMAP(0x24, KEY_J),
+ KEYMAP(0x25, KEY_K),
+ KEYMAP(0x26, KEY_L),
+ KEYMAP(0x27, KEY_SEMICOLON),
+ KEYMAP(0x28, KEY_APOSTROPHE),
+ KEYMAP(0x1c, KEY_ENTER),
+ /* Row-4 */
+ KEYMAP(0x2a, KEY_LEFTSHIFT),
+ KEYMAP(0x56, KEY_102ND), /* UK keyboards only */
+ KEYMAP(0x2c, KEY_Z),
+ KEYMAP(0x2d, KEY_X),
+ KEYMAP(0x2e, KEY_C),
+ KEYMAP(0x2f, KEY_V),
+ KEYMAP(0x30, KEY_B),
+ KEYMAP(0x31, KEY_N),
+ KEYMAP(0x32, KEY_M),
+ KEYMAP(0x33, KEY_COMMA),
+ KEYMAP(0x34, KEY_DOT),
+ KEYMAP(0x35, KEY_SLASH),
+ KEYMAP(0x73, KEY_RO), /* JP keyboards only */
+ KEYMAP(0x36, KEY_RIGHTSHIFT),
+ /* Row-5 */
+ KEYMAP(0x1d, KEY_LEFTCTRL),
+ KEYMAP(0x38, KEY_LEFTALT),
+ KEYMAP(0x7b, KEY_MUHENKAN), /* JP keyboards only */
+ KEYMAP(0x39, KEY_SPACE),
+ KEYMAP(0x79, KEY_HENKAN), /* JP keyboards only */
+ KEYMAP(0xb8, KEY_RIGHTALT),
+ KEYMAP(0x9d, KEY_RIGHTCTRL),
+ /* Arrow keys */
+ KEYMAP(0xcb, KEY_LEFT),
+ KEYMAP(0xd0, KEY_DOWN),
+ KEYMAP(0xcd, KEY_RIGHT),
+ KEYMAP(0xc8, KEY_UP),
+};
+
+static void ssdt_generate_physmap(struct acpi_dp *dp, uint8_t num_top_row_keys,
+ enum ps2_action_key action_keys[])
+{
+ struct acpi_dp *dp_array;
+ enum ps2_action_key key;
+ uint32_t keymap, i;
+
+ dp_array = acpi_dp_new_table("function-row-physmap");
+ if (!dp_array) {
+ printk(BIOS_ERR, "PS2K: couldn't write function-row-physmap\n");
+ return;
+ }
+
+ printk(BIOS_INFO, "PS2K: Physmap: [");
+ for (i = 0; i < num_top_row_keys; i++) {
+ key = action_keys[i];
+ if (key && key < ARRAY_SIZE(action_keymaps)) {
+ keymap = action_keymaps[key];
+ } else {
+ keymap = 0;
+ printk(BIOS_ERR,
+ "PS2K: invalid top-action-key-%u: %u(skipped)\n",
+ i, key);
+ }
+ acpi_dp_add_integer(dp_array, NULL, SCANCODE(keymap));
+ printk(BIOS_INFO, " %X", SCANCODE(keymap));
+ }
+
+ printk(BIOS_INFO, " ]\n");
+ acpi_dp_add_array(dp, dp_array);
+}
+
+static void ssdt_generate_keymap(struct acpi_dp *dp, uint8_t num_top_row_keys,
+ enum ps2_action_key action_keys[],
+ bool can_send_function_keys,
+ bool has_numeric_keypad,
+ bool has_scrnlock_key)
+{
+ struct acpi_dp *dp_array;
+ enum ps2_action_key key;
+ uint32_t keymap;
+ unsigned int i, total = 0;
+
+ dp_array = acpi_dp_new_table("linux,keymap");
+ if (!dp_array) {
+ printk(BIOS_ERR, "PS2K: couldn't write linux,keymap\n");
+ return;
+ }
+
+ /* Write out keymap for top row action keys */
+ for (i = 0; i < num_top_row_keys; i++) {
+ key = action_keys[i];
+ if (!key || key >= ARRAY_SIZE(action_keymaps)) {
+ printk(BIOS_ERR,
+ "PS2K: invalid top-action-key-%u: %u\n", i, key);
+ continue;
+ }
+ keymap = action_keymaps[key];
+ acpi_dp_add_integer(dp_array, NULL, keymap);
+ total++;
+ }
+
+ /* Write out keymap for function keys, if keyboard can send them */
+ if (can_send_function_keys) {
+ for (i = 0; i < num_top_row_keys; i++) {
+ keymap = function_keymaps[i];
+ acpi_dp_add_integer(dp_array, NULL, keymap);
+ }
+
+ total += num_top_row_keys;
+ }
+
+ /* Write out keymap for numeric keypad, if the keyboard has it */
+ if (has_numeric_keypad) {
+ for (i = 0; i < ARRAY_SIZE(numeric_keypad_keymaps); i++) {
+ keymap = numeric_keypad_keymaps[i];
+ acpi_dp_add_integer(dp_array, NULL, keymap);
+ }
+
+ total += ARRAY_SIZE(numeric_keypad_keymaps);
+ }
+
+ /* Provide keymap for screenlock only if it is present */
+ if (has_scrnlock_key) {
+ acpi_dp_add_integer(dp_array, NULL, KEYMAP(0x5d, KEY_SLEEP));
+ total++;
+ }
+
+ /* Write out keymap for rest of keys */
+ for (i = 0; i < ARRAY_SIZE(rest_of_keymaps); i++) {
+ keymap = rest_of_keymaps[i];
+ acpi_dp_add_integer(dp_array, NULL, keymap);
+ }
+
+ total += ARRAY_SIZE(rest_of_keymaps);
+ printk(BIOS_INFO, "PS2K: Passing %u keymaps to kernel\n", total);
+
+ acpi_dp_add_array(dp, dp_array);
+}
+
+void acpigen_ps2_keyboard_dsd(const char *scope, uint8_t num_top_row_keys,
+ enum ps2_action_key action_keys[],
+ bool can_send_function_keys,
+ bool has_numeric_keypad,
+ bool has_scrnlock_key)
+{
+ struct acpi_dp *dsd;
+
+ if (!scope ||
+ num_top_row_keys < PS2_MIN_TOP_ROW_KEYS ||
+ num_top_row_keys > PS2_MAX_TOP_ROW_KEYS) {
+ printk(BIOS_ERR, "PS2K: %s: invalid args\n", __func__);
+ return;
+ }
+
+ dsd = acpi_dp_new_table("_DSD");
+ if (!dsd) {
+ printk(BIOS_ERR, "PS2K: couldn't write _DSD\n");
+ return;
+ }
+
+ acpigen_write_scope(scope);
+ ssdt_generate_physmap(dsd, num_top_row_keys, action_keys);
+ ssdt_generate_keymap(dsd, num_top_row_keys, action_keys,
+ can_send_function_keys, has_numeric_keypad,
+ has_scrnlock_key);
+ acpi_dp_write(dsd);
+ acpigen_pop_len(); /* Scope */
+}