From 64f1c11a477cb76e1572ee0793234739e045b3d5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 17 Sep 2010 13:35:25 +1000 Subject: drm/nouveau: restore perflvl on resume, and restore boot perflvl on unload Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 3 ++ drivers/gpu/drm/nouveau/nouveau_pm.c | 64 ++++++++++++++++++++++++----------- drivers/gpu/drm/nouveau/nouveau_pm.h | 1 + 3 files changed, 49 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index b03bb6d..f919e41 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -31,6 +31,7 @@ #include "nouveau_hw.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" +#include "nouveau_pm.h" #include "nv50_display.h" #include "drm_pciids.h" @@ -279,6 +280,8 @@ nouveau_pci_resume(struct pci_dev *pdev) if (ret) return ret; + nouveau_pm_resume(dev); + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { ret = nouveau_mem_init_agp(dev); if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 9e8e14e..4e92d21 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -47,12 +47,38 @@ nouveau_pm_clock_set(struct drm_device *dev, u8 id, u32 khz) } static int +nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + int ret; + + if (perflvl == pm->cur) + return 0; + + if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { + ret = pm->voltage_set(dev, perflvl->voltage); + if (ret) { + NV_ERROR(dev, "voltage_set %d failed: %d\n", + perflvl->voltage, ret); + } + } + + nouveau_pm_clock_set(dev, PLL_CORE, perflvl->core); + nouveau_pm_clock_set(dev, PLL_SHADER, perflvl->shader); + nouveau_pm_clock_set(dev, PLL_MEMORY, perflvl->memory); + nouveau_pm_clock_set(dev, PLL_UNK05, perflvl->unk05); + + pm->cur = perflvl; + return 0; +} + +static int nouveau_pm_profile_set(struct drm_device *dev, const char *profile) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; struct nouveau_pm_level *perflvl = NULL; - int ret; /* safety precaution, for now */ if (nouveau_perflvl_wr != 7777) @@ -78,25 +104,8 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) return -EINVAL; } - if (perflvl == pm->cur) - return 0; - NV_INFO(dev, "setting performance level: %s\n", profile); - if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { - ret = pm->voltage_set(dev, perflvl->voltage); - if (ret) { - NV_ERROR(dev, "voltage_set %d failed: %d\n", - perflvl->voltage, ret); - } - } - - nouveau_pm_clock_set(dev, PLL_CORE, perflvl->core); - nouveau_pm_clock_set(dev, PLL_SHADER, perflvl->shader); - nouveau_pm_clock_set(dev, PLL_MEMORY, perflvl->memory); - nouveau_pm_clock_set(dev, PLL_UNK05, perflvl->unk05); - - pm->cur = perflvl; - return 0; + return nouveau_pm_perflvl_set(dev, perflvl); } static int @@ -285,6 +294,9 @@ nouveau_pm_fini(struct drm_device *dev) struct device *d = &dev->pdev->dev; int i; + if (pm->cur != &pm->boot) + nouveau_pm_perflvl_set(dev, &pm->boot); + device_remove_file(d, &dev_attr_performance_level); for (i = 0; i < pm->nr_perflvl; i++) { struct nouveau_pm_level *pl = &pm->perflvl[i]; @@ -299,3 +311,17 @@ nouveau_pm_fini(struct drm_device *dev) nouveau_volt_fini(dev); } +void +nouveau_pm_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm_level *perflvl; + + if (pm->cur == &pm->boot) + return; + + perflvl = pm->cur; + pm->cur = &pm->boot; + nouveau_pm_perflvl_set(dev, perflvl); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index 70e1862..f3de5a6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h @@ -28,6 +28,7 @@ /* nouveau_pm.c */ int nouveau_pm_init(struct drm_device *dev); void nouveau_pm_fini(struct drm_device *dev); +void nouveau_pm_resume(struct drm_device *dev); /* nouveau_volt.c */ void nouveau_volt_init(struct drm_device *); -- cgit v1.1