Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
  4
  5#include <linux/crc8.h>
  6#include <linux/delay.h>
  7#include <linux/err.h>
  8#include <linux/i2c.h>
  9#include <linux/input.h>
 10#include <linux/input/matrix_keypad.h>
 11#include <linux/interrupt.h>
 12#include <linux/module.h>
 13#include <linux/mod_devicetable.h>
 14#include <linux/of.h>
 15#include <linux/regulator/consumer.h>
 16#include <linux/types.h>
 17
 18#define DRV_NAME			"pinephone-keyboard"
 19
 20#define PPKB_CRC8_POLYNOMIAL		0x07
 21
 22#define PPKB_DEVICE_ID_HI		0x00
 23#define PPKB_DEVICE_ID_HI_VALUE			'K'
 24#define PPKB_DEVICE_ID_LO		0x01
 25#define PPKB_DEVICE_ID_LO_VALUE			'B'
 26#define PPKB_FW_REVISION		0x02
 27#define PPKB_FW_FEATURES		0x03
 28#define PPKB_MATRIX_SIZE		0x06
 29#define PPKB_SCAN_CRC			0x07
 30#define PPKB_SCAN_DATA			0x08
 31#define PPKB_SYS_CONFIG			0x20
 32#define PPKB_SYS_CONFIG_DISABLE_SCAN		BIT(0)
 33#define PPKB_SYS_SMBUS_COMMAND		0x21
 34#define PPKB_SYS_SMBUS_DATA		0x22
 35#define PPKB_SYS_COMMAND		0x23
 36#define PPKB_SYS_COMMAND_SMBUS_READ		0x91
 37#define PPKB_SYS_COMMAND_SMBUS_WRITE		0xa1
 38
 39#define PPKB_ROWS			6
 40#define PPKB_COLS			12
 41
 42/* Size of the scan buffer, including the CRC byte at the beginning. */
 43#define PPKB_BUF_LEN			(1 + PPKB_COLS)
 44
 45static const uint32_t ppkb_keymap[] = {
 46	KEY(0,  0, KEY_ESC),
 47	KEY(0,  1, KEY_1),
 48	KEY(0,  2, KEY_2),
 49	KEY(0,  3, KEY_3),
 50	KEY(0,  4, KEY_4),
 51	KEY(0,  5, KEY_5),
 52	KEY(0,  6, KEY_6),
 53	KEY(0,  7, KEY_7),
 54	KEY(0,  8, KEY_8),
 55	KEY(0,  9, KEY_9),
 56	KEY(0, 10, KEY_0),
 57	KEY(0, 11, KEY_BACKSPACE),
 58
 59	KEY(1,  0, KEY_TAB),
 60	KEY(1,  1, KEY_Q),
 61	KEY(1,  2, KEY_W),
 62	KEY(1,  3, KEY_E),
 63	KEY(1,  4, KEY_R),
 64	KEY(1,  5, KEY_T),
 65	KEY(1,  6, KEY_Y),
 66	KEY(1,  7, KEY_U),
 67	KEY(1,  8, KEY_I),
 68	KEY(1,  9, KEY_O),
 69	KEY(1, 10, KEY_P),
 70	KEY(1, 11, KEY_ENTER),
 71
 72	KEY(2,  0, KEY_LEFTMETA),
 73	KEY(2,  1, KEY_A),
 74	KEY(2,  2, KEY_S),
 75	KEY(2,  3, KEY_D),
 76	KEY(2,  4, KEY_F),
 77	KEY(2,  5, KEY_G),
 78	KEY(2,  6, KEY_H),
 79	KEY(2,  7, KEY_J),
 80	KEY(2,  8, KEY_K),
 81	KEY(2,  9, KEY_L),
 82	KEY(2, 10, KEY_SEMICOLON),
 83
 84	KEY(3,  0, KEY_LEFTSHIFT),
 85	KEY(3,  1, KEY_Z),
 86	KEY(3,  2, KEY_X),
 87	KEY(3,  3, KEY_C),
 88	KEY(3,  4, KEY_V),
 89	KEY(3,  5, KEY_B),
 90	KEY(3,  6, KEY_N),
 91	KEY(3,  7, KEY_M),
 92	KEY(3,  8, KEY_COMMA),
 93	KEY(3,  9, KEY_DOT),
 94	KEY(3, 10, KEY_SLASH),
 95
 96	KEY(4,  1, KEY_LEFTCTRL),
 97	KEY(4,  4, KEY_SPACE),
 98	KEY(4,  6, KEY_APOSTROPHE),
 99	KEY(4,  8, KEY_RIGHTBRACE),
100	KEY(4,  9, KEY_LEFTBRACE),
101
102	KEY(5,  2, KEY_FN),
103	KEY(5,  3, KEY_LEFTALT),
104	KEY(5,  5, KEY_RIGHTALT),
105
106	/* FN layer */
107	KEY(PPKB_ROWS + 0,  0, KEY_FN_ESC),
108	KEY(PPKB_ROWS + 0,  1, KEY_F1),
109	KEY(PPKB_ROWS + 0,  2, KEY_F2),
110	KEY(PPKB_ROWS + 0,  3, KEY_F3),
111	KEY(PPKB_ROWS + 0,  4, KEY_F4),
112	KEY(PPKB_ROWS + 0,  5, KEY_F5),
113	KEY(PPKB_ROWS + 0,  6, KEY_F6),
114	KEY(PPKB_ROWS + 0,  7, KEY_F7),
115	KEY(PPKB_ROWS + 0,  8, KEY_F8),
116	KEY(PPKB_ROWS + 0,  9, KEY_F9),
117	KEY(PPKB_ROWS + 0, 10, KEY_F10),
118	KEY(PPKB_ROWS + 0, 11, KEY_DELETE),
119
120	KEY(PPKB_ROWS + 1, 10, KEY_PAGEUP),
121
122	KEY(PPKB_ROWS + 2,  0, KEY_SYSRQ),
123	KEY(PPKB_ROWS + 2,  9, KEY_PAGEDOWN),
124	KEY(PPKB_ROWS + 2, 10, KEY_INSERT),
125
126	KEY(PPKB_ROWS + 3,  0, KEY_LEFTSHIFT),
127	KEY(PPKB_ROWS + 3,  8, KEY_HOME),
128	KEY(PPKB_ROWS + 3,  9, KEY_UP),
129	KEY(PPKB_ROWS + 3, 10, KEY_END),
130
131	KEY(PPKB_ROWS + 4, 1, KEY_LEFTCTRL),
132	KEY(PPKB_ROWS + 4, 6, KEY_LEFT),
133	KEY(PPKB_ROWS + 4, 8, KEY_RIGHT),
134	KEY(PPKB_ROWS + 4, 9, KEY_DOWN),
135
136	KEY(PPKB_ROWS + 5, 3, KEY_LEFTALT),
137	KEY(PPKB_ROWS + 5, 5, KEY_RIGHTALT),
138};
139
140static const struct matrix_keymap_data ppkb_keymap_data = {
141	.keymap		= ppkb_keymap,
142	.keymap_size	= ARRAY_SIZE(ppkb_keymap),
143};
144
145struct pinephone_keyboard {
146	struct i2c_adapter adapter;
147	struct input_dev *input;
148	u8 buf[2][PPKB_BUF_LEN];
149	u8 crc_table[CRC8_TABLE_SIZE];
150	u8 fn_state[PPKB_COLS];
151	bool buf_swap;
152	bool fn_pressed;
153};
154
155static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr,
156				unsigned short flags, char read_write,
157				u8 command, int size,
158				union i2c_smbus_data *data)
159{
160	struct i2c_client *client = adap->algo_data;
161	u8 buf[3];
162	int ret;
163
164	buf[0] = command;
165	buf[1] = data->byte;
166	buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ
167					      : PPKB_SYS_COMMAND_SMBUS_WRITE;
168
169	ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND,
170					     sizeof(buf), buf);
171	if (ret)
172		return ret;
173
174	/* Read back the command status until it passes or fails. */
175	do {
176		usleep_range(300, 500);
177		ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND);
178	} while (ret == buf[2]);
179	if (ret < 0)
180		return ret;
181	/* Commands return 0x00 on success and 0xff on failure. */
182	if (ret)
183		return -EIO;
184
185	if (read_write == I2C_SMBUS_READ) {
186		ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA);
187		if (ret < 0)
188			return ret;
189
190		data->byte = ret;
191	}
192
193	return 0;
194}
195
196static u32 ppkg_adap_functionality(struct i2c_adapter *adap)
197{
198	return I2C_FUNC_SMBUS_BYTE_DATA;
199}
200
201static const struct i2c_algorithm ppkb_adap_algo = {
202	.smbus_xfer		= ppkb_adap_smbus_xfer,
203	.functionality		= ppkg_adap_functionality,
204};
205
206static void ppkb_update(struct i2c_client *client)
207{
208	struct pinephone_keyboard *ppkb = i2c_get_clientdata(client);
209	unsigned short *keymap = ppkb->input->keycode;
210	int row_shift = get_count_order(PPKB_COLS);
211	u8 *old_buf = ppkb->buf[!ppkb->buf_swap];
212	u8 *new_buf = ppkb->buf[ppkb->buf_swap];
213	int col, crc, ret, row;
214	struct device *dev = &client->dev;
215
216	ret = i2c_smbus_read_i2c_block_data(client, PPKB_SCAN_CRC,
217					    PPKB_BUF_LEN, new_buf);
218	if (ret != PPKB_BUF_LEN) {
219		dev_err(dev, "Failed to read scan data: %d\n", ret);
220		return;
221	}
222
223	crc = crc8(ppkb->crc_table, &new_buf[1], PPKB_COLS, CRC8_INIT_VALUE);
224	if (crc != new_buf[0]) {
225		dev_err(dev, "Bad scan data (%02x != %02x)\n", crc, new_buf[0]);
226		return;
227	}
228
229	ppkb->buf_swap = !ppkb->buf_swap;
230
231	for (col = 0; col < PPKB_COLS; ++col) {
232		u8 old = old_buf[1 + col];
233		u8 new = new_buf[1 + col];
234		u8 changed = old ^ new;
235
236		if (!changed)
237			continue;
238
239		for (row = 0; row < PPKB_ROWS; ++row) {
240			u8 mask = BIT(row);
241			u8 value = new & mask;
242			unsigned short code;
243			bool fn_state;
244
245			if (!(changed & mask))
246				continue;
247
248			/*
249			 * Save off the FN key state when the key was pressed,
250			 * and use that to determine the code during a release.
251			 */
252			fn_state = value ? ppkb->fn_pressed : ppkb->fn_state[col] & mask;
253			if (fn_state)
254				ppkb->fn_state[col] ^= mask;
255
256			/* The FN layer is a second set of rows. */
257			code = MATRIX_SCAN_CODE(fn_state ? PPKB_ROWS + row : row,
258						col, row_shift);
259			input_event(ppkb->input, EV_MSC, MSC_SCAN, code);
260			input_report_key(ppkb->input, keymap[code], value);
261			if (keymap[code] == KEY_FN)
262				ppkb->fn_pressed = value;
263		}
264	}
265	input_sync(ppkb->input);
266}
267
268static irqreturn_t ppkb_irq_thread(int irq, void *data)
269{
270	struct i2c_client *client = data;
271
272	ppkb_update(client);
273
274	return IRQ_HANDLED;
275}
276
277static int ppkb_set_scan(struct i2c_client *client, bool enable)
278{
279	struct device *dev = &client->dev;
280	int ret, val;
281
282	ret = i2c_smbus_read_byte_data(client, PPKB_SYS_CONFIG);
283	if (ret < 0) {
284		dev_err(dev, "Failed to read config: %d\n", ret);
285		return ret;
286	}
287
288	if (enable)
289		val = ret & ~PPKB_SYS_CONFIG_DISABLE_SCAN;
290	else
291		val = ret | PPKB_SYS_CONFIG_DISABLE_SCAN;
292
293	ret = i2c_smbus_write_byte_data(client, PPKB_SYS_CONFIG, val);
294	if (ret) {
295		dev_err(dev, "Failed to write config: %d\n", ret);
296		return ret;
297	}
298
299	return 0;
300}
301
302static int ppkb_open(struct input_dev *input)
303{
304	struct i2c_client *client = input_get_drvdata(input);
305	int error;
306
307	error = ppkb_set_scan(client, true);
308	if (error)
309		return error;
310
311	return 0;
312}
313
314static void ppkb_close(struct input_dev *input)
315{
316	struct i2c_client *client = input_get_drvdata(input);
317
318	ppkb_set_scan(client, false);
319}
320
321static int ppkb_probe(struct i2c_client *client)
322{
323	struct device *dev = &client->dev;
324	unsigned int phys_rows, phys_cols;
325	struct pinephone_keyboard *ppkb;
326	u8 info[PPKB_MATRIX_SIZE + 1];
327	struct device_node *i2c_bus;
328	int ret;
329	int error;
330
331	error = devm_regulator_get_enable(dev, "vbat");
332	if (error) {
333		dev_err(dev, "Failed to get VBAT supply: %d\n", error);
334		return error;
335	}
336
337	ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info);
338	if (ret != sizeof(info)) {
339		error = ret < 0 ? ret : -EIO;
340		dev_err(dev, "Failed to read device ID: %d\n", error);
341		return error;
342	}
343
344	if (info[PPKB_DEVICE_ID_HI] != PPKB_DEVICE_ID_HI_VALUE ||
345	    info[PPKB_DEVICE_ID_LO] != PPKB_DEVICE_ID_LO_VALUE) {
346		dev_warn(dev, "Unexpected device ID: %#02x %#02x\n",
347			 info[PPKB_DEVICE_ID_HI], info[PPKB_DEVICE_ID_LO]);
348		return -ENODEV;
349	}
350
351	dev_info(dev, "Found firmware version %d.%d features %#x\n",
352		 info[PPKB_FW_REVISION] >> 4,
353		 info[PPKB_FW_REVISION] & 0xf,
354		 info[PPKB_FW_FEATURES]);
355
356	phys_rows = info[PPKB_MATRIX_SIZE] & 0xf;
357	phys_cols = info[PPKB_MATRIX_SIZE] >> 4;
358	if (phys_rows != PPKB_ROWS || phys_cols != PPKB_COLS) {
359		dev_err(dev, "Unexpected keyboard size %ux%u\n",
360			phys_rows, phys_cols);
361		return -EINVAL;
362	}
363
364	/* Disable scan by default to save power. */
365	error = ppkb_set_scan(client, false);
366	if (error)
367		return error;
368
369	ppkb = devm_kzalloc(dev, sizeof(*ppkb), GFP_KERNEL);
370	if (!ppkb)
371		return -ENOMEM;
372
373	i2c_set_clientdata(client, ppkb);
374
375	i2c_bus = of_get_child_by_name(dev->of_node, "i2c");
376	if (i2c_bus) {
377		ppkb->adapter.owner = THIS_MODULE;
378		ppkb->adapter.algo = &ppkb_adap_algo;
379		ppkb->adapter.algo_data = client;
380		ppkb->adapter.dev.parent = dev;
381		ppkb->adapter.dev.of_node = i2c_bus;
382		strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name));
383
384		error = devm_i2c_add_adapter(dev, &ppkb->adapter);
385		if (error) {
386			dev_err(dev, "Failed to add I2C adapter: %d\n", error);
387			return error;
388		}
389	}
390
391	crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL);
392
393	ppkb->input = devm_input_allocate_device(dev);
394	if (!ppkb->input)
395		return -ENOMEM;
396
397	input_set_drvdata(ppkb->input, client);
398
399	ppkb->input->name = "PinePhone Keyboard";
400	ppkb->input->phys = DRV_NAME "/input0";
401	ppkb->input->id.bustype = BUS_I2C;
402	ppkb->input->open = ppkb_open;
403	ppkb->input->close = ppkb_close;
404
405	input_set_capability(ppkb->input, EV_MSC, MSC_SCAN);
406	__set_bit(EV_REP, ppkb->input->evbit);
407
408	error = matrix_keypad_build_keymap(&ppkb_keymap_data, NULL,
409					   2 * PPKB_ROWS, PPKB_COLS, NULL,
410					   ppkb->input);
411	if (error) {
412		dev_err(dev, "Failed to build keymap: %d\n", error);
413		return error;
414	}
415
416	error = input_register_device(ppkb->input);
417	if (error) {
418		dev_err(dev, "Failed to register input: %d\n", error);
419		return error;
420	}
421
422	error = devm_request_threaded_irq(dev, client->irq,
423					  NULL, ppkb_irq_thread,
424					  IRQF_ONESHOT, client->name, client);
425	if (error) {
426		dev_err(dev, "Failed to request IRQ: %d\n", error);
427		return error;
428	}
429
430	return 0;
431}
432
433static const struct of_device_id ppkb_of_match[] = {
434	{ .compatible = "pine64,pinephone-keyboard" },
435	{ }
436};
437MODULE_DEVICE_TABLE(of, ppkb_of_match);
438
439static struct i2c_driver ppkb_driver = {
440	.probe		= ppkb_probe,
441	.driver		= {
442		.name		= DRV_NAME,
443		.of_match_table = ppkb_of_match,
444	},
445};
446module_i2c_driver(ppkb_driver);
447
448MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
449MODULE_DESCRIPTION("Pine64 PinePhone keyboard driver");
450MODULE_LICENSE("GPL");
1