summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2011-10-30 18:45:05 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:55 -0800
commita2480080a52bf8d4fe5dc68530443bf53eccc4eb (patch)
treeb62852e91657199cb30157fed72e3d7ed1e57356 /drivers/input
parent712cab86234851d02b4384f0f6d49895022717d9 (diff)
input: tegra: kbc: Board param for scan count
The scan timeout of the continuous mode can be calculated based on init delay, repeat delay, debounce count and number of active row. It also depends on how many scan need to be done before kbc change the mode from continuous to wakeup mode. Providing mechanism to select the scan count from platform data and calculating the scan timeout count based on above parameters. bug 876712 Reviewed-on: http://git-master/r/62591 (cherry picked from commit 3360ed5be86a2afd6716bc5227cc39657efd35b2) Change-Id: Ib9dc96b1cc201b7af0bd62a3ec7fe9a80791d796 Reviewed-on: http://git-master/r/63229 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Tested-by: Laxman Dewangan <ldewangan@nvidia.com> Rebase-Id: Rbcb685d34c5d00ebf1c79d356eb63e4584075447
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/tegra-kbc.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index e560e428db98..134960a219ea 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -55,6 +55,7 @@
#define KBC_ROW_CFG0_0 0x8
#define KBC_COL_CFG0_0 0x18
+#define KBC_TO_CNT_0 0x24
#define KBC_INIT_DLY_0 0x28
#define KBC_RPT_DLY_0 0x2c
#define KBC_KP_ENT0_0 0x30
@@ -62,6 +63,8 @@
#define KBC_ROW0_MASK_0 0x38
#define KBC_ROW_SHIFT 3
+#define DEFAULT_SCAN_COUNT 2
+#define DEFAULT_INIT_DLY 5
struct tegra_kbc {
void __iomem *mmio;
@@ -80,6 +83,8 @@ struct tegra_kbc {
unsigned int num_pressed_keys;
struct timer_list timer;
struct clk *clk;
+ unsigned long scan_timeout_count;
+ unsigned long one_scan_time;
};
static const u32 tegra_kbc_default_keymap[] = {
@@ -495,6 +500,9 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
val |= KBC_CONTROL_KBC_EN; /* enable */
writel(val, kbc->mmio + KBC_CONTROL_0);
+ writel(DEFAULT_INIT_DLY, kbc->mmio + KBC_INIT_DLY_0);
+ writel(kbc->scan_timeout_count, kbc->mmio + KBC_TO_CNT_0);
+
/*
* Compute the delay(ns) from interrupt mode to continuous polling
* mode so the timer routine is scheduled appropriately.
@@ -602,6 +610,9 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
int num_rows = 0;
unsigned int debounce_cnt;
unsigned int scan_time_rows;
+ unsigned long scan_tc;
+
+ dev_dbg(&pdev->dev, "KBC: tegra_kbc_probe\n");
if (!pdata)
return -EINVAL;
@@ -673,6 +684,17 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt;
kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS);
+ if (pdata->scan_count)
+ scan_tc = DEFAULT_INIT_DLY + (scan_time_rows +
+ pdata->repeat_cnt) * pdata->scan_count;
+ else
+ scan_tc = DEFAULT_INIT_DLY + (scan_time_rows +
+ pdata->repeat_cnt) * DEFAULT_SCAN_COUNT;
+
+ kbc->one_scan_time = scan_time_rows + pdata->repeat_cnt;
+ /* Bit 19:0 is for scan timeout count */
+ kbc->scan_timeout_count = scan_tc & 0xFFFFF;
+
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
@@ -756,8 +778,27 @@ static int tegra_kbc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+ int timeout;
+ unsigned long int_st;
+ dev_dbg(&pdev->dev, "KBC: tegra_kbc_suspend\n");
if (device_may_wakeup(&pdev->dev)) {
+ timeout = DIV_ROUND_UP((kbc->scan_timeout_count +
+ kbc->one_scan_time), 32);
+ timeout = DIV_ROUND_UP(timeout, 10);
+ while (timeout--) {
+ int_st = readl(kbc->mmio + KBC_INT_0);
+ if (int_st & 0x8) {
+ msleep(10);
+ continue;
+ }
+ break;
+ }
+ int_st = readl(kbc->mmio + KBC_INT_0);
+ if (int_st & 0x8)
+ dev_err(&pdev->dev, "KBC: Controller is not in "
+ "wakeupmode\n");
+
tegra_kbc_setup_wakekeys(kbc, true);
enable_irq_wake(kbc->irq);
/* Forcefully clear the interrupt status */