[Nexus 4 Original Android Development] franciscofranco:
Here is the new r666. The pseudo code of the touch core boosting is now implemented. I have no idea about the battery life, I just merely finished and polished the code. Here's the diff. boot.img attached.

diff --git a/arch/arm/kernel/mako_hotplug.c b/arch/arm/kernel/mako_hotplug.c
index 34ba386..5dd1378 100644
--- a/arch/arm/kernel/mako_hotplug.c
+++ b/arch/arm/kernel/mako_hotplug.c
@@ -15,16 +15,21 @@
#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 TOUCH_PULSE_DURATION 80
+#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 +39,24 @@ 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 int load_history[HISTORY_SIZE] = {0};
unsigned int counter = 0;

+void is_touching(bool touch)
+{
+ is_touched = touch;
+}
+
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 +67,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 +75,51 @@ 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 +131,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 +180,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,17 +187,31 @@ 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);
+ pr_info("EXTRA COUNTER: %d\n", extra_counter);
*/

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;
}
-
+
+ else if (is_touched)
+ {
+ if ((now - stats.time_stamp) >= TOUCH_PULSE_DURATION)
+ is_touched = false;
+
+ 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)
+ else if (load >= second_level && stats.online_cpus < stats.total_cpus)
{
/* feed it 2 times the seconds threshold because when this is called
there is a check inside that onlines cpu1 bypassing the time_diff
@@ -192,26 +220,15 @@ static void decide_hotplug_func(struct work_struct *work)
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);
+ 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));
@@ -236,7 +253,7 @@ static void mako_hotplug_early_suspend(struct early_suspend *handler)
static void mako_hotplug_late_resume(struct early_suspend *handler)
{
/* 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()));

/* restore default 1,5GHz max frequency */
msm_cpufreq_set_freq_limits(0, MSM_CPUFREQ_NO_LIMIT, MSM_CPUFREQ_NO_LIMIT);
@@ -306,7 +323,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/input/touchscreen/lge_touch_core.c b/drivers/input/touchscreen/lge_touch_core.c
index 8c2ed9e..a7e2cab 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>
@@ -809,9 +810,7 @@ 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);

atomic_dec(&ts->next_work);
ts->ts_data.total_num = 0;
@@ -861,18 +860,20 @@ static void touch_work_func(struct work_struct *work)
if (policy->cur < BOOST_FREQ)
__cpufreq_driver_target(policy, BOOST_FREQ, CPUFREQ_RELATION_H);

-	flag = true;
+	is_touching(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);

-	flag = true;
+	is_touching(true);
}
} else {
-	x = 0;
-	y = 0;
-	flag = false;
-	xy_lock = false;
+	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 +1844,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");