|
@@ -187,6 +187,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
|
|
|
#define IT87_REG_FAN_MAIN_CTRL 0x13
|
|
|
#define IT87_REG_FAN_CTL 0x14
|
|
|
#define IT87_REG_PWM(nr) (0x15 + (nr))
|
|
|
+#define IT87_REG_PWM_DUTY(nr) (0x63 + (nr) * 8)
|
|
|
|
|
|
#define IT87_REG_VIN(nr) (0x20 + (nr))
|
|
|
#define IT87_REG_TEMP(nr) (0x29 + (nr))
|
|
@@ -251,12 +252,16 @@ struct it87_data {
|
|
|
u8 fan_main_ctrl; /* Register value */
|
|
|
u8 fan_ctl; /* Register value */
|
|
|
|
|
|
- /* The following 3 arrays correspond to the same registers. The
|
|
|
- * meaning of bits 6-0 depends on the value of bit 7, and we want
|
|
|
- * to preserve settings on mode changes, so we have to track all
|
|
|
- * values separately. */
|
|
|
+ /* The following 3 arrays correspond to the same registers up to
|
|
|
+ * the IT8720F. The meaning of bits 6-0 depends on the value of bit
|
|
|
+ * 7, and we want to preserve settings on mode changes, so we have
|
|
|
+ * to track all values separately.
|
|
|
+ * Starting with the IT8721F, the manual PWM duty cycles are stored
|
|
|
+ * in separate registers (8-bit values), so the separate tracking
|
|
|
+ * is no longer needed, but it is still done to keep the driver
|
|
|
+ * simple. */
|
|
|
u8 pwm_ctrl[3]; /* Register value */
|
|
|
- u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */
|
|
|
+ u8 pwm_duty[3]; /* Manual PWM value set by user */
|
|
|
u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */
|
|
|
|
|
|
/* Automatic fan speed control registers */
|
|
@@ -832,7 +837,9 @@ static ssize_t set_pwm_enable(struct device *dev,
|
|
|
data->fan_main_ctrl);
|
|
|
} else {
|
|
|
if (val == 1) /* Manual mode */
|
|
|
- data->pwm_ctrl[nr] = data->pwm_duty[nr];
|
|
|
+ data->pwm_ctrl[nr] = data->type == it8721 ?
|
|
|
+ data->pwm_temp_map[nr] :
|
|
|
+ data->pwm_duty[nr];
|
|
|
else /* Automatic mode */
|
|
|
data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
|
|
|
it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
|
|
@@ -858,12 +865,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
|
|
return -EINVAL;
|
|
|
|
|
|
mutex_lock(&data->update_lock);
|
|
|
- data->pwm_duty[nr] = pwm_to_reg(data, val);
|
|
|
- /* If we are in manual mode, write the duty cycle immediately;
|
|
|
- * otherwise, just store it for later use. */
|
|
|
- if (!(data->pwm_ctrl[nr] & 0x80)) {
|
|
|
- data->pwm_ctrl[nr] = data->pwm_duty[nr];
|
|
|
- it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
|
|
|
+ if (data->type == it8721) {
|
|
|
+ /* If we are in automatic mode, the PWM duty cycle register
|
|
|
+ * is read-only so we can't write the value */
|
|
|
+ if (data->pwm_ctrl[nr] & 0x80) {
|
|
|
+ mutex_unlock(&data->update_lock);
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+ data->pwm_duty[nr] = pwm_to_reg(data, val);
|
|
|
+ it87_write_value(data, IT87_REG_PWM_DUTY(nr),
|
|
|
+ data->pwm_duty[nr]);
|
|
|
+ } else {
|
|
|
+ data->pwm_duty[nr] = pwm_to_reg(data, val);
|
|
|
+ /* If we are in manual mode, write the duty cycle immediately;
|
|
|
+ * otherwise, just store it for later use. */
|
|
|
+ if (!(data->pwm_ctrl[nr] & 0x80)) {
|
|
|
+ data->pwm_ctrl[nr] = data->pwm_duty[nr];
|
|
|
+ it87_write_value(data, IT87_REG_PWM(nr),
|
|
|
+ data->pwm_ctrl[nr]);
|
|
|
+ }
|
|
|
}
|
|
|
mutex_unlock(&data->update_lock);
|
|
|
return count;
|
|
@@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev)
|
|
|
* channels to use when later setting to automatic mode later.
|
|
|
* Use a 1:1 mapping by default (we are clueless.)
|
|
|
* In both cases, the value can (and should) be changed by the user
|
|
|
- * prior to switching to a different mode. */
|
|
|
+ * prior to switching to a different mode.
|
|
|
+ * Note that this is no longer needed for the IT8721F and later, as
|
|
|
+ * these have separate registers for the temperature mapping and the
|
|
|
+ * manual duty cycle. */
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
data->pwm_temp_map[i] = i;
|
|
|
data->pwm_duty[i] = 0x7f; /* Full speed */
|
|
@@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev)
|
|
|
static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
|
|
|
{
|
|
|
data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
|
|
|
- if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
|
|
|
+ if (data->type == it8721) {
|
|
|
data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
|
|
|
- else /* Manual mode */
|
|
|
- data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
|
|
|
+ data->pwm_duty[nr] = it87_read_value(data,
|
|
|
+ IT87_REG_PWM_DUTY(nr));
|
|
|
+ } else {
|
|
|
+ if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
|
|
|
+ data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
|
|
|
+ else /* Manual mode */
|
|
|
+ data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
|
|
|
+ }
|
|
|
|
|
|
if (has_old_autopwm(data)) {
|
|
|
int i;
|