diff options
author | Martin Peres <martin.peres@labri.fr> | 2013-02-23 17:15:18 +0100 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-04-26 15:37:36 +1000 |
commit | ba366c25bc0b2a6f5e4d3fab07851e6f39b883be (patch) | |
tree | fb2e329376ed5544edb889db0e1c70559fc12bb0 /drivers/gpu/drm/nouveau | |
parent | 2f4573679a8159e0c80a5d4f812b778aef9ceb14 (diff) |
drm/nv50/therm: implement temperature reading
Signed-off-by: Martin Peres <martin.peres@labri.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index 37da24a5418b..8cf7597a2182 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -118,10 +118,36 @@ nv50_fan_pwm_clock(struct nouveau_therm *therm) return pwm_clock; } -int +static void +nv50_sensor_setup(struct nouveau_therm *therm) +{ + nv_mask(therm, 0x20010, 0x40000000, 0x0); + mdelay(20); /* wait for the temperature to stabilize */ +} + +static int nv50_temp_get(struct nouveau_therm *therm) { - return nv_rd32(therm, 0x20400); + struct nouveau_therm_priv *priv = (void *)therm; + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + int core_temp; + + core_temp = nv_rd32(therm, 0x20014) & 0x3fff; + + /* if the slope or the offset is unset, do no use the sensor */ + if (!sensor->slope_div || !sensor->slope_mult || + !sensor->offset_num || !sensor->offset_den) + return -ENODEV; + + core_temp = core_temp * sensor->slope_mult / sensor->slope_div; + core_temp = core_temp + sensor->offset_num / sensor->offset_den; + core_temp = core_temp + sensor->offset_constant - 8; + + /* reserve negative temperatures for errors */ + if (core_temp < 0) + core_temp = 0; + + return core_temp; } static int @@ -149,13 +175,23 @@ nv50_therm_ctor(struct nouveau_object *parent, return nouveau_therm_preinit(&priv->base.base); } +static int +nv50_therm_init(struct nouveau_object *object) +{ + struct nouveau_therm *therm = (void *)object; + + nv50_sensor_setup(therm); + + return _nouveau_therm_init(object); +} + struct nouveau_oclass nv50_therm_oclass = { .handle = NV_SUBDEV(THERM, 0x50), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_therm_ctor, .dtor = _nouveau_therm_dtor, - .init = _nouveau_therm_init, + .init = nv50_therm_init, .fini = _nouveau_therm_fini, }, }; |