--- c18e65e572c7c3144440bad43ade9a7d507fc4b0 +++ 4fd8c860b7ca7d83dc068450b34ce202d3e49459 @@ -28,6 +28,7 @@ #include #include #include +#include #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ "cpufreq-core", msg) @@ -647,6 +648,96 @@ static ssize_t show_scaling_setspeed(str return policy->governor->show_setspeed(policy, buf); } +#ifdef CONFIG_CPU_FREQ_VDD_LEVELS + +extern ssize_t acpuclk_get_vdd_levels_str(char *buf); +#ifdef CONFIG_MSM_CPU_AVS +static ssize_t show_vdd_levels_havs(struct cpufreq_policy *policy, char *buf) +#else +static ssize_t show_vdd_levels(struct cpufreq_policy *policy, char *buf) +#endif +{ + return acpuclk_get_vdd_levels_str(buf); +} + +#ifdef CONFIG_MSM_CPU_AVS +extern void acpuclk_set_vdd(unsigned acpu_khz, int min_vdd, int max_vdd); +static ssize_t store_vdd_levels_havs(struct cpufreq_policy *policy, const char *buf, size_t count) +#else +extern void acpuclk_set_vdd(unsigned acpu_khz, int max_vdd); +static ssize_t store_vdd_levels(struct cpufreq_policy *policy, const char *buf, size_t count) +#endif +{ + int i = 0, j; + int pair[3] = { 0, 0, 0 }; + int sign = 0; + + if (count < 1) + return 0; + + if (buf[0] == '-') + { + sign = -1; + i++; + } + else if (buf[0] == '+') + { + sign = 1; + i++; + } + + for (j = 0; i < count; i++) + { + char c = buf[i]; + if ((c >= '0') && (c <= '9')) + { + pair[j] *= 10; + pair[j] += (c - '0'); + } + else if ((c == ' ') || (c == '\t')) + { + if (pair[j] != 0) + { + j++; +#ifndef CONFIG_MSM_CPU_AVS + if ((sign != 0) || (j > 1)) +#else + if ((sign != 0) || (j > 2)) +#endif + break; + } + } + else + break; + } + + if (sign != 0) + { + if (pair[0] > 0) +#ifndef CONFIG_MSM_CPU_AVS + acpuclk_set_vdd(0, sign * pair[0]); +#else + acpuclk_set_vdd(0, sign * pair[0], 0); +#endif + } + else + { +#ifndef CONFIG_MSM_CPU_AVS + if ((pair[0] > 0) && (pair[1] > 0)) + acpuclk_set_vdd((unsigned)pair[0], pair[1]); +#else + if ((pair[0] > 0) && (pair[1] > 0) && (pair[2] > 0)) + acpuclk_set_vdd((unsigned)pair[0], pair[1], pair[2]); +#endif + else + return -EINVAL; + } + + return count; +} + +#endif + #define define_one_ro(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) @@ -672,6 +763,13 @@ define_one_rw(scaling_min_freq); define_one_rw(scaling_max_freq); define_one_rw(scaling_governor); define_one_rw(scaling_setspeed); +#ifdef CONFIG_CPU_FREQ_VDD_LEVELS +#ifdef CONFIG_MSM_CPU_AVS +define_one_rw(vdd_levels_havs); +#else +define_one_rw(vdd_levels); +#endif +#endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, @@ -685,6 +783,13 @@ static struct attribute *default_attrs[] &scaling_driver.attr, &scaling_available_governors.attr, &scaling_setspeed.attr, +#ifdef CONFIG_CPU_FREQ_VDD_LEVELS +#ifdef CONFIG_MSM_CPU_AVS + &vdd_levels_havs.attr, +#else + &vdd_levels.attr, +#endif +#endif NULL }; @@ -1505,6 +1610,12 @@ int __cpufreq_driver_target(struct cpufr target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); + if (likely(retval != -EINVAL)) { + if (target_freq == policy->max) + cpu_nonscaling(policy->cpu); + else + cpu_scaling(policy->cpu); + } return retval; }