From: Ziggy Date: Sat, 19 Jan 2013 21:05:42 +0000 (-0500) Subject: Add screen off profile to mpdecision X-Git-Url: https://ziggy471.com/git/gitweb.cgi?p=ziggy471-sgs3-jb.git;a=commitdiff;h=21db4de8770a6a611dfa720298e17f9232d90355 Add screen off profile to mpdecision Signed-off-by: Ziggy --- --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1532,6 +1532,35 @@ config MSM_MPDEC This enables kernel based multi core control. (up/down hotplug based on load) +config MSM_MPDEC_STARTDELAY + int "Starup delay for MPDECISION (ms)" + depends on MSM_MPDEC + default 20000 + +config MSM_MPDEC_DELAY + int "MPDECISION Delay (ms)" + depends on MSM_MPDEC + default 70 + +config MSM_MPDEC_PAUSE + int "MPDECISION Pause (ms)" + depends on MSM_MPDEC + default 10000 + +config MSM_MPDEC_IDLE_FREQ + int "MPDECISION Idle Frequency (khz)" + depends on MSM_MPDEC + default 486000 + +config MSM_MPDEC_SCROFF_FREQ + int "Max frequency when screen is off (khz)" + depends on MSM_MPDEC + default 486000 + +config MSM_MPDEC_SCROFF_BOOT_DELAY + int "Disable Screen off for X seconds after boot" + depends on MSM_MPDEC + default 600 if CPU_FREQ_MSM --- a/arch/arm/mach-msm/msm_mpdecision.c +++ b/arch/arm/mach-msm/msm_mpdecision.c @@ -37,11 +37,12 @@ #define DEBUG 0 -#define MPDEC_TAG "[AnThRaX MPDEC]: " -#define MSM_MPDEC_STARTDELAY 20000 -#define MSM_MPDEC_DELAY 70 -#define MSM_MPDEC_PAUSE 10000 -#define MSM_MPDEC_IDLE_FREQ 486000 +#define MPDEC_TAG "[MSM MPDEC]: " +#define MSM_MPDEC_STARTDELAY CONFIG_MSM_MPDEC_STARTDELAY +#define MSM_MPDEC_DELAY CONFIG_MSM_MPDEC_DELAY +#define MSM_MPDEC_PAUSE CONFIG_MSM_MPDEC_PAUSE +#define MSM_MPDEC_IDLE_FREQ CONFIG_MSM_MPDEC_IDLE_FREQ +#define MSM_MPDEC_SCROFF_FREQ CONFIG_MSM_MPDEC_SCROFF_FREQ enum { MSM_MPDEC_DISABLED = 0, @@ -53,8 +54,10 @@ enum { struct msm_mpdec_cpudata_t { struct mutex suspend_mutex; int online; - int device_suspended; + bool device_suspended; cputime64_t on_time; + unsigned int max; + bool cpu_sleeping; }; static DEFINE_PER_CPU(struct msm_mpdec_cpudata_t, msm_mpdec_cpudata); @@ -67,7 +70,9 @@ static struct msm_mpdec_tuners { unsigned int delay; unsigned int pause; bool scroff_single_core; + bool scroff_profile; unsigned long int idle_freq; + unsigned long int scroff_freq; unsigned int max_cpus; unsigned int min_cpus; } msm_mpdec_tuners_ins = { @@ -75,7 +80,9 @@ static struct msm_mpdec_tuners { .delay = MSM_MPDEC_DELAY, .pause = MSM_MPDEC_PAUSE, .scroff_single_core = true, + .scroff_profile = true, .idle_freq = MSM_MPDEC_IDLE_FREQ, + .scroff_freq = MSM_MPDEC_SCROFF_FREQ, .max_cpus = CONFIG_NR_CPUS, .min_cpus = 1, }; @@ -89,6 +96,20 @@ extern unsigned long acpuclk_get_rate(in unsigned int state = MSM_MPDEC_IDLE; bool was_paused = false; +static void update_cpu_max_freq(int max_freq) +{ + pr_info(MPDEC_TAG"Update Max Freq enter --%d--\n", max_freq); + + if (max_freq >= MAX_FREQ_LIMIT) + cpufreq_set_limit_defered(USER_MAX_STOP, max_freq); + else if (max_freq >= MIN_FREQ_LIMIT) + cpufreq_set_limit_defered(USER_MAX_START, max_freq); + + pr_info(MPDEC_TAG"Update Max Freq leave --%d--\n", max_freq); + + return; +} + static unsigned long get_rate(int cpu) { return acpuclk_get_rate(cpu); @@ -191,8 +212,8 @@ static int mp_decision(void) last_time = ktime_to_ms(ktime_get()); #if DEBUG - pr_info(MPDEC_TAG"[DEBUG] rq: %u, new_state: %i | Mask=[%d%d%d%d]\n", - rq_depth, new_state, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + pr_info(MPDEC_TAG"[DEBUG] rq: %u, new_state: %i | Mask=[%d%d%d%d]\n", + rq_depth, new_state, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); #endif return new_state; } @@ -289,50 +310,84 @@ out: return; } +static int checkuptime(void) +{ + struct timespec uptime; + + do_posix_clock_monotonic_gettime(&uptime); + + if (uptime.tv_sec > CONFIG_MSM_MPDEC_SCROFF_BOOT_DELAY) + return 1; + else + return 0; +} + static void msm_mpdec_early_suspend(struct early_suspend *h) { int cpu = nr_cpu_ids; + char cpu_mask[CONFIG_NR_CPUS +1] = ""; + char cpu_online_string[2] = ""; + struct cpufreq_policy *cpu_policy = NULL; + + pr_info(MPDEC_TAG"Screen -> off.\n"); for_each_possible_cpu(cpu) { mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).suspend_mutex); if ((cpu >= 1) && (cpu_online(cpu))) { cpu_down(cpu); - pr_info(MPDEC_TAG"Screen -> off. Suspended CPU[%d] | Mask=[%d%d%d%d]\n", - cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + pr_info(MPDEC_TAG"Screen -> off. Suspended CPU%d.\n", cpu); per_cpu(msm_mpdec_cpudata, cpu).online = false; } + if ((cpu_online(cpu) == 1) && (msm_mpdec_tuners_ins.scroff_profile) && (checkuptime())) { + cpu_policy = cpufreq_cpu_get(cpu); + per_cpu(msm_mpdec_cpudata, cpu).max = cpu_policy->max; + update_cpu_max_freq(msm_mpdec_tuners_ins.scroff_freq); + pr_info(MPDEC_TAG"Entered sleep profile on CPU%d successfully.\n", cpu); + per_cpu(msm_mpdec_cpudata, cpu).cpu_sleeping = true; + } per_cpu(msm_mpdec_cpudata, cpu).device_suspended = true; + sprintf(cpu_online_string, "%d", cpu_online(cpu)); + strncat(cpu_mask,cpu_online_string,1); mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).suspend_mutex); } /* main work thread can sleep now */ cancel_delayed_work_sync(&msm_mpdec_work); - pr_info(MPDEC_TAG"Screen -> off. Deactivated mpdecision.\n"); + pr_info(MPDEC_TAG"CPU Mask = [%s].\n",cpu_mask); } static void msm_mpdec_late_resume(struct early_suspend *h) { int cpu = nr_cpu_ids; - for_each_possible_cpu(cpu) - per_cpu(msm_mpdec_cpudata, cpu).device_suspended = false; + char cpu_mask[CONFIG_NR_CPUS +1] = ""; + char cpu_online_string[2] = ""; - mutex_lock(&per_cpu(msm_mpdec_cpudata, 1).suspend_mutex); - if (!cpu_online(1)) { - /* Always enable cpu1 when screen comes online. - * This boosts the wakeup process. */ - cpu_up(1); - per_cpu(msm_mpdec_cpudata, 1).on_time = ktime_to_ms(ktime_get()); - per_cpu(msm_mpdec_cpudata, 1).online = true; - pr_info(MPDEC_TAG"Screen -> on. Hot plugged CPU1 | Mask=[%d%d%d%d]\n", - cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + pr_info(MPDEC_TAG"Screen -> on.\n"); + for_each_possible_cpu(cpu) { + mutex_lock(&per_cpu(msm_mpdec_cpudata, 1).suspend_mutex); + per_cpu(msm_mpdec_cpudata, cpu).device_suspended = false; + if ((cpu_online(cpu) == 1) && (msm_mpdec_tuners_ins.scroff_profile) && (checkuptime())) { + update_cpu_max_freq(per_cpu(msm_mpdec_cpudata, cpu).max); + pr_info(MPDEC_TAG"Entered wake profile on CPU%d successfully.\n", cpu); + per_cpu(msm_mpdec_cpudata, cpu).cpu_sleeping = false; + } + if (!cpu_online(cpu)) { + /* Turn on all cpus when the screen comes on + * This boost the wakeup process. */ + cpu_up(cpu); + per_cpu(msm_mpdec_cpudata, cpu).on_time = ktime_to_ms(ktime_get()); + per_cpu(msm_mpdec_cpudata, cpu).online = true; + } + sprintf(cpu_online_string, "%d", cpu_online(cpu)); + strncat(cpu_mask,cpu_online_string,1); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, 1).suspend_mutex); } - mutex_unlock(&per_cpu(msm_mpdec_cpudata, 1).suspend_mutex); + + pr_info(MPDEC_TAG"CPU Mask = [%s].\n",cpu_mask); /* wake up main work thread */ was_paused = true; queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, 0); - pr_info(MPDEC_TAG"Screen -> on. Activated mpdecision. | Mask=[%d%d%d%d]\n", - cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); } static struct early_suspend msm_mpdec_early_suspend_handler = { @@ -357,6 +412,13 @@ show_one(pause, pause); show_one(scroff_single_core, scroff_single_core); show_one(min_cpus, min_cpus); show_one(max_cpus, max_cpus); +show_one(scroff_profile, scroff_profile); + +static ssize_t show_scroff_freq (struct kobject *kobj, struct attribute *attr, + char *buf) +{ + return sprintf(buf, "%lu\n", msm_mpdec_tuners_ins.scroff_freq); +} #define show_one_twts(file_name, arraypos) \ static ssize_t show_##file_name \ @@ -513,6 +575,19 @@ static ssize_t store_idle_freq(struct ko return count; } +static ssize_t store_scroff_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + long unsigned int input; + int ret; + ret = sscanf(buf, "%lu", &input); + if (ret != 1) + return -EINVAL; + msm_mpdec_tuners_ins.scroff_freq = input; + + return count; +} + static ssize_t store_scroff_single_core(struct kobject *a, struct attribute *b, const char *buf, size_t count) { @@ -562,6 +637,51 @@ static ssize_t store_min_cpus(struct kob return count; } +static ssize_t store_scroff_profile(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + size_t ret = count; + int cpu; + struct cpufreq_policy *cpu_policy = NULL; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + switch (buf[0]) { + case '0': + msm_mpdec_tuners_ins.scroff_profile = input; + break; + case '1': + msm_mpdec_tuners_ins.scroff_profile = input; + break; + default: + ret = -EINVAL; + } + + for_each_possible_cpu(cpu) { + if (per_cpu(msm_mpdec_cpudata, cpu).device_suspended == true) { + if (per_cpu(msm_mpdec_cpudata, cpu).cpu_sleeping == true) { + if ((cpu_online(cpu) == 1) && (msm_mpdec_tuners_ins.scroff_profile == false) && (checkuptime())) { + update_cpu_max_freq(per_cpu(msm_mpdec_cpudata, cpu).max); + pr_info(MPDEC_TAG"Entered wake profile on CPU%d successfully.\n", cpu); + per_cpu(msm_mpdec_cpudata, cpu).cpu_sleeping = false; + } + } else { + if ((cpu_online(cpu) == 1) && (msm_mpdec_tuners_ins.scroff_profile) && (checkuptime())) { + cpu_policy = cpufreq_cpu_get(cpu); + per_cpu(msm_mpdec_cpudata, cpu).max = cpu_policy->max; + update_cpu_max_freq(msm_mpdec_tuners_ins.scroff_freq); + pr_info(MPDEC_TAG"Entered sleep profile on CPU%d successfully.\n", cpu); + per_cpu(msm_mpdec_cpudata, cpu).cpu_sleeping = true; + } + } + } + } + + return ret; +} + static ssize_t store_enabled(struct kobject *a, struct attribute *b, const char *buf, size_t count) { @@ -605,8 +725,7 @@ static ssize_t store_enabled(struct kobj case '1': state = MSM_MPDEC_IDLE; was_paused = true; - queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, - msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); pr_info(MPDEC_TAG" ENABLED mpdecision...\n"); break; default: @@ -619,7 +738,9 @@ define_one_global_rw(startdelay); define_one_global_rw(delay); define_one_global_rw(pause); define_one_global_rw(scroff_single_core); +define_one_global_rw(scroff_profile); define_one_global_rw(idle_freq); +define_one_global_rw(scroff_freq); define_one_global_rw(min_cpus); define_one_global_rw(max_cpus); define_one_global_rw(enabled); @@ -649,6 +770,8 @@ static struct attribute *msm_mpdec_attri &nwns_threshold_5.attr, &nwns_threshold_6.attr, &nwns_threshold_7.attr, + &scroff_profile.attr, + &scroff_freq.attr, NULL }; @@ -684,13 +807,13 @@ static int __init msm_mpdec_init(void) msm_mpdec_kobject = kobject_create_and_add("msm_mpdecision", kernel_kobj); if (msm_mpdec_kobject) { - rc = sysfs_create_group(msm_mpdec_kobject, - &msm_mpdec_attr_group); + rc = sysfs_create_group(msm_mpdec_kobject, &msm_mpdec_attr_group); if (rc) { pr_warn(MPDEC_TAG"sysfs: ERROR, could not create sysfs group"); } - } else + } else { pr_warn(MPDEC_TAG"sysfs: ERROR, could not create sysfs kobj"); + } pr_info(MPDEC_TAG"%s init complete.", __func__); @@ -704,4 +827,4 @@ void msm_mpdec_exit(void) destroy_workqueue(msm_mpdec_workq); } -MODULE_DESCRIPTION("Kernel based MPDECISION (C) 2011-12 Chad Goodman"); +MODULE_DESCRIPTION("Kernel based MPDECISION (C) 2011-13 Chad Goodman"); --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2106,6 +2106,7 @@ int cpufreq_set_limit_defered(unsigned i return ret; } +EXPORT_SYMBOL(cpufreq_set_limit_defered); #endif --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -341,17 +341,17 @@ static inline unsigned int cpufreq_quick #ifdef CONFIG_SEC_DVFS -#define TOUCH_BOOSTER_FIRST_FREQ_LIMIT 1134000 -#define TOUCH_BOOSTER_SECOND_FREQ_LIMIT 810000 -#define TOUCH_BOOSTER_FREQ_LIMIT 486000 +#define TOUCH_BOOSTER_FIRST_FREQ_LIMIT 1134000 +#define TOUCH_BOOSTER_SECOND_FREQ_LIMIT 810000 +#define TOUCH_BOOSTER_FREQ_LIMIT 486000 -#define LOW_MAX_FREQ_LIMIT 1188000 +#define LOW_MAX_FREQ_LIMIT 1188000 -#define MIN_FREQ_LIMIT CONFIG_CPU_FREQ_MIN_SCALING_LIMIT -#define MAX_FREQ_LIMIT CONFIG_CPU_FREQ_MAX_SCALING_LIMIT - #define FREQ_TABLE_SIZE 38 - #define FREQ_TABLE_SIZE_OFFSET 6 - #define FREQ_STEPS 30 +#define MIN_FREQ_LIMIT CONFIG_CPU_FREQ_MIN_SCALING_LIMIT +#define MAX_FREQ_LIMIT CONFIG_CPU_FREQ_MAX_SCALING_LIMIT +#define FREQ_TABLE_SIZE 38 +#define FREQ_TABLE_SIZE_OFFSET 6 +#define FREQ_STEPS 30 enum { SET_MIN = 0,