[Nexus 4 Original Android Development] franciscofranco:
diff --git a/arch/arm/kernel/mako_hotplug.c b/arch/arm/kernel/mako_hotplug.c
index 34ba386..f67fb43 100644
--- a/arch/arm/kernel/mako_hotplug.c
+++ b/arch/arm/kernel/mako_hotplug.c
@@ -1,8 +1,16 @@
/*
- * Copyright (c) 2013, Francisco Franco <franciscofranco.1990@gmail.com>.
- * All rights reserved.
+ * Copyright (c) 2013, Francisco Franco <franciscofranco.1990@gmail.com>.
*
- * Simple no bull**** hot[in]plug driver for SMP
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * Simple no bull**** hot[in]plug driver for SMP
*/

#include <linux/kernel.h>
@@ -15,16 +23,20 @@
#include <linux/rq_stats.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
+#include <linux/hotplug.h>

#include <mach/cpufreq.h>

/* threshold for comparing time diffs is 2 seconds */
#define SEC_THRESHOLD 2000
-#define HISTORY_SIZE 8
-#define DEFAULT_FIRST_LEVEL 80
+/* value in ms */
+#define HISTORY_SIZE 10
+#define DEFAULT_FIRST_LEVEL 90
#define DEFAULT_SECOND_LEVEL 50
-#define DEFAULT_THIRD_LEVEL 25
+#define DEFAULT_THIRD_LEVEL 30
+#define DEFAULT_FOURTH_LEVEL 10
#define DEFAULT_SUSPEND_FREQ 702000
+#define DEFAULT_CORES_ON_TOUCH 2

struct cpu_stats
{
@@ -34,16 +46,26 @@ struct cpu_stats
unsigned int default_first_level;
unsigned int default_second_level;
unsigned int default_third_level;
+ unsigned int default_fourth_level;
unsigned int suspend_frequency;
+ unsigned int cores_on_touch;
};

static struct cpu_stats stats;
static struct workqueue_struct *wq;
static struct delayed_work decide_hotplug;

+bool is_touched = false;
+unsigned long touch_off_time = 0;
unsigned int load_history[HISTORY_SIZE] = {0};
unsigned int counter = 0;

+void is_touching(bool touch, unsigned long time_off)
+{
+ is_touched = touch;
+ touch_off_time = time_off;
+}
+
static void scale_interactive_tunables(unsigned int above_hispeed_delay,
unsigned int go_hispeed_load, unsigned int timer_rate,
unsigned int min_sample_time)
@@ -54,7 +76,7 @@ static void scale_interactive_tunables(unsigned int above_hispeed_delay,
scale_min_sample_time(min_sample_time);
}

-static void first_level_work_check(unsigned long temp_diff, unsigned long now)
+static void first_level_work_check(unsigned long now)
{
unsigned int cpu = nr_cpu_ids;

@@ -62,62 +84,55 @@ static void first_level_work_check(unsigned long temp_diff, unsigned long now)
if (stats.online_cpus == stats.total_cpus)
return;

- if (stats.online_cpus == 2 || (now - stats.time_stamp) >= temp_diff)
+ for_each_possible_cpu(cpu)
{
- for_each_possible_cpu(cpu)
+ if (cpu && !cpu_online(cpu))
{
- if (cpu && !cpu_online(cpu))
- {
- cpu_up(cpu);
- pr_info("Hotplug: cpu%d is up - high load\n", cpu);
- }
+ cpu_up(cpu);
+ pr_info("Hotplug: cpu%d is up - high load\n", cpu);
}
+ }

- scale_interactive_tunables(0, 80, 10, 80);
+ scale_interactive_tunables(0, 80, 10, 80);

- stats.time_stamp = now;
- }
+ stats.time_stamp = now;
}

