forked from Minki/linux
hwmon: (lm63) Let the user adjust the lookup table
Make the automatic fan speed control lookup table writable. This lets the user tweak the fan speed / temperature response curve. Signed-off-by: Jean Delvare <khali@linux-fr.org> Acked-by: Guenter Roeck <guenter.roeck@ericsson.com> Tested-by: Guenter Roeck <guenter.roeck@ericsson.com>
This commit is contained in:
parent
817c6cc546
commit
af2ef4fc04
@ -205,6 +205,15 @@ static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
|
||||
return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
|
||||
}
|
||||
|
||||
static inline int lut_temp_to_reg(struct lm63_data *data, long val)
|
||||
{
|
||||
val -= data->temp2_offset;
|
||||
if (data->lut_temp_highres)
|
||||
return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127500), 500);
|
||||
else
|
||||
return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127000), 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the lookup table register cache.
|
||||
* client->update_lock must be held when calling this function.
|
||||
@ -387,13 +396,16 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
|
||||
return sprintf(buf, "%d\n", pwm);
|
||||
}
|
||||
|
||||
static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
|
||||
static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm63_data *data = i2c_get_clientdata(client);
|
||||
int nr = attr->index;
|
||||
unsigned long val;
|
||||
int err;
|
||||
u8 reg;
|
||||
|
||||
if (!(data->config_fan & 0x20)) /* register is read-only */
|
||||
return -EPERM;
|
||||
@ -402,11 +414,13 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
reg = nr ? LM63_REG_LUT_PWM(nr - 1) : LM63_REG_PWM_VALUE;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm1[0] = data->pwm_highres ? val :
|
||||
data->pwm1[nr] = data->pwm_highres ? val :
|
||||
(val * data->pwm1_freq * 2 + 127) / 255;
|
||||
i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
|
||||
i2c_smbus_write_byte_data(client, reg, data->pwm1[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
@ -495,23 +509,31 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm63_data *data = i2c_get_clientdata(client);
|
||||
int nr = attr->index;
|
||||
int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
|
||||
long val;
|
||||
int err;
|
||||
int temp;
|
||||
u8 reg;
|
||||
|
||||
err = kstrtol(buf, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (nr == 2) {
|
||||
switch (nr) {
|
||||
case 2:
|
||||
reg = LM63_REG_REMOTE_TCRIT;
|
||||
if (data->remote_unsigned)
|
||||
temp = TEMP8U_TO_REG(val - data->temp2_offset);
|
||||
else
|
||||
temp = TEMP8_TO_REG(val - data->temp2_offset);
|
||||
} else {
|
||||
break;
|
||||
case 1:
|
||||
reg = LM63_REG_LOCAL_HIGH;
|
||||
temp = TEMP8_TO_REG(val);
|
||||
break;
|
||||
default: /* lookup table */
|
||||
reg = LM63_REG_LUT_TEMP(nr - 3);
|
||||
temp = lut_temp_to_reg(data, val);
|
||||
}
|
||||
data->temp8[nr] = temp;
|
||||
i2c_smbus_write_byte_data(client, reg, temp);
|
||||
@ -743,64 +765,76 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
|
||||
static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
|
||||
show_pwm1_enable, set_pwm1_enable);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 2);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 7);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 8);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 7);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 9);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 8);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 10);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 9);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 11);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 10);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 12);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 11);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 13);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO,
|
||||
show_lut_temp, NULL, 14);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IWUSR | S_IRUGO,
|
||||
show_pwm1, set_pwm1, 12);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IWUSR | S_IRUGO,
|
||||
show_lut_temp, set_temp8, 14);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO,
|
||||
show_lut_temp_hyst, NULL, 14);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user