diff options
Diffstat (limited to 'drivers/input/cros_ec_keyb.c')
| -rw-r--r-- | drivers/input/cros_ec_keyb.c | 34 | 
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c index e8dac237a..a2501e020 100644 --- a/drivers/input/cros_ec_keyb.c +++ b/drivers/input/cros_ec_keyb.c @@ -8,6 +8,7 @@  #include <common.h>  #include <cros_ec.h> +#include <errno.h>  #include <fdtdec.h>  #include <input.h>  #include <key_matrix.h> @@ -39,20 +40,34 @@ static struct keyb {   * @param config	Keyboard config   * @param keys		List of keys that we have detected   * @param max_count	Maximum number of keys to return - * @return number of pressed keys, 0 for none + * @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 keyb *config, -			   struct key_matrix_key *keys, int max_count) +			   struct key_matrix_key *keys, int max_count, +			   bool *samep)  {  	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(config->dev, &scan)) {  		debug("%s: keyboard scan failed\n", __func__); -		return -1; +		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 < config->matrix.num_cols;  			col++) { @@ -112,6 +127,7 @@ int cros_ec_kbc_check(struct input_config *input)  	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 @@ -125,7 +141,10 @@ int cros_ec_kbc_check(struct input_config *input)  	do {  		irq_pending = cros_ec_interrupt_pending(config.dev);  		if (irq_pending) { -			num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS); +			num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS, +						  &same); +			if (num_keys < 0) +				return 0;  			last_num_keys = num_keys;  			memcpy(last_keys, keys, sizeof(keys));  		} else { @@ -142,6 +161,13 @@ int cros_ec_kbc_check(struct input_config *input)  		num_keycodes = key_matrix_decode(&config.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;  |