diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_pm.c | 26 |
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index 8ac02cdd03a1..bbab7013aed1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h @@ -56,6 +56,8 @@ void nv04_pm_clock_set(struct drm_device *, void *); int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); void nv40_pm_clocks_set(struct drm_device *, void *); +int nv40_pm_fanspeed_get(struct drm_device *); +int nv40_pm_fanspeed_set(struct drm_device *, int percent); /* nv50_pm.c */ int nv50_pm_clock_get(struct drm_device *, u32 id); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index d8831ab42bb9..06664e779792 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -292,6 +292,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->pm.temp_get = nv40_temp_get; + switch (dev_priv->chipset) { + case 0x40: + case 0x49: + engine->pm.fanspeed_get = nv40_pm_fanspeed_get; + engine->pm.fanspeed_set = nv40_pm_fanspeed_set; + break; + default: + break; + } engine->vram.init = nouveau_mem_detect; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index e676b0d53478..c969bcbab547 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -346,3 +346,29 @@ resume: kfree(info); } + +int +nv40_pm_fanspeed_get(struct drm_device *dev) +{ + u32 reg = nv_rd32(dev, 0x0010f0); + if (reg & 0x80000000) { + u32 duty = (reg & 0x7fff0000) >> 16; + u32 divs = (reg & 0x00007fff); + if (divs && divs >= duty) + return ((divs - duty) * 100) / divs; + } + + return 100; +} + +int +nv40_pm_fanspeed_set(struct drm_device *dev, int percent) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + u32 divs = pm->pwm_divisor; + u32 duty = ((100 - percent) * divs) / 100; + + nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs); + return 0; +} |