aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_pm.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-16 02:47:14 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:27:20 -0400
commit6f876986bedf23b40ab707543e88fae7eac27f1f (patch)
tree8b0176d16bc5ea891e1367ef9accda53a753a568 /drivers/gpu/drm/nouveau/nouveau_pm.c
parent442b626ece6fbbe7f52c03a09f85ae5755f29eab (diff)
drm/nouveau: allow static performance level setting
Guarded by a module parameter for the moment, read the code for the magic value which enables it. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_pm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 9cf5fd665b8c..9e8e14eb6df3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -28,6 +28,78 @@
28#include "nouveau_pm.h" 28#include "nouveau_pm.h"
29 29
30static int 30static int
31nouveau_pm_clock_set(struct drm_device *dev, u8 id, u32 khz)
32{
33 struct drm_nouveau_private *dev_priv = dev->dev_private;
34 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
35 void *pre_state;
36
37 if (khz == 0)
38 return 0;
39
40 pre_state = pm->clock_pre(dev, id, khz);
41 if (IS_ERR(pre_state))
42 return PTR_ERR(pre_state);
43
44 if (pre_state)
45 pm->clock_set(dev, pre_state);
46 return 0;
47}
48
49static int
50nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
51{
52 struct drm_nouveau_private *dev_priv = dev->dev_private;
53 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
54 struct nouveau_pm_level *perflvl = NULL;
55 int ret;
56
57 /* safety precaution, for now */
58 if (nouveau_perflvl_wr != 7777)
59 return -EPERM;
60
61 if (!pm->clock_set)
62 return -EINVAL;
63
64 if (!strncmp(profile, "boot", 4))
65 perflvl = &pm->boot;
66 else {
67 int pl = simple_strtol(profile, NULL, 10);
68 int i;
69
70 for (i = 0; i < pm->nr_perflvl; i++) {
71 if (pm->perflvl[i].id == pl) {
72 perflvl = &pm->perflvl[i];
73 break;
74 }
75 }
76
77 if (!perflvl)
78 return -EINVAL;
79 }
80
81 if (perflvl == pm->cur)
82 return 0;
83
84 NV_INFO(dev, "setting performance level: %s\n", profile);
85 if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) {
86 ret = pm->voltage_set(dev, perflvl->voltage);
87 if (ret) {
88 NV_ERROR(dev, "voltage_set %d failed: %d\n",
89 perflvl->voltage, ret);
90 }
91 }
92
93 nouveau_pm_clock_set(dev, PLL_CORE, perflvl->core);
94 nouveau_pm_clock_set(dev, PLL_SHADER, perflvl->shader);
95 nouveau_pm_clock_set(dev, PLL_MEMORY, perflvl->memory);
96 nouveau_pm_clock_set(dev, PLL_UNK05, perflvl->unk05);
97
98 pm->cur = perflvl;
99 return 0;
100}
101
102static int
31nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) 103nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
32{ 104{
33 struct drm_nouveau_private *dev_priv = dev->dev_private; 105 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -130,7 +202,13 @@ static ssize_t
130nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a, 202nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a,
131 const char *buf, size_t count) 203 const char *buf, size_t count)
132{ 204{
133 return -EPERM; 205 struct drm_device *dev = pci_get_drvdata(to_pci_dev(d));
206 int ret;
207
208 ret = nouveau_pm_profile_set(dev, buf);
209 if (ret)
210 return ret;
211 return strlen(buf);
134} 212}
135 213
136DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, 214DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR,
@@ -163,6 +241,15 @@ nouveau_pm_init(struct drm_device *dev)
163 NV_INFO(dev, "c: %s", info); 241 NV_INFO(dev, "c: %s", info);
164 } 242 }
165 243
244 /* switch performance levels now if requested */
245 if (nouveau_perflvl != NULL) {
246 ret = nouveau_pm_profile_set(dev, nouveau_perflvl);
247 if (ret) {
248 NV_ERROR(dev, "error setting perflvl \"%s\": %d\n",
249 nouveau_perflvl, ret);
250 }
251 }
252
166 /* initialise sysfs */ 253 /* initialise sysfs */
167 ret = device_create_file(d, &dev_attr_performance_level); 254 ret = device_create_file(d, &dev_attr_performance_level);
168 if (ret) 255 if (ret)