diff options
Diffstat (limited to 'drivers/hwmon/f75375s.c')
-rw-r--r-- | drivers/hwmon/f75375s.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index eb648d9c91d6..9ab034a1b4c1 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c | |||
@@ -264,6 +264,21 @@ static inline u16 rpm_to_reg(int rpm) | |||
264 | return 1500000 / rpm; | 264 | return 1500000 / rpm; |
265 | } | 265 | } |
266 | 266 | ||
267 | static bool duty_mode_enabled(u8 pwm_enable) | ||
268 | { | ||
269 | switch (pwm_enable) { | ||
270 | case 0: /* Manual, duty mode (full speed) */ | ||
271 | case 1: /* Manual, duty mode */ | ||
272 | case 4: /* Auto, duty mode */ | ||
273 | return true; | ||
274 | case 2: /* Auto, speed mode */ | ||
275 | case 3: /* Manual, speed mode */ | ||
276 | return false; | ||
277 | default: | ||
278 | BUG(); | ||
279 | } | ||
280 | } | ||
281 | |||
267 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 282 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
268 | const char *buf, size_t count) | 283 | const char *buf, size_t count) |
269 | { | 284 | { |
@@ -337,11 +352,15 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
337 | struct f75375_data *data = i2c_get_clientdata(client); | 352 | struct f75375_data *data = i2c_get_clientdata(client); |
338 | u8 fanmode; | 353 | u8 fanmode; |
339 | 354 | ||
340 | if (val < 0 || val > 3) | 355 | if (val < 0 || val > 4) |
341 | return -EINVAL; | 356 | return -EINVAL; |
342 | 357 | ||
343 | fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); | 358 | fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); |
344 | if (data->kind == f75387) { | 359 | if (data->kind == f75387) { |
360 | /* For now, deny dangerous toggling of duty mode */ | ||
361 | if (duty_mode_enabled(data->pwm_enable[nr]) != | ||
362 | duty_mode_enabled(val)) | ||
363 | return -EOPNOTSUPP; | ||
345 | /* clear each fanX_mode bit before setting them properly */ | 364 | /* clear each fanX_mode bit before setting them properly */ |
346 | fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); | 365 | fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); |
347 | fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); | 366 | fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); |
@@ -355,12 +374,14 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
355 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); | 374 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); |
356 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | 375 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); |
357 | break; | 376 | break; |
358 | case 2: /* AUTOMATIC*/ | 377 | case 2: /* Automatic, speed mode */ |
359 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | ||
360 | break; | 378 | break; |
361 | case 3: /* fan speed */ | 379 | case 3: /* fan speed */ |
362 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); | 380 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); |
363 | break; | 381 | break; |
382 | case 4: /* Automatic, pwm */ | ||
383 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | ||
384 | break; | ||
364 | } | 385 | } |
365 | } else { | 386 | } else { |
366 | /* clear each fanX_mode bit before setting them properly */ | 387 | /* clear each fanX_mode bit before setting them properly */ |
@@ -378,6 +399,8 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
378 | break; | 399 | break; |
379 | case 3: /* fan speed */ | 400 | case 3: /* fan speed */ |
380 | break; | 401 | break; |
402 | case 4: /* Automatic pwm */ | ||
403 | return -EINVAL; | ||
381 | } | 404 | } |
382 | } | 405 | } |
383 | 406 | ||
@@ -735,14 +758,17 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, | |||
735 | 758 | ||
736 | manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); | 759 | manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); |
737 | duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); | 760 | duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); |
738 | if (manu && duty) | 761 | if (!manu && duty) |
739 | /* speed */ | 762 | /* auto, pwm */ |
763 | data->pwm_enable[nr] = 4; | ||
764 | else if (manu && !duty) | ||
765 | /* manual, speed */ | ||
740 | data->pwm_enable[nr] = 3; | 766 | data->pwm_enable[nr] = 3; |
741 | else if (!manu && duty) | 767 | else if (!manu && !duty) |
742 | /* automatic */ | 768 | /* automatic, speed */ |
743 | data->pwm_enable[nr] = 2; | 769 | data->pwm_enable[nr] = 2; |
744 | else | 770 | else |
745 | /* manual */ | 771 | /* manual, pwm */ |
746 | data->pwm_enable[nr] = 1; | 772 | data->pwm_enable[nr] = 1; |
747 | } else { | 773 | } else { |
748 | if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) | 774 | if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) |