int nouveau_therm_create_(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, int length, void **pobject) { struct nouveau_therm_priv *priv; int ret; ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PTHERM", "therm", length, pobject); priv = *pobject; if (ret) return ret; nouveau_alarm_init(&priv->alarm, nouveau_therm_alarm); spin_lock_init(&priv->lock); spin_lock_init(&priv->sensor.alarm_program_lock); priv->base.fan_get = nouveau_therm_fan_user_get; priv->base.fan_set = nouveau_therm_fan_user_set; priv->base.fan_sense = nouveau_therm_fan_sense; priv->base.attr_get = nouveau_therm_attr_get; priv->base.attr_set = nouveau_therm_attr_set; priv->mode = priv->suspend = -1; /* undefined */ return 0; }
int nouveau_therm_fan_ctor(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_gpio *gpio = nouveau_gpio(therm); struct nouveau_bios *bios = nouveau_bios(therm); struct dcb_gpio_func func; int ret; /* attempt to locate a drivable fan, and determine control method */ ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); if (ret == 0) { /* FIXME: is this really the place to perform such checks ? */ if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) { nv_debug(therm, "GPIO_FAN is in input mode\n"); ret = -EINVAL; } else { ret = nouveau_fanpwm_create(therm, &func); if (ret != 0) ret = nouveau_fantog_create(therm, &func); } } /* no controllable fan found, create a dummy fan module */ if (ret != 0) { ret = nouveau_fannil_create(therm); if (ret) return ret; } nv_info(therm, "FAN control: %s\n", priv->fan->type); /* read the current speed, it is useful when resuming */ priv->fan->percent = nouveau_therm_fan_get(therm); /* attempt to detect a tachometer connection */ ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); if (ret) priv->fan->tach.func = DCB_GPIO_UNUSED; /* initialise fan bump/slow update handling */ priv->fan->parent = therm; nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm); spin_lock_init(&priv->fan->lock); /* other random init... */ nouveau_therm_fan_set_defaults(therm); nvbios_perf_fan_parse(bios, &priv->fan->perf); if (!nvbios_fan_parse(bios, &priv->fan->bios)) { nv_debug(therm, "parsing the fan table failed\n"); if (nvbios_therm_fan_parse(bios, &priv->fan->bios)) nv_error(therm, "parsing both fan tables failed\n"); } nouveau_therm_fan_safety_checks(therm); return 0; }
int nouveau_therm_sensor_ctor(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_bios *bios = nouveau_bios(therm); nouveau_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback); nouveau_therm_temp_set_defaults(therm); if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, &priv->bios_sensor)) nv_error(therm, "nvbios_therm_sensor_parse failed\n"); nouveau_therm_temp_safety_checks(therm); return 0; }