1.. _gpio-kbd: 2 3GPIO Keyboard Matrix 4#################### 5 6The :dtcompatible:`gpio-kbd-matrix` driver supports a large variety of keyboard 7matrix hardware configurations and has numerous options to change its behavior. 8This is an overview of some common setups and how they can be supported by the 9driver. 10 11The conventional configuration for all of these is that the driver reads on the 12row GPIOs (inputs) and selects on the columns GPIOs (output). 13 14Base use case, no isolation diodes, interrupt capable GPIOs 15*********************************************************** 16 17This is the common configuration found on consumer keyboards with membrane 18switches and flexible circuit boards, no isolation diodes, requires ghosting 19detection (which is enabled by default). 20 21.. figure:: no-diodes.svg 22 :align: center 23 :width: 50% 24 25 A 3x3 matrix, no diodes 26 27The system must support GPIO interrupts, and the interrupt can be enabled on all 28row GPIOs at the same time. 29 30.. code-block:: devicetree 31 32 kbd-matrix { 33 compatible = "gpio-kbd-matrix"; 34 row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, 35 <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, 36 <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; 37 col-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, 38 <&gpio0 4 GPIO_ACTIVE_LOW>, 39 <&gpio0 5 GPIO_ACTIVE_LOW>; 40 }; 41 42In this configuration the matrix scanning library enters idle mode once all 43keys are released, and the keyboard matrix thread only wakes up when a key has 44been pressed. 45 46GPIOs for columns that are not currently selected are configured in high 47impedance mode. This means that the row state may need some time to settle to 48avoid misreading the key state from a column to the following one. The settle 49time can be tweaked by changing the ``settle-time-us`` property. 50 51Isolation diodes 52**************** 53 54If the matrix has isolation diodes for every key, then it's possible to: 55 56 - disable ghosting detection, allowing any key combination to be detected 57 - configuring the driver to drive unselected columns GPIO to inactive state 58 rather than high impedance, this allows to reduce the settle time 59 (potentially down to 0), and use the more efficient port wide GPIO read APIs 60 (happens automatically if the GPIO pins are sequential) 61 62Matrixes with diodes going from rows to columns must use pull-ups on rows and 63active low columns. 64 65.. figure:: diodes-rc.svg 66 :align: center 67 :width: 50% 68 69 A 3x3 matrix with row to column isolation diodes. 70 71.. code-block:: devicetree 72 73 kbd-matrix { 74 compatible = "gpio-kbd-matrix"; 75 row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, 76 <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, 77 <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; 78 col-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, 79 <&gpio0 4 GPIO_ACTIVE_LOW>, 80 <&gpio0 5 GPIO_ACTIVE_LOW>; 81 col-drive-inactive; 82 settle-time-us = <0>; 83 no-ghostkey-check; 84 }; 85 86Matrixes with diodes going from columns to rows must use pull-downs on rows and 87active high columns. 88 89.. figure:: diodes-cr.svg 90 :align: center 91 :width: 50% 92 93 A 3x3 matrix with column to row isolation diodes. 94 95.. code-block:: devicetree 96 97 kbd-matrix { 98 compatible = "gpio-kbd-matrix"; 99 row-gpios = <&gpio0 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, 100 <&gpio0 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, 101 <&gpio0 2 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; 102 col-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>, 103 <&gpio0 4 GPIO_ACTIVE_HIGH>, 104 <&gpio0 5 GPIO_ACTIVE_HIGH>; 105 col-drive-inactive; 106 settle-time-us = <0>; 107 no-ghostkey-check; 108 }; 109 110GPIO with no interrupt support 111****************************** 112 113Some GPIO controllers have limitations on GPIO interrupts, and may not support 114enabling interrupts on all row GPIOs at the same time. 115 116In this case, the driver can be configured to not use interrupt at all, and 117instead idle by selecting all columns and keep polling on the row GPIOs, which 118is a single GPIO API operation if the pins are sequential. 119 120This configuration can be enabled by setting the ``idle-mode`` property to 121``poll``: 122 123.. code-block:: devicetree 124 125 kbd-matrix { 126 compatible = "gpio-kbd-matrix"; 127 ... 128 idle-mode = "poll"; 129 }; 130 131GPIO multiplexer 132**************** 133 134In more extreme cases, such as if the columns are using a multiplexer and it's 135impossible to select all of them at the same time, the driver can be configured 136to scan continuously. 137 138This can be done by setting ``idle-mode`` to ``scan`` and ``poll-timeout-ms`` 139to ``0``. 140 141.. code-block:: devicetree 142 143 kbd-matrix { 144 compatible = "gpio-kbd-matrix"; 145 ... 146 poll-timeout-ms = <0>; 147 idle-mode = "scan"; 148 }; 149 150Row and column GPIO selection 151***************************** 152 153If the row GPIOs are sequential and on the same gpio controller, the driver 154automatically switches API to read from the whole GPIO port rather than the 155individual pins. This is particularly useful if the GPIOs are not memory 156mapped, for example on an I2C or SPI port expander, as this significantly 157reduces the number of transactions on the corresponding bus. 158 159The same is true for column GPIOs, but only if the matrix is configured for 160``col-drive-inactive``, so that is only usable for matrixes with isolation 161diodes. 162 16316-bit row support 164****************** 165 166The driver uses an 8-bit datatype to store the row state by default, which 167limits the matrix row size to 8. This can be increased to 16 by enabling the 168:kconfig:option:`CONFIG_INPUT_KBD_MATRIX_16_BIT_ROW` option. 169 170Actual key mask configuration 171***************************** 172 173If the key matrix is not complete, a map of the keys that are actually 174populated can be specified using the `actual-key-mask` property. This allows 175the matrix state to be filtered to remove keys that are not present before 176ghosting detection, potentially allowing key combinations that would otherwise 177be blocked by it. 178 179For example for a 3x3 matrix missing a key: 180 181.. figure:: no-sw4.svg 182 :align: center 183 :width: 50% 184 185 A 3x3 matrix missing a key. 186 187.. code-block:: devicetree 188 189 kbd-matrix { 190 compatible = "gpio-kbd-matrix"; 191 ... 192 actual-key-mask = <0x07 0x05 0x07>; 193 }; 194 195This would allow, for example, to detect pressing ``Sw1``, ``SW2`` and ``SW4`` 196at the same time without triggering anti ghosting. 197 198The actual key mask can be changed at runtime by enabling 199:kconfig:option:`CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC` and the using the 200:c:func:`input_kbd_matrix_actual_key_mask_set` API. 201 202Keymap configuration 203******************** 204 205Keyboard matrix devices report a series of x/y/touch events. These can be 206mapped to normal key events using the :dtcompatible:`input-keymap` driver. 207 208For example, the following would setup a ``keymap`` device that take the 209x/y/touch events as an input and generate corresponding key events as an 210output: 211 212.. code-block:: devicetree 213 214 kbd { 215 ... 216 keymap { 217 compatible = "input-keymap"; 218 keymap = < 219 MATRIX_KEY(0, 0, INPUT_KEY_1) 220 MATRIX_KEY(0, 1, INPUT_KEY_2) 221 MATRIX_KEY(0, 2, INPUT_KEY_3) 222 MATRIX_KEY(1, 0, INPUT_KEY_4) 223 MATRIX_KEY(1, 1, INPUT_KEY_5) 224 MATRIX_KEY(1, 2, INPUT_KEY_6) 225 MATRIX_KEY(2, 0, INPUT_KEY_7) 226 MATRIX_KEY(2, 1, INPUT_KEY_8) 227 MATRIX_KEY(2, 2, INPUT_KEY_9) 228 >; 229 row-size = <3>; 230 col-size = <3>; 231 }; 232 }; 233 234Keyboard matrix shell commands 235****************************** 236 237The shell command ``kbd_matrix_state_dump`` can be used to test the 238functionality of any keyboard matrix driver implemented using the keyboard 239matrix library. Once enabled it logs the state of the matrix every time it 240changes, and once disabled it prints an or-mask of any key that has been 241detected, which can be used to set the ``actual-key-mask`` property. 242 243The command can be enabled using the 244:kconfig:option:`CONFIG_INPUT_SHELL_KBD_MATRIX_STATE`. 245 246Example usage: 247 248.. code-block:: console 249 250 uart:~$ device list 251 devices: 252 - kbd-matrix (READY) 253 uart:~$ input kbd_matrix_state_dump kbd-matrix 254 Keyboard state logging enabled for kbd-matrix 255 [00:01:41.678,466] <inf> input: kbd-matrix state [01 -- -- --] (1) 256 [00:01:41.784,912] <inf> input: kbd-matrix state [-- -- -- --] (0) 257 ... 258 press more buttons 259 ... 260 uart:~$ input kbd_matrix_state_dump off 261 Keyboard state logging disabled 262 [00:01:47.967,651] <inf> input: kbd-matrix key-mask [07 05 07 --] (8) 263 264Keyboard matrix library 265*********************** 266 267The GPIO keyboard matrix driver is based on a generic keyboard matrix library, 268which implements the core functionalities such as scanning delays, debouncing, 269idle mode etc. This can be reused to implement other keyboard matrix drivers, 270potentially application specific. 271 272.. doxygengroup:: input_kbd_matrix 273