diff options
-rw-r--r-- | arch/arm/configs/imx5_ccwmx53js_defconfig | 15 | ||||
-rw-r--r-- | arch/arm/mach-mx5/Kconfig | 1 | ||||
-rw-r--r-- | drivers/input/misc/da9052_onkey.c | 75 |
3 files changed, 89 insertions, 2 deletions
diff --git a/arch/arm/configs/imx5_ccwmx53js_defconfig b/arch/arm/configs/imx5_ccwmx53js_defconfig index 58480c1c16be..969437651c25 100644 --- a/arch/arm/configs/imx5_ccwmx53js_defconfig +++ b/arch/arm/configs/imx5_ccwmx53js_defconfig @@ -944,7 +944,20 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_P1003 is not set CONFIG_TOUCHSCREEN_DA9052=y # CONFIG_TOUCHSCREEN_MAX11801 is not set -# CONFIG_INPUT_MISC is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_MMA7455L is not set +CONFIG_INPUT_DA9052_ONKEY=y +# CONFIG_INPUT_ISL29023 is not set # # Hardware I/O ports diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig index 760388704c1d..91ebe7ad9ea0 100644 --- a/arch/arm/mach-mx5/Kconfig +++ b/arch/arm/mach-mx5/Kconfig @@ -285,6 +285,7 @@ config MXC_DISABLE_WARM_RESET config CCXMX5X_PM_POWER_BUTTON bool "Enable power button for suspend/resume to RAM" + depends on MODULE_CCXMX51 || (MODULE_CCXMX53 && (INPUT_DA9052_ONKEY || INPUT_DA9052_ONKEY_MODULE)) default y help This option will enable the usage of the power button to suspend diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index dc3bf46420fb..54450f09e91e 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -7,6 +7,10 @@ #include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/reg.h> +#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON +#include <linux/suspend.h> +#endif + #define DRIVER_NAME "da9052-onkey" struct da9052_onkey_data { @@ -16,6 +20,59 @@ struct da9052_onkey_data { struct delayed_work polling_work; }; +#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON +enum power_on_state { + PWRON_FROM_RESUME, + PWRON_FALLING_EDGE, + PWRON_FROM_SUSPEND +}; + +static int pwron_state = PWRON_FROM_RESUME; + +static void da9052_power_button( struct da9052 *da9052 , int value ) +{ + struct da9052_ssc_msg ssc_msg; + unsigned int ret; + + switch (pwron_state){ + case PWRON_FROM_RESUME: + // Are we waking up from a non power button suspend + // and this is the falling edge already? + if( !value ) + pwron_state = PWRON_FROM_RESUME; + else + // Skipping falling edge + pwron_state = PWRON_FALLING_EDGE; + break; + case PWRON_FALLING_EDGE: + // Suspend on rising edge + pm_suspend(PM_SUSPEND_MEM); + // Did we wake by a power button press? + da9052_lock(da9052); + ssc_msg.addr = DA9052_EVENTB_REG; + ret = da9052->read(da9052, &ssc_msg); + if (ret) { + da9052_unlock(da9052); + pwron_state = PWRON_FROM_RESUME; + return; + } + da9052_unlock(da9052); + if( ssc_msg.data | DA9052_EVENTB_ENONKEY ) + pwron_state = PWRON_FROM_SUSPEND; + else + // Waken by other source + pwron_state = PWRON_FROM_RESUME; + break; + case PWRON_FROM_SUSPEND: + // Ignoring raising edge + pwron_state = PWRON_FROM_RESUME; + break; + default: + pr_err("power_on_evt_handler: Unitialized state\n"); + } +} +#endif + static void da9052_onkey_work_func(struct work_struct *work) { struct da9052_onkey_data *da9052_onkey = @@ -37,6 +94,10 @@ static void da9052_onkey_work_func(struct work_struct *work) input_report_key(da9052_onkey->input, KEY_POWER, value); input_sync(da9052_onkey->input); +#ifdef CONFIG_CCXMX5X_PM_POWER_BUTTON + da9052_power_button( da9052_onkey->da9052 , value ); +#endif + /* if key down, polling for up */ if (value) schedule_delayed_work(&da9052_onkey->polling_work, HZ/10); @@ -55,7 +116,8 @@ static void da9052_onkey_report_event(struct da9052_eh_nb *eh_data, static int __devinit da9052_onkey_probe(struct platform_device *pdev) { struct da9052_onkey_data *da9052_onkey; - int error; + int error,ret; + struct da9052_ssc_msg msg; da9052_onkey = kzalloc(sizeof(*da9052_onkey), GFP_KERNEL); da9052_onkey->input = input_allocate_device(); @@ -97,6 +159,17 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) platform_set_drvdata(pdev, da9052_onkey); + // Unmask IRQ + da9052_lock(da9052_onkey->da9052); + msg.addr = DA9052_IRQMASKB_REG; + ret = da9052_onkey->da9052->read(da9052_onkey->da9052, &msg); + if (ret) { + da9052_unlock(da9052_onkey->da9052); + return 0; + } + msg.data &= ~DA9052_IRQMASKB_MNONKEY; + da9052_onkey->da9052->write(da9052_onkey->da9052, &msg); + da9052_unlock(da9052_onkey->da9052); return 0; fail3: |