-static void second_level_work_check(unsigned long temp_diff, unsigned long now)
+static void second_level_work_check(unsigned long now)
{
unsigned int cpu = nr_cpu_ids;
-
+
/* lets bail if all cores are online */
if (stats.online_cpus == stats.total_cpus)
return;

- if (stats.online_cpus < 2 || (now - stats.time_stamp) >= temp_diff)
- {
- for_each_possible_cpu(cpu)
+ for_each_possible_cpu(cpu)
+ {
+ if (cpu && !cpu_online(cpu))
{
- if (cpu && !cpu_online(cpu))
- {
- cpu_up(cpu);
- pr_info("Hotplug: cpu%d is up - medium load\n", cpu);
- break;
- }
+ cpu_up(cpu);
+ pr_info("Hotplug: cpu%d is up - medium load\n", cpu);
+ break;
}
+ }

- if (stats.online_cpus == 1)
- scale_interactive_tunables(50, 99, 30, 20);
+ if (stats.online_cpus == 1)
+ scale_interactive_tunables(50, 99, 30, 20);

- else if (stats.online_cpus == 3)
- scale_interactive_tunables(0, 80, 10, 80);
+ else if (stats.online_cpus == 3)
+ scale_interactive_tunables(0, 80, 10, 80);

- stats.time_stamp = now;
- }
+ stats.time_stamp = now;
}

-static void third_level_work_check(unsigned long temp_diff, unsigned long now)
+static void third_level_work_check(unsigned int load, unsigned long now)
{
unsigned int cpu = nr_cpu_ids;

- /* lets bail if all cores are offline */
- if (stats.online_cpus == 1)
- return;
+ unsigned int third_level = stats.default_third_level * stats.online_cpus;
+ unsigned int fourth_level = stats.default_fourth_level * stats.online_cpus;

- if ((now - stats.time_stamp) >= temp_diff)
+ if (load <= fourth_level)
{
for_each_online_cpu(cpu)
{
@@ -129,15 +144,28 @@ static void third_level_work_check(unsigned long temp_diff, unsigned long now)
}

scale_interactive_tunables(15, 99, 25, 40);
+ }

- stats.time_stamp = now;
+ else if (load <= third_level)
+ {
+ for_each_online_cpu(cpu)
+ {
+ if (cpu)
+ {
+ cpu_down(cpu);
+ pr_info("Hotplug: cpu%d is down - low load\n", cpu);
+ break;
+ }
+ }
}
+
+ stats.time_stamp = now;
}

