int switch_on_temp;
int desired_id;
int desired_temp;
+ int k_p;
+ int k_i;
+ s64 integral;
};
struct _thermal_zone {
{
s64 temp_diff;
int desired_temp = zone->trip_ctrl_alg.desired_temp;
- s64 power_budget;
+ s64 power_budget, p, i;
+ s64 decay;
+ int k_i = zone->trip_ctrl_alg.k_i;
struct thermal_zone_device *tz = zone->tz;
/* temperature is represented in milidegress */
temp_diff = desired_temp - tz->temperature;
- power_budget = temp_diff;
+ p = temp_diff * zone->trip_ctrl_alg.k_p;
+
+ i = zone->trip_ctrl_alg.integral * k_i;
+
+ if (temp_diff < 0) {
+ s64 i_0 = i + k_i * temp_diff;
+
+ zone->trip_ctrl_alg.integral += temp_diff;
+ }
+
+ power_budget = p + i;
+ power_budget >>= 10;
power_budget = max(0LL, power_budget);
+ /* decay of 1/8 (~12.5%), after a while will reach 0 */
+ decay = zone->trip_ctrl_alg.integral >> 3;
+ zone->trip_ctrl_alg.integral -= decay;
+
return power_budget;
}
zone->trip_ctrl_alg.switch_on_id = -EINVAL;
zone->trip_ctrl_alg.desired_id = -EINVAL;
+ zone->trip_ctrl_alg.k_p = DEFAULT_K_P;
+ zone->trip_ctrl_alg.k_i = DEFAULT_K_I;
for (i = 0; i < tz->trips; i++) {
ret = tz->ops->get_trip_ctrl_alg_flag(tz, i,