--- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -46,6 +46,14 @@ MODULE_PARM_DESC(perflvl_wr, "Allow perf static int nouveau_perflvl_wr; module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); +MODULE_PARM_DESC(therm_fan_mode, "Allow thermal fan mode changes (warning: dangerous!)"); +static int nouveau_therm_fan_mode; +module_param_named(therm_fan_mode, nouveau_therm_fan_mode, int, 0400); + +MODULE_PARM_DESC(therm_fan_duty, "Allow thermal fan speed changes (warning: dangerous!)"); +static int nouveau_therm_fan_duty; +module_param_named(therm_fan_duty, nouveau_therm_fan_duty, int, 0400); + static int nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, struct nouveau_pm_level *a, struct nouveau_pm_level *b) @@ -1032,6 +1040,7 @@ nouveau_pm_init(struct drm_device *dev) { struct nouveau_device *device = nouveau_dev(dev); struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_therm *therm = nouveau_therm(drm->device); struct nouveau_pm *pm; char info[256]; int ret, i; @@ -1129,6 +1138,43 @@ nouveau_pm_init(struct drm_device *dev) register_acpi_notifier(&pm->acpi_nb); #endif + if (nouveau_therm_fan_mode) { + if (nouveau_perflvl_wr != 7777) + return -EPERM; + + if ((nouveau_therm_fan_mode == NOUVEAU_THERM_CTRL_AUTO && + nouveau_therm_fan_duty > 0) || + nouveau_therm_fan_mode > NOUVEAU_THERM_CTRL_AUTO || + nouveau_therm_fan_mode < NOUVEAU_THERM_CTRL_NONE || + nouveau_therm_fan_duty > 100 || + nouveau_therm_fan_duty < 0 || + (nouveau_therm_fan_mode == NOUVEAU_THERM_CTRL_MANUAL && + nouveau_therm_fan_duty == 0)) + return -EINVAL; + + switch(nouveau_therm_fan_mode) { + case NOUVEAU_THERM_CTRL_AUTO: + ret = therm->attr_set(therm, + NOUVEAU_THERM_ATTR_FAN_MODE, + NOUVEAU_THERM_CTRL_AUTO); + if (ret) + return ret; + break; + + case NOUVEAU_THERM_CTRL_MANUAL: + ret = therm->attr_set(therm, + NOUVEAU_THERM_ATTR_FAN_MODE, + NOUVEAU_THERM_CTRL_MANUAL); + if (ret) + return ret; + + ret = therm->fan_set(therm, nouveau_therm_fan_duty); + + if (ret) + return ret; + default: break; + } + } return 0; }