diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2012-04-30 17:57:55 -0400 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2012-04-30 17:57:55 -0400 |
| commit | f7269a825cde879355bd15778012d2c3fb2ff778 (patch) | |
| tree | d36d61e3953e096efa1094442aee5ef1d2fab1d3 | |
| parent | 66f75a5d028beaf67c931435fdc3e7823125730c (diff) | |
| parent | fb054bf26914ee4c55cf149bc5b2a8e2c89fb81f (diff) | |
Merge branch 'keyboard' of git://github.com/hzhuang1/linux into next/drivers
From Haojian Zhuang <haojian.zhuang@gmail.com>
* 'keyboard' of git://github.com/hzhuang1/linux:
Input: pxa27x_keypad add choice to set direct_key_mask
Input: pxa27x_keypad direct key may be low active
Input: pxa27x_keypad bug fix for direct_key_mask
Input: pxa27x_keypad keep clock on as wakeup source
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
| -rw-r--r-- | arch/arm/plat-pxa/include/plat/pxa27x_keypad.h | 4 | ||||
| -rw-r--r-- | drivers/input/keyboard/pxa27x_keypad.c | 52 |
2 files changed, 42 insertions, 14 deletions
diff --git a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h index abcc36eb1242..5ce8d5e6ea51 100644 --- a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h +++ b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h | |||
| @@ -44,6 +44,10 @@ struct pxa27x_keypad_platform_data { | |||
| 44 | /* direct keys */ | 44 | /* direct keys */ |
| 45 | int direct_key_num; | 45 | int direct_key_num; |
| 46 | unsigned int direct_key_map[MAX_DIRECT_KEY_NUM]; | 46 | unsigned int direct_key_map[MAX_DIRECT_KEY_NUM]; |
| 47 | /* the key output may be low active */ | ||
| 48 | int direct_key_low_active; | ||
| 49 | /* give board a chance to choose the start direct key */ | ||
| 50 | unsigned int direct_key_mask; | ||
| 47 | 51 | ||
| 48 | /* rotary encoders 0 */ | 52 | /* rotary encoders 0 */ |
| 49 | int enable_rotary0; | 53 | int enable_rotary0; |
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) | |||
| 311 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 311 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
| 312 | pxa27x_keypad_scan_rotary(keypad); | 312 | pxa27x_keypad_scan_rotary(keypad); |
| 313 | 313 | ||
| 314 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | 314 | /* |
| 315 | * The KPDR_DK only output the key pin level, so it relates to board, | ||
| 316 | * and low level may be active. | ||
| 317 | */ | ||
| 318 | if (pdata->direct_key_low_active) | ||
| 319 | new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask; | ||
| 320 | else | ||
| 321 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | ||
| 322 | |||
| 315 | bits_changed = keypad->direct_key_state ^ new_state; | 323 | bits_changed = keypad->direct_key_state ^ new_state; |
| 316 | 324 | ||
| 317 | if (bits_changed == 0) | 325 | if (bits_changed == 0) |
| @@ -383,7 +391,14 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | |||
| 383 | if (pdata->direct_key_num > direct_key_num) | 391 | if (pdata->direct_key_num > direct_key_num) |
| 384 | direct_key_num = pdata->direct_key_num; | 392 | direct_key_num = pdata->direct_key_num; |
| 385 | 393 | ||
| 386 | keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask; | 394 | /* |
| 395 | * Direct keys usage may not start from KP_DKIN0, check the platfrom | ||
| 396 | * mask data to config the specific. | ||
| 397 | */ | ||
| 398 | if (pdata->direct_key_mask) | ||
| 399 | keypad->direct_key_mask = pdata->direct_key_mask; | ||
| 400 | else | ||
| 401 | keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask; | ||
| 387 | 402 | ||
| 388 | /* enable direct key */ | 403 | /* enable direct key */ |
| 389 | if (direct_key_num) | 404 | if (direct_key_num) |
| @@ -399,7 +414,7 @@ static int pxa27x_keypad_open(struct input_dev *dev) | |||
| 399 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | 414 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); |
| 400 | 415 | ||
| 401 | /* Enable unit clock */ | 416 | /* Enable unit clock */ |
| 402 | clk_enable(keypad->clk); | 417 | clk_prepare_enable(keypad->clk); |
| 403 | pxa27x_keypad_config(keypad); | 418 | pxa27x_keypad_config(keypad); |
| 404 | 419 | ||
| 405 | return 0; | 420 | return 0; |
| @@ -410,7 +425,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
| 410 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | 425 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); |
| 411 | 426 | ||
| 412 | /* Disable clock unit */ | 427 | /* Disable clock unit */ |
| 413 | clk_disable(keypad->clk); | 428 | clk_disable_unprepare(keypad->clk); |
| 414 | } | 429 | } |
| 415 | 430 | ||
| 416 | #ifdef CONFIG_PM | 431 | #ifdef CONFIG_PM |
| @@ -419,10 +434,14 @@ static int pxa27x_keypad_suspend(struct device *dev) | |||
| 419 | struct platform_device *pdev = to_platform_device(dev); | 434 | struct platform_device *pdev = to_platform_device(dev); |
| 420 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 435 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
| 421 | 436 | ||
| 422 | clk_disable(keypad->clk); | 437 | /* |
| 423 | 438 | * If the keypad is used a wake up source, clock can not be disabled. | |
| 439 | * Or it can not detect the key pressing. | ||
| 440 | */ | ||
| 424 | if (device_may_wakeup(&pdev->dev)) | 441 | if (device_may_wakeup(&pdev->dev)) |
| 425 | enable_irq_wake(keypad->irq); | 442 | enable_irq_wake(keypad->irq); |
| 443 | else | ||
| 444 | clk_disable_unprepare(keypad->clk); | ||
| 426 | 445 | ||
| 427 | return 0; | 446 | return 0; |
| 428 | } | 447 | } |
| @@ -433,19 +452,24 @@ static int pxa27x_keypad_resume(struct device *dev) | |||
| 433 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 452 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
| 434 | struct input_dev *input_dev = keypad->input_dev; | 453 | struct input_dev *input_dev = keypad->input_dev; |
| 435 | 454 | ||
| 436 | if (device_may_wakeup(&pdev->dev)) | 455 | /* |
| 456 | * If the keypad is used as wake up source, the clock is not turned | ||
| 457 | * off. So do not need configure it again. | ||
| 458 | */ | ||
| 459 | if (device_may_wakeup(&pdev->dev)) { | ||
| 437 | disable_irq_wake(keypad->irq); | 460 | disable_irq_wake(keypad->irq); |
| 461 | } else { | ||
| 462 | mutex_lock(&input_dev->mutex); | ||
| 438 | 463 | ||
| 439 | mutex_lock(&input_dev->mutex); | 464 | if (input_dev->users) { |
| 465 | /* Enable unit clock */ | ||
| 466 | clk_prepare_enable(keypad->clk); | ||
| 467 | pxa27x_keypad_config(keypad); | ||
| 468 | } | ||
| 440 | 469 | ||
| 441 | if (input_dev->users) { | 470 | mutex_unlock(&input_dev->mutex); |
| 442 | /* Enable unit clock */ | ||
| 443 | clk_enable(keypad->clk); | ||
| 444 | pxa27x_keypad_config(keypad); | ||
| 445 | } | 471 | } |
| 446 | 472 | ||
| 447 | mutex_unlock(&input_dev->mutex); | ||
| 448 | |||
| 449 | return 0; | 473 | return 0; |
| 450 | } | 474 | } |
| 451 | 475 | ||
