diff options
author | Rakesh Iyer <riyer@nvidia.com> | 2011-04-28 02:18:15 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-04-28 02:19:14 -0400 |
commit | 34abeeb23575c9c25b8c582d582e5bcfcd1cf338 (patch) | |
tree | ac09faeaeb7afbe9badc78383dea9229aea62b33 /drivers/input/keyboard | |
parent | 5c9db64888ecabfb170081335f30e3d7192fbcf4 (diff) |
Input: tegra-kbc - add ghost key filter
Add ghost key filtering support for the Nvidia Tegra matrix keyboard.
Signed-off-by: Rakesh Iyer <riyer@nvidia.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 99ce9032d08c..5fb4b972f205 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -72,6 +72,7 @@ struct tegra_kbc { | |||
72 | unsigned int repoll_dly; | 72 | unsigned int repoll_dly; |
73 | unsigned long cp_dly_jiffies; | 73 | unsigned long cp_dly_jiffies; |
74 | bool use_fn_map; | 74 | bool use_fn_map; |
75 | bool use_ghost_filter; | ||
75 | const struct tegra_kbc_platform_data *pdata; | 76 | const struct tegra_kbc_platform_data *pdata; |
76 | unsigned short keycode[KBC_MAX_KEY * 2]; | 77 | unsigned short keycode[KBC_MAX_KEY * 2]; |
77 | unsigned short current_keys[KBC_MAX_KPENT]; | 78 | unsigned short current_keys[KBC_MAX_KPENT]; |
@@ -260,6 +261,8 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
260 | unsigned int num_down = 0; | 261 | unsigned int num_down = 0; |
261 | unsigned long flags; | 262 | unsigned long flags; |
262 | bool fn_keypress = false; | 263 | bool fn_keypress = false; |
264 | bool key_in_same_row = false; | ||
265 | bool key_in_same_col = false; | ||
263 | 266 | ||
264 | spin_lock_irqsave(&kbc->lock, flags); | 267 | spin_lock_irqsave(&kbc->lock, flags); |
265 | for (i = 0; i < KBC_MAX_KPENT; i++) { | 268 | for (i = 0; i < KBC_MAX_KPENT; i++) { |
@@ -285,6 +288,34 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
285 | } | 288 | } |
286 | 289 | ||
287 | /* | 290 | /* |
291 | * Matrix keyboard designs are prone to keyboard ghosting. | ||
292 | * Ghosting occurs if there are 3 keys such that - | ||
293 | * any 2 of the 3 keys share a row, and any 2 of them share a column. | ||
294 | * If so ignore the key presses for this iteration. | ||
295 | */ | ||
296 | if ((kbc->use_ghost_filter) && (num_down >= 3)) { | ||
297 | for (i = 0; i < num_down; i++) { | ||
298 | unsigned int j; | ||
299 | u8 curr_col = scancodes[i] & 0x07; | ||
300 | u8 curr_row = scancodes[i] >> KBC_ROW_SHIFT; | ||
301 | |||
302 | /* | ||
303 | * Find 2 keys such that one key is in the same row | ||
304 | * and the other is in the same column as the i-th key. | ||
305 | */ | ||
306 | for (j = i + 1; j < num_down; j++) { | ||
307 | u8 col = scancodes[j] & 0x07; | ||
308 | u8 row = scancodes[j] >> KBC_ROW_SHIFT; | ||
309 | |||
310 | if (col == curr_col) | ||
311 | key_in_same_col = true; | ||
312 | if (row == curr_row) | ||
313 | key_in_same_row = true; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /* | ||
288 | * If the platform uses Fn keymaps, translate keys on a Fn keypress. | 319 | * If the platform uses Fn keymaps, translate keys on a Fn keypress. |
289 | * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. | 320 | * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. |
290 | */ | 321 | */ |
@@ -297,6 +328,10 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
297 | 328 | ||
298 | spin_unlock_irqrestore(&kbc->lock, flags); | 329 | spin_unlock_irqrestore(&kbc->lock, flags); |
299 | 330 | ||
331 | /* Ignore the key presses for this iteration? */ | ||
332 | if (key_in_same_col && key_in_same_row) | ||
333 | return; | ||
334 | |||
300 | tegra_kbc_report_released_keys(kbc->idev, | 335 | tegra_kbc_report_released_keys(kbc->idev, |
301 | kbc->current_keys, kbc->num_pressed_keys, | 336 | kbc->current_keys, kbc->num_pressed_keys, |
302 | keycodes, num_down); | 337 | keycodes, num_down); |
@@ -652,6 +687,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
652 | input_dev->keycodemax *= 2; | 687 | input_dev->keycodemax *= 2; |
653 | 688 | ||
654 | kbc->use_fn_map = pdata->use_fn_map; | 689 | kbc->use_fn_map = pdata->use_fn_map; |
690 | kbc->use_ghost_filter = pdata->use_ghost_filter; | ||
655 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | 691 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; |
656 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, | 692 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, |
657 | input_dev->keycode, input_dev->keybit); | 693 | input_dev->keycode, input_dev->keybit); |