static void decide_hotplug_func(struct work_struct *work)
{
unsigned long now;
- unsigned int i, j, first_level, second_level, third_level, load = 0;
+ unsigned int i, j, first_level, second_level, load = 0;

/* start feeding the current load to the history array so that we can
make a little average. Works good for filtering low and/or high load
@@ -165,7 +193,6 @@ static void decide_hotplug_func(struct work_struct *work)
/* the load thresholds scale with the number of online cpus */
first_level = stats.default_first_level * stats.online_cpus;
second_level = stats.default_second_level * stats.online_cpus;
- third_level = stats.default_third_level * stats.online_cpus;

/*
pr_info("LOAD: %d\n", load);
@@ -173,45 +200,41 @@ static void decide_hotplug_func(struct work_struct *work)
pr_info("SECOND: %d\n", second_level);
pr_info("THIRD: %d\n", third_level);
pr_info("COUNTER: %d\n", counter);
+ pr_info("BOOL: %d\n", is_touched);
*/

if (load >= first_level)
{
- first_level_work_check(SEC_THRESHOLD, now);
+ first_level_work_check(now);
queue_delayed_work_on(0, wq, &decide_hotplug, msecs_to_jiffies(HZ));
return;
}
-
+
+ /* if the touch driver detects a finger in the screen go down this path */
+ else if (is_touched)
+ {
+ if (now >= touch_off_time + SEC_THRESHOLD)
+ is_touched = false;
+
+ else if (stats.online_cpus < stats.cores_on_touch)
+ {
+ second_level_work_check(now);
+ queue_delayed_work_on(0, wq, &decide_hotplug, msecs_to_jiffies(HZ));
+ return;
+ }
+ }
/* load is medium-high so online only one core at a time */
- else if ((load >= third_level && stats.online_cpus < 2) || load >= second_level)
- {
- /* feed it 2 times the seconds threshold because when this is called
- there is a check inside that onlines cpu1 bypassing the time_diff
- but afterwards it takes at least 4 seconds as threshold before
- onlining another cpu. This eliminates unneeded onlining when we are
- for example swipping between home or app drawer and we only need
- cpu0 and cpu1 online for that, cpufreq takes care of the rest */
-
- second_level_work_check(SEC_THRESHOLD*2, now);
+ else if (load >= second_level)
+ {
+ second_level_work_check(now);
queue_delayed_work_on(0, wq, &decide_hotplug, msecs_to_jiffies(HZ));
return;
}
-
- /* if two cpus are online while the load is just above the low zone
- then its most than likely that the user is interacting with the UI
- so instead of onling/offlining cpu1 every now and then lets keep it
- online until the user is not interacting anymore. This should save
- some resources that are ineherent to the hotplugging routines */
- else if (load >= DEFAULT_THIRD_LEVEL && stats.online_cpus == 2)
- {
- queue_delayed_work_on(0, wq, &decide_hotplug, msecs_to_jiffies(HZ));
- return;
- }

/* low load obliterate the cpus to death */
- else if (load <= third_level && stats.online_cpus > 1)
+ else if (stats.online_cpus > 1 && (now - stats.time_stamp) >= SEC_THRESHOLD)
{
- third_level_work_check(SEC_THRESHOLD, now);
+ third_level_work_check(load, now);
}

queue_delayed_work_on(0, wq, &decide_hotplug, msecs_to_jiffies(HZ));
@@ -234,11 +257,18 @@ static void mako_hotplug_early_suspend(struct early_suspend *handler)
}

static void mako_hotplug_late_resume(struct early_suspend *handler)
-{
+{
+ int i;
+
/* online all cores when the screen goes online */
- first_level_work_check(0, ktime_to_ms(ktime_get()));
+ first_level_work_check(ktime_to_ms(ktime_get()));
+
+ /* feed the buffer with fake load so that it doesn't average from low
+ values and derp the UI interactivity after screening on */
+ for (i = 0; i < HISTORY_SIZE; i++)
+ load_history[i] = 100;

- /* restore default 1,5GHz max frequency */
+ /* restore max frequency */
msm_cpufreq_set_freq_limits(0, MSM_CPUFREQ_NO_LIMIT, MSM_CPUFREQ_NO_LIMIT);
pr_info("Cpulimit: Late resume - restore cpu%d max frequency.\n", 0);

@@ -306,7 +336,9 @@ int __init mako_hotplug_init(void)
stats.default_first_level = DEFAULT_FIRST_LEVEL;
stats.default_second_level = DEFAULT_SECOND_LEVEL;
stats.default_third_level = DEFAULT_THIRD_LEVEL;
+ stats.default_fourth_level = DEFAULT_FOURTH_LEVEL;
stats.suspend_frequency = DEFAULT_SUSPEND_FREQ;
+ stats.cores_on_touch = DEFAULT_CORES_ON_TOUCH;

wq = alloc_workqueue("mako_hotplug_workqueue",
WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, 1);
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 8f5b079..058f04c 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/input.h>
#include <asm/cputime.h>
+#include <linux/hotplug.h>

#define CREATE_TRACE_POINTS
#include <trace/events/cpufreq_interactive.h>
@@ -867,6 +868,11 @@ void scale_min_sample_time(unsigned int new_min_sample_time)
min_sample_time = new_min_sample_time * 1000;
}

+unsigned int get_input_boost_freq()
+{
+	return input_boost_freq;
+}
+
static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
unsigned int event)
{
diff --git a/drivers/input/touchscreen/lge_touch_core.c b/drivers/input/touchscreen/lge_touch_core.c
index 8c2ed9e..97fc491 100644
--- a/drivers/input/touchscreen/lge_touch_core.c
+++ b/drivers/input/touchscreen/lge_touch_core.c
@@ -30,6 +30,7 @@
#include <linux/time.h>
#include <linux/version.h>
#include <linux/cpufreq.h>
+#include <linux/hotplug.h>

#include <asm/atomic.h>
#include <linux/gpio.h>
@@ -794,7 +795,8 @@ static void touch_input_report(struct lge_touch_data *ts)
input_sync(ts->input_dev);
}

-#define BOOST_FREQ 1026000
+#define TOUCH_BOOST_FREQ get_input_boost_freq()
+#define SWIPE_BOOST_FREQ 702000
static struct cpufreq_policy *policy;

/*
@@ -809,9 +811,8 @@ static void touch_work_func(struct work_struct *work)
int ret;
static unsigned int x = 0;
static unsigned int y = 0;
-	static bool flag = false;
static bool xy_lock = false;
-	policy = cpufreq_cpu_get(0);
+	unsigned long now = ktime_to_ms(ktime_get());

atomic_dec(&ts->next_work);
ts->ts_data.total_num = 0;
@@ -849,30 +850,43 @@ static void touch_work_func(struct work_struct *work)
}

touch_input_report(ts);
-
-	if (ts->ts_data.curr_data[0].state == ABS_PRESS) {
-	if(!xy_lock) {
+
+	if (likely(ts->ts_data.curr_data[0].state == ABS_PRESS))
+	{
+	if (!xy_lock)
+	{
x = ts->ts_data.curr_data[0].x_position;
y = ts->ts_data.curr_data[0].y_position;
xy_lock = true;
}

-	if (ts->ts_data.curr_data[0].x_position > (x + 100) || ts->ts_data.curr_data[0].x_position < (x - 100)) {
-	if (policy->cur < BOOST_FREQ)
-	__cpufreq_driver_target(policy, BOOST_FREQ, CPUFREQ_RELATION_H);
+	if (ts->ts_data.curr_data[0].x_position > (x + 100) ||
+	ts->ts_data.curr_data[0].x_position < (x - 100) ||
+	ts->ts_data.curr_data[0].y_position > (y + 100) ||
+	ts->ts_data.curr_data[0].y_position < (y - 100))
+	{
+	if (policy->cur < SWIPE_BOOST_FREQ)
+	__cpufreq_driver_target(policy, SWIPE_BOOST_FREQ,
+	CPUFREQ_RELATION_H);

-	flag = true;
-	} else if (ts->ts_data.curr_data[0].y_position > (y + 100) || ts->ts_data.curr_data[0].y_position < (y - 100)) {
-	if (policy->cur < BOOST_FREQ)
-	__cpufreq_driver_target(policy, BOOST_FREQ, CPUFREQ_RELATION_H);
+	is_touching(true, now);
+	}

-	flag = true;
+	else if (policy->cur < TOUCH_BOOST_FREQ && num_online_cpus() < 2)
+	{
+	__cpufreq_driver_target(policy, TOUCH_BOOST_FREQ,
+	CPUFREQ_RELATION_H);
}
-	} else {
-	x = 0;
-	y = 0;
-	flag = false;
-	xy_lock = false;
+	}
+
+	else
+	{
+	if (x != 0)
+	x = 0;
+	if (y != 0)
+	y = 0;
+	if (xy_lock)
+	xy_lock = false;
}
out:
if (likely(ts->pdata->role->operation_mode == INTERRUPT_MODE)) {
@@ -1843,6 +1857,8 @@ static int touch_probe(struct i2c_client *client,
int ret = 0;
int one_sec = 0;

+	policy = cpufreq_cpu_get(0);
+
if (unlikely(touch_debug_mask & DEBUG_TRACE))
TOUCH_DEBUG_MSG("\n");