pwm fan control with IT8705F I/O chip it87 module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jonas,

Thanks for the patch and sorry for the delay, crazy week here...

> Here is an updated version of that patch. The pwm values are now
> stored internally as 8 bit instead of throwing away the lowest bit as
> it did earlier (the chip's pwm registers are 7 bit).

Well, why not... Doesn't change much actally, does it?

See my comments inline.

> -/* Reset the registers on init if true */
> -static int reset;

I'm very happy to see this one go :)

> @@ -200,6 +202,8 @@ struct it87_data {
>  	u8 vid;			/* Register encoding, combined */
>  	int vrm;
>  	u32 alarms;		/* Register encoding, combined */
> +	u8 fan_main_ctrl;	/* Register value */
> +	u8 manual_pwm_ctl[3];   /* Register encoding, shifted left */

This is more of a value than encoding.  Also, this is not really a
register value anymore since you will store the value given by the user
on 8-bit, and feed the register with a modified version of it. The fact
that the conversion operation is a simple 1-bit shift is incidental.
What manual_pwm_ctl really holds now is a "real" PWM value, not a
register encoding/value, right?

>  static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
>  {
>  	struct it87_data *data = it87_update_device(dev);
> -	return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
> +	return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]));

While you're at it, please add a white space after the first comma. Same
holds for the rest of the file, whether you modify lines or add them.

> +static ssize_t set_pwm_enable(struct device *dev, const char *buf,
> +		size_t count, int nr)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct it87_data *data = i2c_get_clientdata(client);
> +	int tmp;
> +	int val = simple_strtol(buf, NULL, 10);
> +
> +	if (val == 0) {
> +		data->fan_main_ctrl &= ~(1 << nr);
> +		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
> +		/* make sure the fan is on */
> +		tmp = it87_read_value(client, IT87_REG_FAN_CTL);
> +		if ((tmp & (1 << nr)) == 0)
> +			it87_write_value(client, IT87_REG_FAN_CTL, tmp | (1 << nr));

You can probably get rid of this check... See below.

> +	} else if (val == 1) {
> +		/* set SmartGuardian mode */
> +		data->fan_main_ctrl |= (1 << nr);
> +		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
> +		/* set saved pwm value and FAN_CTLX PWM mode bit */
> +		it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));

Doesn't quite match your description of manual_pwm_ctl. This will work
OK in manual PWM mode, but if the chip was in automatic mode it'll
switch to manual at this point, right? So the FAN_CTLX PWM mode bit
isn't restored. I'm fine with the code, but the comment would need to be
updated.

> +#define show_pwm_offset(offset)						\
> +static ssize_t show_pwm##offset##_enable (struct device *dev,		\
> +	char *buf)							\
> +{									\
> +	return show_pwm_enable(dev, buf, 0x##offset - 1);		\

Get rid of the 0x## (in other functions too). Mark M. Hoffman got rid of
all of them some times ago (to my great pleasure, needless to say),
let's not introduce them anew.

> +	/* Set current fan mode registers and the default settings for the
> +	 * other mode registers */
> +	for (i = 0; i < 3; i++) {
> +		if (data->fan_main_ctrl & (1 << i)) {
> +			/* pwm mode */
> +			tmp = it87_read_value(client, IT87_REG_PWM(i));
> +			if (tmp & 0x80) {
> +				/* automatic pwm - not yet implemented, but
> +				 * leave the settings made by the BIOS alone
> +				 * until a change is requested via the sysfs
> +				 * interface */
> +			} else {
> +				/* manual pwm */
> +				data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp);
> +			}
> +		} else {
> +			/* on/off mode, make sure the fan is on */
> +			tmp = it87_read_value(client, IT87_REG_FAN_CTL);
> +			if ((tmp & (1 << i)) == 0)
> +				it87_write_value(client,
> +						IT87_REG_FAN_CTL, tmp | (1 << i));
> +		}
> + 	}

The last part here could be simplified IMHO. Just do:
  tmp = it87_read_value(client, IT87_REG_FAN_CTL);
  it87_write_value(client, IT87_REG_FAN_CTL, tmp | 0x07);
to permanently "lock" fans to "on" in "on/off" mode. This is the
expected behavior according to our sysfs interface (pwm off == fan to
full speed).

Doing so spares you several checks and multiple reads/writes on the same
register. This also lets you get rid of some code in set_pwm_enable above.

Note that one could argue that we are not exactly doing the right thing
here. If any fan was in on/off mode and actually stopped (off), we will
fire it up here (both your code and mine) which is contrary to our
policy of non-intrusiveness. The correct behavior would be to switch to
manual PWM mode and set the duty cycle to 0. Or we can do it the other
way around, i.e. the driver would implement manual PWM 0 by switching
the fan to on/off mode, value off. This probably would waste less power
too. However this will make things more complex and I would agree not to
go that direction for now. This can be done at a later time is needed.

OK, looks good overall, please fix the few comment and coding style
issues, change the code where you agree with my proposals, and subit the
patch again. Don't forget to CC: Greg KH if you want him to catch it!

Thanks for the good work,
-- 
Jean Delvare
http://khali.linux-fr.org/



[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux