summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Jain <ajain@motorola.com>2014-10-02 11:11:23 -0500
committerAmit Jain <ajain@motorola.com>2014-10-03 13:37:12 +0000
commit58efe519a5477c70a184cdf376520122127f69f0 (patch)
tree597aef9bad8256e13a695b110888ac697b8c9589
parent079a36c83139757332cde9a8a588d7249645283b (diff)
downloadolio-linux-3.10-58efe519a5477c70a184cdf376520122127f69f0.tar.xz
olio-linux-3.10-58efe519a5477c70a184cdf376520122127f69f0.zip
IKXCLOCK-4061: power key behavior change
-rw-r--r--arch/arm/configs/minnow_defconfig1
-rw-r--r--drivers/mfd/tps65912-irq.c30
-rw-r--r--drivers/mfd/tps65912-key.c47
-rw-r--r--drivers/misc/Kconfig5
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/bq5105x_detect.c9
-rw-r--r--drivers/misc/charger_notify.c50
-rw-r--r--drivers/misc/display_notify.c50
-rw-r--r--drivers/video/omap2/displays/panel-minnow.c20
-rw-r--r--include/linux/charger_notify.h34
-rw-r--r--include/linux/display_notify.h34
-rw-r--r--include/linux/mfd/tps65912.h11
-rw-r--r--include/linux/wakeup_source_notify.h2
13 files changed, 292 insertions, 3 deletions
diff --git a/arch/arm/configs/minnow_defconfig b/arch/arm/configs/minnow_defconfig
index fa1a3eb44af..96cf883e0d6 100644
--- a/arch/arm/configs/minnow_defconfig
+++ b/arch/arm/configs/minnow_defconfig
@@ -1154,6 +1154,7 @@ CONFIG_MOT_UTAG=y
CONFIG_BQ5105X_CTRL=y
CONFIG_BQ5105X_DETECT=y
CONFIG_WAKEUP_SOURCE_NOTIFY=y
+CONFIG_POWER_KEY_OVERRIDE=y
# CONFIG_C2PORT is not set
#
diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c
index 766ed7dd8f5..9637a632e19 100644
--- a/drivers/mfd/tps65912-irq.c
+++ b/drivers/mfd/tps65912-irq.c
@@ -34,6 +34,7 @@ static inline int irq_to_tps65912_irq(struct tps65912 *tps65912,
static irqreturn_t powerkey_handler(int irq, void *irq_data)
{
struct tps65912 *tps65912 = irq_data;
+ unsigned int code = tps65912->powerkey_code;
u32 new_state;
if (irq - tps65912->irq_base == tps65912->powerkey_up_irq) {
@@ -47,9 +48,36 @@ static irqreturn_t powerkey_handler(int irq, void *irq_data)
}
mutex_lock(&tps65912->irq_lock);
+
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ /* if we are not on dock, send the sleep key*/
+ /* this logic is a bit tricky, notifier from
+ display driver will trigger on keypress which will
+ interfere with the logic for keyrelease. we will
+ see key press sent for KEY_POWER, but key release
+ for KEY_SLEEP. To fix this, we cache the event code
+ being sent out for keypress and we always send the
+ cached event code for key release */
+
+ if (new_state == PWRKEY_PRESS) {
+ if (tps65912->dockstatus == false &&
+ tps65912->displaystatus == true)
+ code = KEY_SLEEP;
+
+ tps65912->lastkeyevent = code;
+ }
+
+ if (new_state == PWRKEY_RELEASE) {
+ code = tps65912->lastkeyevent;
+ /* Deliberately setting to -1, to catch
+ errors */
+ tps65912->lastkeyevent = -1;
+ }
+#endif
+
if (new_state != tps65912->powerkey_state) {
tps65912_broadcast_key_event(tps65912,
- tps65912->powerkey_code,
+ code,
new_state);
tps65912->powerkey_state = new_state;
}
diff --git a/drivers/mfd/tps65912-key.c b/drivers/mfd/tps65912-key.c
index 3f389039405..308f5c97921 100644
--- a/drivers/mfd/tps65912-key.c
+++ b/drivers/mfd/tps65912-key.c
@@ -23,13 +23,42 @@
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65912.h>
+#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY
#include <linux/wakeup_source_notify.h>
+#endif
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+#include <linux/charger_notify.h>
+#include <linux/display_notify.h>
+#endif
struct tps65912_key_data {
struct input_dev *input_dev;
struct tps65912 *tps65912;
};
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+static int charger_notify(struct notifier_block *self,
+ unsigned long action, void *dev)
+{
+ struct tps65912 *tps65912 =
+ container_of(self, struct tps65912, charger_nb);
+ tps65912->dockstatus = (action == EVENT_DOCKON);
+ pr_info("%s: dockstatus is %d\n", __func__, tps65912->dockstatus);
+ return NOTIFY_OK;
+}
+
+static int display_notify(struct notifier_block *self,
+ unsigned long action, void *dev)
+{
+ struct tps65912 *tps65912 =
+ container_of(self, struct tps65912, display_nb);
+
+ tps65912->displaystatus = (action == DISPLAY_EVENT_DISPLAYON);
+ pr_info("%s: displaystatus is %d\n", __func__, tps65912->displaystatus);
+ return NOTIFY_OK;
+}
+#endif
+
static int tps65912_key_probe(struct platform_device *pdev)
{
int err;
@@ -57,6 +86,9 @@ static int tps65912_key_probe(struct platform_device *pdev)
set_bit(EV_KEY, key->input_dev->evbit);
set_bit(key->tps65912->powerkey_code, key->input_dev->keybit);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ set_bit(KEY_SLEEP, key->input_dev->keybit);
+#endif
key->input_dev->name = "tps65912-key";
@@ -69,6 +101,17 @@ static int tps65912_key_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, key);
tps65912_set_keydata(key->tps65912, key);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ key->tps65912->charger_nb.notifier_call = charger_notify;
+ charger_register_notify(&key->tps65912->charger_nb);
+ key->tps65912->dockstatus = false;
+
+ key->tps65912->display_nb.notifier_call = display_notify;
+ display_register_notify(&key->tps65912->display_nb);
+ key->tps65912->displaystatus = true;
+ key->tps65912->lastkeyevent = -1;
+#endif
+
dev_info(&pdev->dev, "tps65912 key device probed\n");
return 0;
@@ -86,6 +129,10 @@ static int __exit tps65912_key_remove(struct platform_device *pdev)
input_unregister_device(key->input_dev);
input_free_device(key->input_dev);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ charger_unregister_notify(&key->tps65912->charger_nb);
+ display_unregister_notify(&key->tps65912->display_nb);
+#endif
kfree(key);
return 0;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5b96da5fda8..2b3fbb02f2a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -586,6 +586,11 @@ config WAKEUP_SOURCE_NOTIFY
help
Driver to allow early notification of wakeups
+config POWER_KEY_OVERRIDE
+ tristate "dynamically switch between generating KEY_SLEEP and KEY_POWER"
+ help
+ controls key code to be generated from power key
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2f57dbac599..684e5a88236 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -68,3 +68,5 @@ obj-$(CONFIG_MOT_UTAG) += utag/
obj-$(CONFIG_BQ5105X_CTRL) += bq5105x_ctrl.o
obj-$(CONFIG_BQ5105X_DETECT) += bq5105x_detect.o
obj-$(CONFIG_WAKEUP_SOURCE_NOTIFY) += wakeup_source_notify.o
+obj-$(CONFIG_POWER_KEY_OVERRIDE) += charger_notify.o
+obj-$(CONFIG_POWER_KEY_OVERRIDE) += display_notify.o
diff --git a/drivers/misc/bq5105x_detect.c b/drivers/misc/bq5105x_detect.c
index 37cbdcaa11c..4c01828f5ca 100644
--- a/drivers/misc/bq5105x_detect.c
+++ b/drivers/misc/bq5105x_detect.c
@@ -31,7 +31,12 @@
#include <linux/switch.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
+#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY
#include <linux/wakeup_source_notify.h>
+#endif
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+#include <linux/charger_notify.h>
+#endif
/*
* Detect when a device is placed on a wireless charger and report this to user
@@ -215,6 +220,10 @@ static void bq5105x_detect_report(struct bq5105x_detect *chip, bool docked)
{
if (chip->reported_docked != docked) {
dev_dbg(&chip->pdev->dev, "report docked=%d\n", docked);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ charger_notify_subscriber(docked
+ ? EVENT_DOCKON : EVENT_DOCKOFF);
+#endif
#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY
wakeup_source_notify_subscriber(docked
? DISPLAY_WAKE_EVENT_DOCKON
diff --git a/drivers/misc/charger_notify.c b/drivers/misc/charger_notify.c
new file mode 100644
index 00000000000..79f9e726f87
--- /dev/null
+++ b/drivers/misc/charger_notify.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 Motorola Mobility LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/notifier.h>
+#include <linux/charger_notify.h>
+
+static BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
+
+/**
+ * charger_register_notify - register a notifier callback for triggering display init
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ */
+void charger_register_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_register(&charger_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(charger_register_notify);
+
+/**
+ * charger_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * charger_register_notify() must have been previously called
+ * for this function to work properly.
+ */
+void charger_unregister_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&charger_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(charger_unregister_notify);
+
+void charger_notify_subscriber(unsigned long event)
+{
+ blocking_notifier_call_chain(&charger_notifier_list, event, NULL);
+}
+EXPORT_SYMBOL_GPL(charger_notify_subscriber);
diff --git a/drivers/misc/display_notify.c b/drivers/misc/display_notify.c
new file mode 100644
index 00000000000..e243058fc4e
--- /dev/null
+++ b/drivers/misc/display_notify.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 Motorola Mobility LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/notifier.h>
+#include <linux/display_notify.h>
+
+static BLOCKING_NOTIFIER_HEAD(display_notifier_list);
+
+/**
+ * display_register_notify - register a notifier callback for triggering display init
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ */
+void display_register_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_register(&display_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(display_register_notify);
+
+/**
+ * display_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * display_register_notify() must have been previously called
+ * for this function to work properly.
+ */
+void display_unregister_notify(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&display_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(display_unregister_notify);
+
+void display_notify_subscriber(unsigned long event)
+{
+ blocking_notifier_call_chain(&display_notifier_list, event, NULL);
+}
+EXPORT_SYMBOL_GPL(display_notify_subscriber);
diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c
index cc231d4da58..e05806626e1 100644
--- a/drivers/video/omap2/displays/panel-minnow.c
+++ b/drivers/video/omap2/displays/panel-minnow.c
@@ -44,7 +44,12 @@
#include <video/omap-panel-data.h>
#include <video/mipi_display.h>
#include <linux/notifier.h>
+#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY
#include <linux/wakeup_source_notify.h>
+#endif
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+#include <linux/display_notify.h>
+#endif
#include "../dss/dss.h"
@@ -3281,8 +3286,12 @@ static int minnow_panel_change_state_mlocked(struct minnow_panel_data *mpd,
switch (state) {
case DISPLAY_DISABLE:
- if (mpd->enabled)
+ if (mpd->enabled) {
minnow_panel_disable_mlocked(mpd);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ display_notify_subscriber(DISPLAY_EVENT_DISPLAYOFF);
+#endif
+ }
break;
case DISPLAY_ENABLE:
if (!mpd->enabled)
@@ -3293,6 +3302,9 @@ static int minnow_panel_change_state_mlocked(struct minnow_panel_data *mpd,
*/
else if (mpd->state == DISPLAY_AMBIENT_ON)
minnow_panel_set_default_fps(mpd);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ display_notify_subscriber(DISPLAY_EVENT_DISPLAYON);
+#endif
#endif
break;
#ifdef CONFIG_HAS_AMBIENTMODE
@@ -3307,6 +3319,9 @@ static int minnow_panel_change_state_mlocked(struct minnow_panel_data *mpd,
/* Turn off the back light */
led_set_brightness(led_get_default_dev(), 0);
minnow_panel_disable_mlocked(mpd);
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ display_notify_subscriber(DISPLAY_EVENT_DISPLAYOFF);
+#endif
}
break;
case DISPLAY_AMBIENT_ON:
@@ -3329,6 +3344,9 @@ static int minnow_panel_change_state_mlocked(struct minnow_panel_data *mpd,
if (!mpd->enabled)
r = minnow_panel_enable_mlocked(mpd);
if (!r) {
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ display_notify_subscriber(DISPLAY_EVENT_DISPLAYOFF);
+#endif
/* switch to lowest refresh rate */
minnow_panel_set_lowest_fps(mpd);
/* Dim the back light */
diff --git a/include/linux/charger_notify.h b/include/linux/charger_notify.h
new file mode 100644
index 00000000000..49bd6cb07be
--- /dev/null
+++ b/include/linux/charger_notify.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 Motorola Mobility LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHARGER_NOTIFY_H
+#define CHARGER_NOTIFY_H
+
+#ifdef __KERNEL__
+
+enum charger_event {
+ EVENT_DOCKON,
+ EVENT_DOCKOFF,
+ EVENT_END
+};
+
+
+extern void charger_register_notify(struct notifier_block *nb);
+extern void charger_unregister_notify(struct notifier_block *nb);
+extern void charger_notify_subscriber(unsigned long event);
+#endif /* __KERNEL__ */
+
+#endif /* CHARGER_NOTIFY_H */
diff --git a/include/linux/display_notify.h b/include/linux/display_notify.h
new file mode 100644
index 00000000000..3dbb6128c4b
--- /dev/null
+++ b/include/linux/display_notify.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 Motorola Mobility LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DISPLAY_NOTIFY_H
+#define DISPLAY_NOTIFY_H
+
+#ifdef __KERNEL__
+
+enum display_event {
+ DISPLAY_EVENT_DISPLAYON,
+ DISPLAY_EVENT_DISPLAYOFF,
+ DISPLAY_EVENT_END
+};
+
+
+extern void display_register_notify(struct notifier_block *nb);
+extern void display_unregister_notify(struct notifier_block *nb);
+extern void display_notify_subscriber(unsigned long event);
+#endif /* __KERNEL__ */
+
+#endif /* DISPLAY_NOTIFY_H */
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
index 426f5e5e08f..6452efcdd8c 100644
--- a/include/linux/mfd/tps65912.h
+++ b/include/linux/mfd/tps65912.h
@@ -15,6 +15,10 @@
#ifndef __LINUX_MFD_TPS65912_H
#define __LINUX_MFD_TPS65912_H
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+#include <linux/notifier.h>
+#endif
+
/* TPS regulator type list */
#define REGULATOR_LDO 0
#define REGULATOR_DCDC 1
@@ -341,6 +345,13 @@ struct tps65912 {
u32 powerkey_up_irq;
u32 powerkey_down_irq;
struct mutex pm_lock; /* guard access to spi bus from irq */
+#ifdef CONFIG_POWER_KEY_OVERRIDE
+ struct notifier_block charger_nb;
+ bool dockstatus;
+ struct notifier_block display_nb;
+ bool displaystatus;
+ int lastkeyevent;
+#endif
};
struct tps65912_platform_data {
diff --git a/include/linux/wakeup_source_notify.h b/include/linux/wakeup_source_notify.h
index 98db849d13d..2681835738d 100644
--- a/include/linux/wakeup_source_notify.h
+++ b/include/linux/wakeup_source_notify.h
@@ -14,7 +14,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WAKEUP_SOURCEE_NOTIFY_H
+#ifndef WAKEUP_SOURCE_NOTIFY_H
#define WAKEUP_SOURCE_NOTIFY_H
#ifdef __KERNEL__