#include "power.h"
+#define HIB_PM_DEBUG 1
+#define _TAG_HIB_M "HIB/PM"
+#if (HIB_PM_DEBUG)
+#undef hib_log
+#define hib_log(fmt, ...) pr_warn("[%s][%s]" fmt, _TAG_HIB_M, __func__, ##__VA_ARGS__);
+#else
+#define hib_log(fmt, ...)
+#endif
+#undef hib_warn
+#define hib_warn(fmt, ...) pr_warn("[%s][%s]" fmt, _TAG_HIB_M, __func__, ##__VA_ARGS__);
+
DEFINE_MUTEX(pm_mutex);
+EXPORT_SYMBOL_GPL(pm_mutex);
#ifdef CONFIG_PM_SLEEP
/* Routines for PM-transition notifications */
-static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
+BLOCKING_NOTIFIER_HEAD(pm_chain_head);
+EXPORT_SYMBOL_GPL(pm_chain_head);
+//<20130327> <marc.huang> add pm_notifier_count
+static unsigned int pm_notifier_count = 0;
int register_pm_notifier(struct notifier_block *nb)
{
+ //<20130327> <marc.huang> add pm_notifier_count
+ ++pm_notifier_count;
return blocking_notifier_chain_register(&pm_chain_head, nb);
}
EXPORT_SYMBOL_GPL(register_pm_notifier);
int unregister_pm_notifier(struct notifier_block *nb)
{
+ //<20130327> <marc.huang> add pm_notifier_count
+ --pm_notifier_count;
return blocking_notifier_chain_unregister(&pm_chain_head, nb);
}
EXPORT_SYMBOL_GPL(unregister_pm_notifier);
int pm_notifier_call_chain(unsigned long val)
{
- int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
+ //<20130327> <marc.huang> add pm_notifier_count
+ int ret;
+ pr_debug("[%s] pm_notifier_count: %u, event = %lu\n", __func__, pm_notifier_count, val);
+
+ ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
return notifier_to_errno(ret);
}
+EXPORT_SYMBOL_GPL(pm_notifier_call_chain);
/* If set, devices may be suspended and resumed asynchronously. */
-int pm_async_enabled = 1;
+//<20130327> <marc.huang> disable async suspend/resume, set pm_async_enabled = 0
+int pm_async_enabled = 0;
static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
#endif /* CONFIG_PM_SLEEP_DEBUG */
struct kobject *power_kobj;
+EXPORT_SYMBOL_GPL(power_kobj);
/**
* state - control system power state.
return PM_SUSPEND_ON;
}
+//<20130327> <marc.huang> merge android kernel 3.0 state_store function
+#ifdef CONFIG_MTK_LDVT
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
pm_autosleep_unlock();
return error ? error : n;
}
+#else //#ifdef CONFIG_MTK_LDVT
+static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_EARLYSUSPEND
+ suspend_state_t state = PM_SUSPEND_ON;
+#else
+ suspend_state_t state = PM_SUSPEND_STANDBY;
+#endif
+ const char * const *s;
+#endif
+ char *p;
+ int len;
+ int error = -EINVAL;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+#ifdef CONFIG_MTK_HIBERNATION
+ state = decode_state(buf, n);
+ hib_log("entry (%d)\n", state);
+#endif
+#ifdef CONFIG_MTK_HIBERNATION
+ if (len == 8 && !strncmp(buf, "hibabort", len)) {
+ hib_log("abort hibernation...\n");
+ error = mtk_hibernate_abort();
+ goto Exit;
+ }
+#endif
+
+ /* First, check if we are requested to hibernate */
+ if (len == 4 && !strncmp(buf, "disk", len)) {
+#ifdef CONFIG_MTK_HIBERNATION
+ hib_log("trigger hibernation...\n");
+#ifdef CONFIG_EARLYSUSPEND
+ if (PM_SUSPEND_ON == get_suspend_state()) {
+ hib_warn("\"on\" to \"disk\" (i.e., 0->4) is not supported !!!\n");
+ error = -EINVAL;
+ goto Exit;
+ }
+#endif
+ if (!pre_hibernate()) {
+ error = 0;
+ error = mtk_hibernate();
+ }
+#else // !CONFIG_MTK_HIBERNATION
+ error = hibernate();
+#endif
+ goto Exit;
+ }
+
+#ifdef CONFIG_SUSPEND
+ for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+ if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
+ break;
+ }
+ if (state < PM_SUSPEND_MAX && *s) {
+#ifdef CONFIG_EARLYSUSPEND
+ if (state == PM_SUSPEND_ON || valid_state(state)) {
+ error = 0;
+ request_suspend_state(state);
+ } else
+ error = -EINVAL;
+#else
+ error = enter_state(state);
+#endif
+ }
+#endif
+
+ Exit:
+ return error ? error : n;
+}
+#endif
power_attr(state);
#ifdef CONFIG_PM_SLEEP
suspend_state_t state = decode_state(buf, n);
int error;
+ hib_log("store autosleep_state(%d)\n", state);
if (state == PM_SUSPEND_ON
&& strcmp(buf, "off") && strcmp(buf, "off\n"))
return -EINVAL;