diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 18:58:49 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 18:58:49 (GMT) |
commit | 4637f40f200063973553ce3c4c1ac6c247e4535c (patch) | |
tree | ff317a0dfb67cae313a208d120edd5102730044d /drivers/input/keyboard/tegra-kbc.c | |
parent | 5129df03d0c44b2d5a5f9d7d52f3b079706b9a8f (diff) | |
parent | b73077eb03f510a84b102fb97640e595a958403c (diff) | |
download | linux-fsl-qoriq-4637f40f200063973553ce3c4c1ac6c247e4535c.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits)
Input: ADP5589 - new driver for I2C Keypad Decoder and I/O Expander
Input: tsc2007 - add X, Y and Z fuzz factors to platform data
Input: tsc2007 - add poll_period parameter to platform data
Input: tsc2007 - add poll_delay parameter to platform data
Input: tsc2007 - add max_rt parameter to platform data
Input: tsc2007 - debounce pressure measurement
Input: ad714x - fix captouch wheel option algorithm
Input: ad714x - allow platform code to specify irqflags
Input: ad714x - fix threshold and completion interrupt masks
Input: ad714x - fix up input configuration
Input: elantech - remove support for proprietary X driver
Input: elantech - report multitouch with proper ABS_MT messages
Input: elantech - export pressure and width when supported
Input: elantech - describe further the protocol
Input: atmel_tsadcc - correct call to input_free_device
Input: add driver FSL MPR121 capacitive touch sensor
Input: remove useless synchronize_rcu() calls
Input: ads7846 - fix gpio_pendown configuration
Input: ads7846 - add possibility to use external vref on ads7846
Input: rotary-encoder - add support for half-period encoders
...
Diffstat (limited to 'drivers/input/keyboard/tegra-kbc.c')
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 99ce903..2b3b73e 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -66,12 +66,11 @@ struct tegra_kbc { void __iomem *mmio; struct input_dev *idev; unsigned int irq; - unsigned int wake_enable_rows; - unsigned int wake_enable_cols; spinlock_t lock; unsigned int repoll_dly; unsigned long cp_dly_jiffies; bool use_fn_map; + bool use_ghost_filter; const struct tegra_kbc_platform_data *pdata; unsigned short keycode[KBC_MAX_KEY * 2]; unsigned short current_keys[KBC_MAX_KPENT]; @@ -260,6 +259,8 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) unsigned int num_down = 0; unsigned long flags; bool fn_keypress = false; + bool key_in_same_row = false; + bool key_in_same_col = false; spin_lock_irqsave(&kbc->lock, flags); for (i = 0; i < KBC_MAX_KPENT; i++) { @@ -285,6 +286,34 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) } /* + * Matrix keyboard designs are prone to keyboard ghosting. + * Ghosting occurs if there are 3 keys such that - + * any 2 of the 3 keys share a row, and any 2 of them share a column. + * If so ignore the key presses for this iteration. + */ + if ((kbc->use_ghost_filter) && (num_down >= 3)) { + for (i = 0; i < num_down; i++) { + unsigned int j; + u8 curr_col = scancodes[i] & 0x07; + u8 curr_row = scancodes[i] >> KBC_ROW_SHIFT; + + /* + * Find 2 keys such that one key is in the same row + * and the other is in the same column as the i-th key. + */ + for (j = i + 1; j < num_down; j++) { + u8 col = scancodes[j] & 0x07; + u8 row = scancodes[j] >> KBC_ROW_SHIFT; + + if (col == curr_col) + key_in_same_col = true; + if (row == curr_row) + key_in_same_row = true; + } + } + } + + /* * If the platform uses Fn keymaps, translate keys on a Fn keypress. * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. */ @@ -297,6 +326,10 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) spin_unlock_irqrestore(&kbc->lock, flags); + /* Ignore the key presses for this iteration? */ + if (key_in_same_col && key_in_same_row) + return; + tegra_kbc_report_released_keys(kbc->idev, kbc->current_keys, kbc->num_pressed_keys, keycodes, num_down); @@ -383,21 +416,11 @@ static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) int i; unsigned int rst_val; - BUG_ON(pdata->wake_cnt > KBC_MAX_KEY); - rst_val = (filter && pdata->wake_cnt) ? ~0 : 0; + /* Either mask all keys or none. */ + rst_val = (filter && !pdata->wakeup) ? ~0 : 0; for (i = 0; i < KBC_MAX_ROW; i++) writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); - - if (filter) { - for (i = 0; i < pdata->wake_cnt; i++) { - u32 val, addr; - addr = pdata->wake_cfg[i].row * 4 + KBC_ROW0_MASK_0; - val = readl(kbc->mmio + addr); - val &= ~(1 << pdata->wake_cfg[i].col); - writel(val, kbc->mmio + addr); - } - } } static void tegra_kbc_config_pins(struct tegra_kbc *kbc) @@ -559,7 +582,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) struct resource *res; int irq; int err; - int i; int num_rows = 0; unsigned int debounce_cnt; unsigned int scan_time_rows; @@ -616,13 +638,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) goto err_iounmap; } - kbc->wake_enable_rows = 0; - kbc->wake_enable_cols = 0; - for (i = 0; i < pdata->wake_cnt; i++) { - kbc->wake_enable_rows |= (1 << pdata->wake_cfg[i].row); - kbc->wake_enable_cols |= (1 << pdata->wake_cfg[i].col); - } - /* * The time delay between two consecutive reads of the FIFO is * the sum of the repeat time and the time taken for scanning @@ -652,6 +667,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) input_dev->keycodemax *= 2; kbc->use_fn_map = pdata->use_fn_map; + kbc->use_ghost_filter = pdata->use_ghost_filter; keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, input_dev->keycode, input_dev->keybit); |