forked from Minki/linux
i8k: Add support for configurable maximum fan speed value
Newer Dell systems provide more granular fan speed selection. Add support for it. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Cc: Andreas Mohr <andi@lisas.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b12ce5f24d
commit
81474fc2fa
@ -65,6 +65,8 @@ static char bios_version[4];
|
|||||||
static struct device *i8k_hwmon_dev;
|
static struct device *i8k_hwmon_dev;
|
||||||
static u32 i8k_hwmon_flags;
|
static u32 i8k_hwmon_flags;
|
||||||
static int i8k_fan_mult;
|
static int i8k_fan_mult;
|
||||||
|
static int i8k_pwm_mult;
|
||||||
|
static int i8k_fan_max = I8K_FAN_HIGH;
|
||||||
|
|
||||||
#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
|
#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
|
||||||
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
|
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
|
||||||
@ -97,6 +99,10 @@ static int fan_mult = I8K_FAN_MULT;
|
|||||||
module_param(fan_mult, int, 0);
|
module_param(fan_mult, int, 0);
|
||||||
MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
|
MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
|
||||||
|
|
||||||
|
static int fan_max = I8K_FAN_HIGH;
|
||||||
|
module_param(fan_max, int, 0);
|
||||||
|
MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed");
|
||||||
|
|
||||||
static int i8k_open_fs(struct inode *inode, struct file *file);
|
static int i8k_open_fs(struct inode *inode, struct file *file);
|
||||||
static long i8k_ioctl(struct file *, unsigned int, unsigned long);
|
static long i8k_ioctl(struct file *, unsigned int, unsigned long);
|
||||||
|
|
||||||
@ -274,7 +280,7 @@ static int i8k_set_fan(int fan, int speed)
|
|||||||
{
|
{
|
||||||
struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
|
struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
|
||||||
|
|
||||||
speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
|
speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
|
||||||
regs.ebx = (fan & 0xff) | (speed << 8);
|
regs.ebx = (fan & 0xff) | (speed << 8);
|
||||||
|
|
||||||
return i8k_smm(®s) ? : i8k_get_fan_status(fan);
|
return i8k_smm(®s) ? : i8k_get_fan_status(fan);
|
||||||
@ -519,7 +525,7 @@ static ssize_t i8k_hwmon_show_pwm(struct device *dev,
|
|||||||
status = i8k_get_fan_status(index);
|
status = i8k_get_fan_status(index);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
return sprintf(buf, "%d\n", clamp_val(status * 128, 0, 255));
|
return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t i8k_hwmon_set_pwm(struct device *dev,
|
static ssize_t i8k_hwmon_set_pwm(struct device *dev,
|
||||||
@ -533,7 +539,7 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev,
|
|||||||
err = kstrtoul(buf, 10, &val);
|
err = kstrtoul(buf, 10, &val);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
val = clamp_val(DIV_ROUND_CLOSEST(val, 128), 0, 2);
|
val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
|
||||||
|
|
||||||
mutex_lock(&i8k_mutex);
|
mutex_lock(&i8k_mutex);
|
||||||
err = i8k_set_fan(index, val);
|
err = i8k_set_fan(index, val);
|
||||||
@ -636,6 +642,27 @@ static int __init i8k_init_hwmon(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct i8k_config_data {
|
||||||
|
int fan_mult;
|
||||||
|
int fan_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum i8k_configs {
|
||||||
|
DELL_STUDIO,
|
||||||
|
DELL_XPS_M140,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct i8k_config_data i8k_config_data[] = {
|
||||||
|
[DELL_STUDIO] = {
|
||||||
|
.fan_mult = 1,
|
||||||
|
.fan_max = I8K_FAN_HIGH,
|
||||||
|
},
|
||||||
|
[DELL_XPS_M140] = {
|
||||||
|
.fan_mult = 1,
|
||||||
|
.fan_max = I8K_FAN_HIGH,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct dmi_system_id i8k_dmi_table[] __initdata = {
|
static struct dmi_system_id i8k_dmi_table[] __initdata = {
|
||||||
{
|
{
|
||||||
.ident = "Dell Inspiron",
|
.ident = "Dell Inspiron",
|
||||||
@ -706,7 +733,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
|
|||||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
|
||||||
},
|
},
|
||||||
.driver_data = (void *)1, /* fan multiplier override */
|
.driver_data = (void *)&i8k_config_data[DELL_STUDIO],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.ident = "Dell XPS M140",
|
.ident = "Dell XPS M140",
|
||||||
@ -714,7 +741,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
|
|||||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
|
||||||
},
|
},
|
||||||
.driver_data = (void *)1, /* fan multiplier override */
|
.driver_data = (void *)&i8k_config_data[DELL_XPS_M140],
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
@ -754,9 +781,17 @@ static int __init i8k_probe(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
i8k_fan_mult = fan_mult;
|
i8k_fan_mult = fan_mult;
|
||||||
|
i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */
|
||||||
id = dmi_first_match(i8k_dmi_table);
|
id = dmi_first_match(i8k_dmi_table);
|
||||||
if (id && fan_mult == I8K_FAN_MULT && id->driver_data)
|
if (id && id->driver_data) {
|
||||||
i8k_fan_mult = (unsigned long)id->driver_data;
|
const struct i8k_config_data *conf = id->driver_data;
|
||||||
|
|
||||||
|
if (fan_mult == I8K_FAN_MULT && conf->fan_mult)
|
||||||
|
i8k_fan_mult = conf->fan_mult;
|
||||||
|
if (fan_max == I8K_FAN_HIGH && conf->fan_max)
|
||||||
|
i8k_fan_max = conf->fan_max;
|
||||||
|
}
|
||||||
|
i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user