summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/therm_fan_est.c91
-rw-r--r--include/linux/therm_est.h2
2 files changed, 75 insertions, 18 deletions
diff --git a/drivers/misc/therm_fan_est.c b/drivers/misc/therm_fan_est.c
index 3d261376d47f..9a32eaffe821 100644
--- a/drivers/misc/therm_fan_est.c
+++ b/drivers/misc/therm_fan_est.c
@@ -42,12 +42,28 @@ struct therm_fan_estimator {
int ndevs;
struct therm_fan_est_subdevice *devs;
struct thermal_zone_device *thz;
+ int current_trip_index;
+ char *cdev_type;
int active_trip_temps[MAX_ACTIVE_STATES];
+ int active_hysteresis[MAX_ACTIVE_STATES];
+ int active_trip_temps_hyst[(MAX_ACTIVE_STATES << 1) + 1];
};
+
+static void fan_set_trip_temp_hyst(struct therm_fan_estimator *est, int trip,
+ unsigned long hyst_temp,
+ unsigned long trip_temp)
+{
+ est->active_hysteresis[trip] = hyst_temp;
+ est->active_trip_temps[trip] = trip_temp;
+ est->active_trip_temps_hyst[(trip << 1)] = trip_temp;
+ est->active_trip_temps_hyst[((trip - 1) << 1) + 1] =
+ trip_temp - hyst_temp;
+}
+
static void therm_fan_est_work_func(struct work_struct *work)
{
- int i, j, index, sum = 0;
+ int i, j, index, trip_index, sum = 0;
long temp;
struct delayed_work *dwork = container_of(work,
struct delayed_work, work);
@@ -72,10 +88,19 @@ static void therm_fan_est_work_func(struct work_struct *work)
est->cur_temp = sum / 100 + est->toffset;
- est->ntemp++;
+ for (trip_index = 0;
+ trip_index < ((MAX_ACTIVE_STATES << 1) + 1); trip_index++) {
+ if (est->cur_temp < est->active_trip_temps_hyst[trip_index])
+ break;
+ }
+
+ if (est->current_trip_index != (trip_index - 1)) {
+ est->current_trip_index = trip_index - 1;
+ if (!((trip_index - 1) % 2))
+ thermal_zone_device_update(est->thz);
+ }
- if (est->thz)
- thermal_zone_device_update(est->thz);
+ est->ntemp++;
queue_delayed_work(est->workqueue, &est->therm_fan_est_work,
msecs_to_jiffies(est->polling_period));
@@ -85,11 +110,10 @@ static int therm_fan_est_bind(struct thermal_zone_device *thz,
struct thermal_cooling_device *cdev)
{
int i;
-
- if (!strcmp(cdev->type, "pwm-fan")) {
+ struct therm_fan_estimator *est = thz->devdata;
+ if (!strcmp(cdev->type, est->cdev_type)) {
for (i = 0; i < MAX_ACTIVE_STATES; i++)
- thermal_zone_bind_cooling_device(thz, i, cdev,
- i + 1, i + 1);
+ thermal_zone_bind_cooling_device(thz, i, cdev, i, i);
}
return 0;
@@ -99,8 +123,8 @@ static int therm_fan_est_unbind(struct thermal_zone_device *thz,
struct thermal_cooling_device *cdev)
{
int i;
-
- if (!strcmp(cdev->type, "pwm-fan")) {
+ struct therm_fan_estimator *est = thz->devdata;
+ if (!strcmp(cdev->type, est->cdev_type)) {
for (i = 0; i < MAX_ACTIVE_STATES; i++)
thermal_zone_unbind_cooling_device(thz, i, cdev);
}
@@ -132,7 +156,11 @@ static int therm_fan_est_set_trip_temp(struct thermal_zone_device *thz,
{
struct therm_fan_estimator *est = thz->devdata;
- est->active_trip_temps[trip] = temp;
+ /*Need trip 0 to remain as it is*/
+ if (((temp - est->active_hysteresis[trip]) < 0) || (trip <= 0))
+ return -EINVAL;
+
+ fan_set_trip_temp_hyst(est, trip, est->active_hysteresis[trip], temp);
return 0;
}
@@ -145,10 +173,26 @@ static int therm_fan_est_get_temp(struct thermal_zone_device *thz,
return 0;
}
-static int therm_fan_est_get_trend(struct thermal_zone_device *thz,
- int trip, enum thermal_trend *trend)
+static int therm_fan_est_set_trip_hyst(struct thermal_zone_device *thz,
+ int trip, unsigned long hyst_temp)
+{
+ struct therm_fan_estimator *est = thz->devdata;
+
+ /*Need trip 0 to remain as it is*/
+ if ((est->active_trip_temps[trip] - hyst_temp) < 0 || trip <= 0)
+ return -EINVAL;
+
+ fan_set_trip_temp_hyst(est, trip,
+ hyst_temp, est->active_trip_temps[trip]);
+ return 0;
+}
+
+static int therm_fan_est_get_trip_hyst(struct thermal_zone_device *thz,
+ int trip, unsigned long *temp)
{
- *trend = THERMAL_TREND_RAISING;
+ struct therm_fan_estimator *est = thz->devdata;
+
+ *temp = est->active_hysteresis[trip];
return 0;
}
@@ -158,8 +202,9 @@ static struct thermal_zone_device_ops therm_fan_est_ops = {
.get_trip_type = therm_fan_est_get_trip_type,
.get_trip_temp = therm_fan_est_get_trip_temp,
.get_temp = therm_fan_est_get_temp,
- .get_trend = therm_fan_est_get_trend,
.set_trip_temp = therm_fan_est_set_trip_temp,
+ .get_trip_hyst = therm_fan_est_get_trip_hyst,
+ .set_trip_hyst = therm_fan_est_set_trip_hyst,
};
static ssize_t show_coeff(struct device *dev,
@@ -292,8 +337,17 @@ static int __devinit therm_fan_est_probe(struct platform_device *pdev)
est->toffset = data->toffset;
est->polling_period = data->polling_period;
- for (i = 0; i < MAX_ACTIVE_STATES; i++)
+ for (i = 0; i < MAX_ACTIVE_STATES; i++) {
est->active_trip_temps[i] = data->active_trip_temps[i];
+ est->active_hysteresis[i] = data->active_hysteresis[i];
+ }
+
+ est->active_trip_temps_hyst[0] = data->active_trip_temps[0];
+
+ for (i = 1; i < MAX_ACTIVE_STATES; i++)
+ fan_set_trip_temp_hyst(est, i,
+ data->active_hysteresis[i], est->active_trip_temps[i]);
+
/* initialize history */
for (i = 0; i < data->ndevs; i++) {
dev = &est->devs[i];
@@ -310,18 +364,19 @@ static int __devinit therm_fan_est_probe(struct platform_device *pdev)
if (!est->workqueue)
return -ENOMEM;
+ est->current_trip_index = 0;
+
INIT_DELAYED_WORK(&est->therm_fan_est_work, therm_fan_est_work_func);
queue_delayed_work(est->workqueue,
&est->therm_fan_est_work,
msecs_to_jiffies(est->polling_period));
-
+ est->cdev_type = data->cdev_type;
est->thz = thermal_zone_device_register((char *) dev_name(&pdev->dev),
10, 0x3FF, est,
&therm_fan_est_ops, NULL, 0, 0);
if (IS_ERR_OR_NULL(est->thz))
return -EINVAL;
-
for (i = 0; i < ARRAY_SIZE(therm_fan_est_nodes); i++)
device_create_file(&pdev->dev,
&therm_fan_est_nodes[i].dev_attr);
diff --git a/include/linux/therm_est.h b/include/linux/therm_est.h
index 8a61d0fa8df9..43f6bb3703ca 100644
--- a/include/linux/therm_est.h
+++ b/include/linux/therm_est.h
@@ -55,7 +55,9 @@ struct therm_fan_est_data {
long toffset;
long polling_period;
int ndevs;
+ char *cdev_type;
int active_trip_temps[MAX_ACTIVE_STATES];
+ int active_hysteresis[MAX_ACTIVE_STATES];
struct therm_fan_est_subdevice devs[];
};
#endif /* _LINUX_THERM_EST_H */