diff options
| -rw-r--r-- | arch/arm/mach-tegra/include/mach/kbc.h | 1 | ||||
| -rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 62 |
2 files changed, 60 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h index 66ad2760c621..04c779832c78 100644 --- a/arch/arm/mach-tegra/include/mach/kbc.h +++ b/arch/arm/mach-tegra/include/mach/kbc.h | |||
| @@ -57,5 +57,6 @@ struct tegra_kbc_platform_data { | |||
| 57 | const struct matrix_keymap_data *keymap_data; | 57 | const struct matrix_keymap_data *keymap_data; |
| 58 | 58 | ||
| 59 | bool wakeup; | 59 | bool wakeup; |
| 60 | bool use_fn_map; | ||
| 60 | }; | 61 | }; |
| 61 | #endif | 62 | #endif |
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index ac471b77c18e..99ce9032d08c 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
| @@ -71,8 +71,9 @@ struct tegra_kbc { | |||
| 71 | spinlock_t lock; | 71 | spinlock_t lock; |
| 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 | const struct tegra_kbc_platform_data *pdata; | 75 | const struct tegra_kbc_platform_data *pdata; |
| 75 | unsigned short keycode[KBC_MAX_KEY]; | 76 | unsigned short keycode[KBC_MAX_KEY * 2]; |
| 76 | unsigned short current_keys[KBC_MAX_KPENT]; | 77 | unsigned short current_keys[KBC_MAX_KPENT]; |
| 77 | unsigned int num_pressed_keys; | 78 | unsigned int num_pressed_keys; |
| 78 | struct timer_list timer; | 79 | struct timer_list timer; |
| @@ -178,6 +179,40 @@ static const u32 tegra_kbc_default_keymap[] = { | |||
| 178 | KEY(15, 5, KEY_F2), | 179 | KEY(15, 5, KEY_F2), |
| 179 | KEY(15, 6, KEY_CAPSLOCK), | 180 | KEY(15, 6, KEY_CAPSLOCK), |
| 180 | KEY(15, 7, KEY_F6), | 181 | KEY(15, 7, KEY_F6), |
| 182 | |||
| 183 | /* Software Handled Function Keys */ | ||
| 184 | KEY(20, 0, KEY_KP7), | ||
| 185 | |||
| 186 | KEY(21, 0, KEY_KP9), | ||
| 187 | KEY(21, 1, KEY_KP8), | ||
| 188 | KEY(21, 2, KEY_KP4), | ||
| 189 | KEY(21, 4, KEY_KP1), | ||
| 190 | |||
| 191 | KEY(22, 1, KEY_KPSLASH), | ||
| 192 | KEY(22, 2, KEY_KP6), | ||
| 193 | KEY(22, 3, KEY_KP5), | ||
| 194 | KEY(22, 4, KEY_KP3), | ||
| 195 | KEY(22, 5, KEY_KP2), | ||
| 196 | KEY(22, 7, KEY_KP0), | ||
| 197 | |||
| 198 | KEY(27, 1, KEY_KPASTERISK), | ||
| 199 | KEY(27, 3, KEY_KPMINUS), | ||
| 200 | KEY(27, 4, KEY_KPPLUS), | ||
| 201 | KEY(27, 5, KEY_KPDOT), | ||
| 202 | |||
| 203 | KEY(28, 5, KEY_VOLUMEUP), | ||
| 204 | |||
| 205 | KEY(29, 3, KEY_HOME), | ||
| 206 | KEY(29, 4, KEY_END), | ||
| 207 | KEY(29, 5, KEY_BRIGHTNESSDOWN), | ||
| 208 | KEY(29, 6, KEY_VOLUMEDOWN), | ||
| 209 | KEY(29, 7, KEY_BRIGHTNESSUP), | ||
| 210 | |||
| 211 | KEY(30, 0, KEY_NUMLOCK), | ||
| 212 | KEY(30, 1, KEY_SCROLLLOCK), | ||
| 213 | KEY(30, 2, KEY_MUTE), | ||
| 214 | |||
| 215 | KEY(31, 4, KEY_HELP), | ||
| 181 | }; | 216 | }; |
| 182 | 217 | ||
| 183 | static const struct matrix_keymap_data tegra_kbc_default_keymap_data = { | 218 | static const struct matrix_keymap_data tegra_kbc_default_keymap_data = { |
| @@ -224,6 +259,7 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
| 224 | unsigned int i; | 259 | unsigned int i; |
| 225 | unsigned int num_down = 0; | 260 | unsigned int num_down = 0; |
| 226 | unsigned long flags; | 261 | unsigned long flags; |
| 262 | bool fn_keypress = false; | ||
| 227 | 263 | ||
| 228 | spin_lock_irqsave(&kbc->lock, flags); | 264 | spin_lock_irqsave(&kbc->lock, flags); |
| 229 | for (i = 0; i < KBC_MAX_KPENT; i++) { | 265 | for (i = 0; i < KBC_MAX_KPENT; i++) { |
| @@ -237,11 +273,28 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
| 237 | MATRIX_SCAN_CODE(row, col, KBC_ROW_SHIFT); | 273 | MATRIX_SCAN_CODE(row, col, KBC_ROW_SHIFT); |
| 238 | 274 | ||
| 239 | scancodes[num_down] = scancode; | 275 | scancodes[num_down] = scancode; |
| 240 | keycodes[num_down++] = kbc->keycode[scancode]; | 276 | keycodes[num_down] = kbc->keycode[scancode]; |
| 277 | /* If driver uses Fn map, do not report the Fn key. */ | ||
| 278 | if ((keycodes[num_down] == KEY_FN) && kbc->use_fn_map) | ||
| 279 | fn_keypress = true; | ||
| 280 | else | ||
| 281 | num_down++; | ||
| 241 | } | 282 | } |
| 242 | 283 | ||
| 243 | val >>= 8; | 284 | val >>= 8; |
| 244 | } | 285 | } |
| 286 | |||
| 287 | /* | ||
| 288 | * If the platform uses Fn keymaps, translate keys on a Fn keypress. | ||
| 289 | * Function keycodes are KBC_MAX_KEY apart from the plain keycodes. | ||
| 290 | */ | ||
| 291 | if (fn_keypress) { | ||
| 292 | for (i = 0; i < num_down; i++) { | ||
| 293 | scancodes[i] += KBC_MAX_KEY; | ||
| 294 | keycodes[i] = kbc->keycode[scancodes[i]]; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 245 | spin_unlock_irqrestore(&kbc->lock, flags); | 298 | spin_unlock_irqrestore(&kbc->lock, flags); |
| 246 | 299 | ||
| 247 | tegra_kbc_report_released_keys(kbc->idev, | 300 | tegra_kbc_report_released_keys(kbc->idev, |
| @@ -594,8 +647,11 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
| 594 | 647 | ||
| 595 | input_dev->keycode = kbc->keycode; | 648 | input_dev->keycode = kbc->keycode; |
| 596 | input_dev->keycodesize = sizeof(kbc->keycode[0]); | 649 | input_dev->keycodesize = sizeof(kbc->keycode[0]); |
| 597 | input_dev->keycodemax = ARRAY_SIZE(kbc->keycode); | 650 | input_dev->keycodemax = KBC_MAX_KEY; |
| 651 | if (pdata->use_fn_map) | ||
| 652 | input_dev->keycodemax *= 2; | ||
| 598 | 653 | ||
| 654 | kbc->use_fn_map = pdata->use_fn_map; | ||
| 599 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | 655 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; |
| 600 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, | 656 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, |
| 601 | input_dev->keycode, input_dev->keybit); | 657 | input_dev->keycode, input_dev->keybit); |
