diff options
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/imx_keypad.c | 25 | ||||
-rw-r--r-- | drivers/input/keyboard/nomadik-ske-keypad.c | 76 | ||||
-rw-r--r-- | drivers/input/keyboard/pxa27x_keypad.c | 52 |
4 files changed, 103 insertions, 51 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 62bfce468f9f..cbb1add43d5e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -559,7 +559,6 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, pdata->rep = !!of_get_property(node, "autorepeat", NULL); /* First count the subnodes */ - pdata->nbuttons = 0; pp = NULL; while ((pp = of_get_next_child(node, pp))) pdata->nbuttons++; diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 6ee7421e2321..ff4c0a87a25f 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -378,20 +378,24 @@ static void imx_keypad_close(struct input_dev *dev) imx_keypad_inhibit(keypad); /* Disable clock unit */ - clk_disable(keypad->clk); + clk_disable_unprepare(keypad->clk); } static int imx_keypad_open(struct input_dev *dev) { struct imx_keypad *keypad = input_get_drvdata(dev); + int error; dev_dbg(&dev->dev, ">%s\n", __func__); + /* Enable the kpp clock */ + error = clk_prepare_enable(keypad->clk); + if (error) + return error; + /* We became active from now */ keypad->enabled = true; - /* Enable the kpp clock */ - clk_enable(keypad->clk); imx_keypad_config(keypad); /* Sanity control, not all the rows must be actived now. */ @@ -467,7 +471,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) goto failed_free_priv; } - keypad->clk = clk_get(&pdev->dev, "kpp"); + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get keypad clock\n"); error = PTR_ERR(keypad->clk); @@ -581,7 +585,7 @@ static int imx_kbd_suspend(struct device *dev) mutex_lock(&input_dev->mutex); if (input_dev->users) - clk_disable(kbd->clk); + clk_disable_unprepare(kbd->clk); mutex_unlock(&input_dev->mutex); @@ -596,18 +600,23 @@ static int imx_kbd_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; + int ret = 0; if (device_may_wakeup(&pdev->dev)) disable_irq_wake(kbd->irq); mutex_lock(&input_dev->mutex); - if (input_dev->users) - clk_enable(kbd->clk); + if (input_dev->users) { + ret = clk_prepare_enable(kbd->clk); + if (ret) + goto err_clk; + } +err_clk: mutex_unlock(&input_dev->mutex); - return 0; + return ret; } #endif diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 4ea4341a68c5..a880e7414202 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -49,6 +49,7 @@ #define SKE_ASR3 0x2C #define SKE_NUM_ASRX_REGISTERS (4) +#define KEY_PRESSED_DELAY 10 /** * struct ske_keypad - data structure used by keypad driver @@ -92,7 +93,7 @@ static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr, static int __init ske_keypad_chip_init(struct ske_keypad *keypad) { u32 value; - int timeout = 50; + int timeout = keypad->board->debounce_ms; /* check SKE_RIS to be 0 */ while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) @@ -135,12 +136,37 @@ static int __init ske_keypad_chip_init(struct ske_keypad *keypad) return 0; } -static void ske_keypad_read_data(struct ske_keypad *keypad) +static void ske_keypad_report(struct ske_keypad *keypad, u8 status, int col) { + int row = 0, code, pos; struct input_dev *input = keypad->input; - u16 status; - int col = 0, row = 0, code; - int ske_asr, ske_ris, key_pressed, i; + u32 ske_ris; + int key_pressed; + int num_of_rows; + + /* find out the row */ + num_of_rows = hweight8(status); + do { + pos = __ffs(status); + row = pos; + status &= ~(1 << pos); + + code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT); + ske_ris = readl(keypad->reg_base + SKE_RIS); + key_pressed = ske_ris & SKE_KPRISA; + + input_event(input, EV_MSC, MSC_SCAN, code); + input_report_key(input, keypad->keymap[code], key_pressed); + input_sync(input); + num_of_rows--; + } while (num_of_rows); +} + +static void ske_keypad_read_data(struct ske_keypad *keypad) +{ + u8 status; + int col = 0; + int ske_asr, i; /* * Read the auto scan registers @@ -154,44 +180,38 @@ static void ske_keypad_read_data(struct ske_keypad *keypad) if (!ske_asr) continue; - /* now that ASRx is zero, find out the column x and row y*/ - if (ske_asr & 0xff) { + /* now that ASRx is zero, find out the coloumn x and row y */ + status = ske_asr & 0xff; + if (status) { col = i * 2; - status = ske_asr & 0xff; - } else { + ske_keypad_report(keypad, status, col); + } + status = (ske_asr & 0xff00) >> 8; + if (status) { col = (i * 2) + 1; - status = (ske_asr & 0xff00) >> 8; + ske_keypad_report(keypad, status, col); } - - /* find out the row */ - row = __ffs(status); - - code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT); - ske_ris = readl(keypad->reg_base + SKE_RIS); - key_pressed = ske_ris & SKE_KPRISA; - - input_event(input, EV_MSC, MSC_SCAN, code); - input_report_key(input, keypad->keymap[code], key_pressed); - input_sync(input); } } static irqreturn_t ske_keypad_irq(int irq, void *dev_id) { struct ske_keypad *keypad = dev_id; - int retries = 20; + int timeout = keypad->board->debounce_ms; /* disable auto scan interrupt; mask the interrupt generated */ ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0); ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA); - while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --retries) - msleep(5); + while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --timeout) + cpu_relax(); - if (retries) { - /* SKEx registers are stable and can be read */ - ske_keypad_read_data(keypad); - } + /* SKEx registers are stable and can be read */ + ske_keypad_read_data(keypad); + + /* wait until raw interrupt is clear */ + while ((readl(keypad->reg_base + SKE_RIS)) && --timeout) + msleep(KEY_PRESSED_DELAY); /* enable auto scan interrupts */ ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 29fe1b2be1c1..7f7b72464a37 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -311,7 +311,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) if (pdata->enable_rotary0 || pdata->enable_rotary1) pxa27x_keypad_scan_rotary(keypad); - new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; + /* + * The KPDR_DK only output the key pin level, so it relates to board, + * and low level may be active. + */ + if (pdata->direct_key_low_active) + new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask; + else + new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; + bits_changed = keypad->direct_key_state ^ new_state; if (bits_changed == 0) @@ -383,7 +391,14 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) if (pdata->direct_key_num > direct_key_num) direct_key_num = pdata->direct_key_num; - keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask; + /* + * Direct keys usage may not start from KP_DKIN0, check the platfrom + * mask data to config the specific. + */ + if (pdata->direct_key_mask) + keypad->direct_key_mask = pdata->direct_key_mask; + else + keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask; /* enable direct key */ if (direct_key_num) @@ -399,7 +414,7 @@ static int pxa27x_keypad_open(struct input_dev *dev) struct pxa27x_keypad *keypad = input_get_drvdata(dev); /* Enable unit clock */ - clk_enable(keypad->clk); + clk_prepare_enable(keypad->clk); pxa27x_keypad_config(keypad); return 0; @@ -410,7 +425,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) struct pxa27x_keypad *keypad = input_get_drvdata(dev); /* Disable clock unit */ - clk_disable(keypad->clk); + clk_disable_unprepare(keypad->clk); } #ifdef CONFIG_PM @@ -419,10 +434,14 @@ static int pxa27x_keypad_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); - clk_disable(keypad->clk); - + /* + * If the keypad is used a wake up source, clock can not be disabled. + * Or it can not detect the key pressing. + */ if (device_may_wakeup(&pdev->dev)) enable_irq_wake(keypad->irq); + else + clk_disable_unprepare(keypad->clk); return 0; } @@ -433,19 +452,24 @@ static int pxa27x_keypad_resume(struct device *dev) struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; - if (device_may_wakeup(&pdev->dev)) + /* + * If the keypad is used as wake up source, the clock is not turned + * off. So do not need configure it again. + */ + if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(keypad->irq); + } else { + mutex_lock(&input_dev->mutex); - mutex_lock(&input_dev->mutex); + if (input_dev->users) { + /* Enable unit clock */ + clk_prepare_enable(keypad->clk); + pxa27x_keypad_config(keypad); + } - if (input_dev->users) { - /* Enable unit clock */ - clk_enable(keypad->clk); - pxa27x_keypad_config(keypad); + mutex_unlock(&input_dev->mutex); } - mutex_unlock(&input_dev->mutex); - return 0; } |