Skip to content

Commit

Permalink
Input: tegra-kbc - report wakeup key for some platforms
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rakesh Iyer authored and Dmitry Torokhov committed Dec 30, 2011
1 parent a445c7f commit fd0fc21
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-tegra/include/mach/kbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct tegra_kbc_platform_data {
struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO];
const struct matrix_keymap_data *keymap_data;

u32 wakeup_key;
bool wakeup;
bool use_fn_map;
bool use_ghost_filter;
Expand Down
27 changes: 24 additions & 3 deletions drivers/input/keyboard/tegra-kbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
/* KBC Interrupt Register */
#define KBC_INT_0 0x4
#define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2)
#define KBC_INT_KEYPRESS_INT_STATUS (1 << 0)

#define KBC_ROW_CFG0_0 0x8
#define KBC_COL_CFG0_0 0x18
Expand All @@ -75,10 +76,12 @@ struct tegra_kbc {
unsigned int cp_to_wkup_dly;
bool use_fn_map;
bool use_ghost_filter;
bool keypress_caused_wake;
const struct tegra_kbc_platform_data *pdata;
unsigned short keycode[KBC_MAX_KEY * 2];
unsigned short current_keys[KBC_MAX_KPENT];
unsigned int num_pressed_keys;
u32 wakeup_key;
struct timer_list timer;
struct clk *clk;
};
Expand Down Expand Up @@ -411,6 +414,9 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args)
*/
tegra_kbc_set_fifo_interrupt(kbc, false);
mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
} else if (val & KBC_INT_KEYPRESS_INT_STATUS) {
/* We can be here only through system resume path */
kbc->keypress_caused_wake = true;
}

spin_unlock_irqrestore(&kbc->lock, flags);
Expand Down Expand Up @@ -733,9 +739,10 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
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);
kbc->wakeup_key = pdata->wakeup_key;

err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH,
pdev->name, kbc);
err = request_irq(kbc->irq, tegra_kbc_isr,
IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc);
if (err) {
dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
goto err_put_clk;
Expand Down Expand Up @@ -823,6 +830,8 @@ static int tegra_kbc_suspend(struct device *dev)
tegra_kbc_setup_wakekeys(kbc, true);
msleep(30);

kbc->keypress_caused_wake = false;
enable_irq(kbc->irq);
enable_irq_wake(kbc->irq);
} else {
if (kbc->idev->users)
Expand All @@ -849,7 +858,19 @@ static int tegra_kbc_resume(struct device *dev)

tegra_kbc_set_fifo_interrupt(kbc, true);

enable_irq(kbc->irq);
if (kbc->keypress_caused_wake && kbc->wakeup_key) {
/*
* We can't report events directly from the ISR
* because timekeeping is stopped when processing
* wakeup request and we get a nasty warning when
* we try to call do_gettimeofday() in evdev
* handler.
*/
input_report_key(kbc->idev, kbc->wakeup_key, 1);
input_sync(kbc->idev);
input_report_key(kbc->idev, kbc->wakeup_key, 0);
input_sync(kbc->idev);
}
} else {
if (kbc->idev->users)
err = tegra_kbc_start(kbc);
Expand Down

0 comments on commit fd0fc21

Please sign in to comment.