/*
 * Chromium OS Matrix Keyboard
 *
 * Copyright (c) 2012 The Chromium OS Authors.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <cros_ec.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <input.h>
#include <keyboard.h>
#include <key_matrix.h>
#include <stdio_dev.h>

DECLARE_GLOBAL_DATA_PTR;

enum {
	KBC_MAX_KEYS		= 8,	/* Maximum keys held down at once */
	KBC_REPEAT_RATE_MS	= 30,
	KBC_REPEAT_DELAY_MS	= 240,
};

struct cros_ec_keyb_priv {
	struct input_config *input;	/* The input layer */
	struct key_matrix matrix;	/* The key matrix layer */
	int key_rows;			/* Number of keyboard rows */
	int key_cols;			/* Number of keyboard columns */
	int ghost_filter;		/* 1 to enable ghost filter, else 0 */
};


/**
 * Check the keyboard controller and return a list of key matrix positions
 * for which a key is pressed
 *
 * @param dev		Keyboard device
 * @param keys		List of keys that we have detected
 * @param max_count	Maximum number of keys to return
 * @param samep		Set to true if this scan repeats the last, else false
 * @return number of pressed keys, 0 for none, -EIO on error
 */
static int check_for_keys(struct udevice *dev, struct key_matrix_key *keys,
			  int max_count, bool *samep)
{
	struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
	struct key_matrix_key *key;
	static struct mbkp_keyscan last_scan;
	static bool last_scan_valid;
	struct mbkp_keyscan scan;
	unsigned int row, col, bit, data;
	int num_keys;

	if (cros_ec_scan_keyboard(dev->parent, &scan)) {
		debug("%s: keyboard scan failed\n", __func__);
		return -EIO;
	}
	*samep = last_scan_valid && !memcmp(&last_scan, &scan, sizeof(scan));

	/*
	 * This is a bit odd. The EC has no way to tell us that it has run
	 * out of key scans. It just returns the same scan over and over
	 * again. So the only way to detect that we have run out is to detect
	 * that this scan is the same as the last.
	 */
	last_scan_valid = true;
	memcpy(&last_scan, &scan, sizeof(last_scan));

	for (col = num_keys = bit = 0; col < priv->matrix.num_cols;
			col++) {
		for (row = 0; row < priv->matrix.num_rows; row++) {
			unsigned int mask = 1 << (bit & 7);

			data = scan.data[bit / 8];
			if ((data & mask) && num_keys < max_count) {
				key = keys + num_keys++;
				key->row = row;
				key->col = col;
				key->valid = 1;
			}
			bit++;
		}
	}

	return num_keys;
}

/**
 * Check the keyboard, and send any keys that are pressed.
 *
 * This is called by input_tstc() and input_getc() when they need more
 * characters
 *
 * @param input		Input configuration
 * @return 1, to indicate that we have something to look at
 */
int cros_ec_kbc_check(struct input_config *input)
{
	struct udevice *dev = input->dev;
	struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
	static struct key_matrix_key last_keys[KBC_MAX_KEYS];
	static int last_num_keys;
	struct key_matrix_key keys[KBC_MAX_KEYS];
	int keycodes[KBC_MAX_KEYS];
	int num_keys, num_keycodes;
	int irq_pending, sent;
	bool same = false;

	/*
	 * Loop until the EC has no more keyscan records, or we have
	 * received at least one character. This means we know that tstc()
	 * will always return non-zero if keys have been pressed.
	 *
	 * Without this loop, a key release (which generates no new ascii
	 * characters) will cause us to exit this function, and just tstc()
	 * may return 0 before all keys have been read from the EC.
	 */
	do {
		irq_pending = cros_ec_interrupt_pending(dev->parent);
		if (irq_pending) {
			num_keys = check_for_keys(dev, keys, KBC_MAX_KEYS,
						  &same);
			if (num_keys < 0)
				return 0;
			last_num_keys = num_keys;
			memcpy(last_keys, keys, sizeof(keys));
		} else {
			/*
			 * EC doesn't want to be asked, so use keys from last
			 * time.
			 */
			num_keys = last_num_keys;
			memcpy(keys, last_keys, sizeof(keys));
		}

		if (num_keys < 0)
			return -1;
		num_keycodes = key_matrix_decode(&priv->matrix, keys,
				num_keys, keycodes, KBC_MAX_KEYS);
		sent = input_send_keycodes(input, keycodes, num_keycodes);

		/*
		 * For those ECs without an interrupt, stop scanning when we
		 * see that the scan is the same as last time.
		 */
		if ((irq_pending < 0) && same)
			break;
	} while (irq_pending && !sent);

	return 1;
}

/**
 * Decode MBKP keyboard details from the device tree
 *
 * @param blob		Device tree blob
 * @param node		Node to decode from
 * @param config	Configuration data read from fdt
 * @return 0 if ok, -1 on error
 */
static int cros_ec_keyb_decode_fdt(const void *blob, int node,
				struct cros_ec_keyb_priv *config)
{
	/*
	 * Get keyboard rows and columns - at present we are limited to
	 * 8 columns by the protocol (one byte per row scan)
	 */
	config->key_rows = fdtdec_get_int(blob, node, "keypad,num-rows", 0);
	config->key_cols = fdtdec_get_int(blob, node, "keypad,num-columns", 0);
	if (!config->key_rows || !config->key_cols ||
			config->key_rows * config->key_cols / 8
				> CROS_EC_KEYSCAN_COLS) {
		debug("%s: Invalid key matrix size %d x %d\n", __func__,
		      config->key_rows, config->key_cols);
		return -1;
	}
	config->ghost_filter = fdtdec_get_bool(blob, node,
					       "google,needs-ghost-filter");
	return 0;
}

static int cros_ec_kbd_probe(struct udevice *dev)
{
	struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
	struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
	struct stdio_dev *sdev = &uc_priv->sdev;
	struct input_config *input = &uc_priv->input;
	const void *blob = gd->fdt_blob;
	int node = dev->of_offset;
	int ret;

	if (cros_ec_keyb_decode_fdt(blob, node, priv))
		return -1;
	input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
	ret = key_matrix_init(&priv->matrix, priv->key_rows, priv->key_cols,
			      priv->ghost_filter);
	if (ret) {
		debug("%s: cannot init key matrix\n", __func__);
		return ret;
	}
	ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
	if (ret) {
		debug("%s: Could not decode key matrix from fdt\n", __func__);
		return ret;
	}
	debug("%s: Matrix keyboard %dx%d ready\n", __func__, priv->key_rows,
	      priv->key_cols);

	priv->input = input;
	input->dev = dev;
	input_add_tables(input, false);
	input->read_keys = cros_ec_kbc_check;
	strcpy(sdev->name, "cros-ec-keyb");

	/* Register the device. cros_ec_init_keyboard() will be called soon */
	return input_stdio_register(sdev);
}

static const struct keyboard_ops cros_ec_kbd_ops = {
};

static const struct udevice_id cros_ec_kbd_ids[] = {
	{ .compatible = "google,cros-ec-keyb" },
	{ }
};

U_BOOT_DRIVER(cros_ec_kbd) = {
	.name	= "cros_ec_kbd",
	.id	= UCLASS_KEYBOARD,
	.of_match = cros_ec_kbd_ids,
	.probe = cros_ec_kbd_probe,
	.ops	= &cros_ec_kbd_ops,
	.priv_auto_alloc_size = sizeof(struct cros_ec_keyb_priv),
};
