Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: tegra-kbc - report wakeup key for some platforms

Tegra kbc cannot detect exact keypress causing wakeup in interrupt mode.
Allow wakeup keypress to be reported for certain platforms.

Signed-off-by: Rakesh Iyer <riyer@nvidia.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Rakesh Iyer and committed by
Dmitry Torokhov
fd0fc213 a445c7f0

+25 -3
+1
arch/arm/mach-tegra/include/mach/kbc.h
··· 53 53 struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; 54 54 const struct matrix_keymap_data *keymap_data; 55 55 56 + u32 wakeup_key; 56 57 bool wakeup; 57 58 bool use_fn_map; 58 59 bool use_ghost_filter;
+24 -3
drivers/input/keyboard/tegra-kbc.c
··· 53 53 /* KBC Interrupt Register */ 54 54 #define KBC_INT_0 0x4 55 55 #define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) 56 + #define KBC_INT_KEYPRESS_INT_STATUS (1 << 0) 56 57 57 58 #define KBC_ROW_CFG0_0 0x8 58 59 #define KBC_COL_CFG0_0 0x18 ··· 76 75 unsigned int cp_to_wkup_dly; 77 76 bool use_fn_map; 78 77 bool use_ghost_filter; 78 + bool keypress_caused_wake; 79 79 const struct tegra_kbc_platform_data *pdata; 80 80 unsigned short keycode[KBC_MAX_KEY * 2]; 81 81 unsigned short current_keys[KBC_MAX_KPENT]; 82 82 unsigned int num_pressed_keys; 83 + u32 wakeup_key; 83 84 struct timer_list timer; 84 85 struct clk *clk; 85 86 }; ··· 414 411 */ 415 412 tegra_kbc_set_fifo_interrupt(kbc, false); 416 413 mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); 414 + } else if (val & KBC_INT_KEYPRESS_INT_STATUS) { 415 + /* We can be here only through system resume path */ 416 + kbc->keypress_caused_wake = true; 417 417 } 418 418 419 419 spin_unlock_irqrestore(&kbc->lock, flags); ··· 739 733 keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; 740 734 matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, 741 735 input_dev->keycode, input_dev->keybit); 736 + kbc->wakeup_key = pdata->wakeup_key; 742 737 743 - err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH, 744 - pdev->name, kbc); 738 + err = request_irq(kbc->irq, tegra_kbc_isr, 739 + IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); 745 740 if (err) { 746 741 dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); 747 742 goto err_put_clk; ··· 830 823 tegra_kbc_setup_wakekeys(kbc, true); 831 824 msleep(30); 832 825 826 + kbc->keypress_caused_wake = false; 827 + enable_irq(kbc->irq); 833 828 enable_irq_wake(kbc->irq); 834 829 } else { 835 830 if (kbc->idev->users) ··· 858 849 859 850 tegra_kbc_set_fifo_interrupt(kbc, true); 860 851 861 - enable_irq(kbc->irq); 852 + if (kbc->keypress_caused_wake && kbc->wakeup_key) { 853 + /* 854 + * We can't report events directly from the ISR 855 + * because timekeeping is stopped when processing 856 + * wakeup request and we get a nasty warning when 857 + * we try to call do_gettimeofday() in evdev 858 + * handler. 859 + */ 860 + input_report_key(kbc->idev, kbc->wakeup_key, 1); 861 + input_sync(kbc->idev); 862 + input_report_key(kbc->idev, kbc->wakeup_key, 0); 863 + input_sync(kbc->idev); 864 + } 862 865 } else { 863 866 if (kbc->idev->users) 864 867 err = tegra_kbc_start(kbc);