diff options
author | Rakesh Iyer <riyer@nvidia.com> | 2011-12-29 22:27:44 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-12-30 03:27:00 -0500 |
commit | fd0fc21350838d3073647be173242db0c58744c8 (patch) | |
tree | 8139c545185c3bf034a846f9e15abc1b3dda52c1 /drivers/input | |
parent | a445c7f0afb9114ef3de2d123f2c851787cf9d11 (diff) |
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>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index b77725db4bea..a136e2e832be 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -53,6 +53,7 @@ | |||
53 | /* KBC Interrupt Register */ | 53 | /* KBC Interrupt Register */ |
54 | #define KBC_INT_0 0x4 | 54 | #define KBC_INT_0 0x4 |
55 | #define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) | 55 | #define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) |
56 | #define KBC_INT_KEYPRESS_INT_STATUS (1 << 0) | ||
56 | 57 | ||
57 | #define KBC_ROW_CFG0_0 0x8 | 58 | #define KBC_ROW_CFG0_0 0x8 |
58 | #define KBC_COL_CFG0_0 0x18 | 59 | #define KBC_COL_CFG0_0 0x18 |
@@ -75,10 +76,12 @@ struct tegra_kbc { | |||
75 | unsigned int cp_to_wkup_dly; | 76 | unsigned int cp_to_wkup_dly; |
76 | bool use_fn_map; | 77 | bool use_fn_map; |
77 | bool use_ghost_filter; | 78 | bool use_ghost_filter; |
79 | bool keypress_caused_wake; | ||
78 | const struct tegra_kbc_platform_data *pdata; | 80 | const struct tegra_kbc_platform_data *pdata; |
79 | unsigned short keycode[KBC_MAX_KEY * 2]; | 81 | unsigned short keycode[KBC_MAX_KEY * 2]; |
80 | unsigned short current_keys[KBC_MAX_KPENT]; | 82 | unsigned short current_keys[KBC_MAX_KPENT]; |
81 | unsigned int num_pressed_keys; | 83 | unsigned int num_pressed_keys; |
84 | u32 wakeup_key; | ||
82 | struct timer_list timer; | 85 | struct timer_list timer; |
83 | struct clk *clk; | 86 | struct clk *clk; |
84 | }; | 87 | }; |
@@ -411,6 +414,9 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args) | |||
411 | */ | 414 | */ |
412 | tegra_kbc_set_fifo_interrupt(kbc, false); | 415 | tegra_kbc_set_fifo_interrupt(kbc, false); |
413 | mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); | 416 | mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); |
417 | } else if (val & KBC_INT_KEYPRESS_INT_STATUS) { | ||
418 | /* We can be here only through system resume path */ | ||
419 | kbc->keypress_caused_wake = true; | ||
414 | } | 420 | } |
415 | 421 | ||
416 | spin_unlock_irqrestore(&kbc->lock, flags); | 422 | spin_unlock_irqrestore(&kbc->lock, flags); |
@@ -733,9 +739,10 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
733 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | 739 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; |
734 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, | 740 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, |
735 | input_dev->keycode, input_dev->keybit); | 741 | input_dev->keycode, input_dev->keybit); |
742 | kbc->wakeup_key = pdata->wakeup_key; | ||
736 | 743 | ||
737 | err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH, | 744 | err = request_irq(kbc->irq, tegra_kbc_isr, |
738 | pdev->name, kbc); | 745 | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); |
739 | if (err) { | 746 | if (err) { |
740 | dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); | 747 | dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); |
741 | goto err_put_clk; | 748 | goto err_put_clk; |
@@ -823,6 +830,8 @@ static int tegra_kbc_suspend(struct device *dev) | |||
823 | tegra_kbc_setup_wakekeys(kbc, true); | 830 | tegra_kbc_setup_wakekeys(kbc, true); |
824 | msleep(30); | 831 | msleep(30); |
825 | 832 | ||
833 | kbc->keypress_caused_wake = false; | ||
834 | enable_irq(kbc->irq); | ||
826 | enable_irq_wake(kbc->irq); | 835 | enable_irq_wake(kbc->irq); |
827 | } else { | 836 | } else { |
828 | if (kbc->idev->users) | 837 | if (kbc->idev->users) |
@@ -849,7 +858,19 @@ static int tegra_kbc_resume(struct device *dev) | |||
849 | 858 | ||
850 | tegra_kbc_set_fifo_interrupt(kbc, true); | 859 | tegra_kbc_set_fifo_interrupt(kbc, true); |
851 | 860 | ||
852 | enable_irq(kbc->irq); | 861 | if (kbc->keypress_caused_wake && kbc->wakeup_key) { |
862 | /* | ||
863 | * We can't report events directly from the ISR | ||
864 | * because timekeeping is stopped when processing | ||
865 | * wakeup request and we get a nasty warning when | ||
866 | * we try to call do_gettimeofday() in evdev | ||
867 | * handler. | ||
868 | */ | ||
869 | input_report_key(kbc->idev, kbc->wakeup_key, 1); | ||
870 | input_sync(kbc->idev); | ||
871 | input_report_key(kbc->idev, kbc->wakeup_key, 0); | ||
872 | input_sync(kbc->idev); | ||
873 | } | ||
853 | } else { | 874 | } else { |
854 | if (kbc->idev->users) | 875 | if (kbc->idev->users) |
855 | err = tegra_kbc_start(kbc); | 876 | err = tegra_kbc_start(kbc); |