diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-13 00:17:09 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 15:11:08 -0400 |
commit | 7238eca4cf18a5bba8679afc8c71a274e264f82e (patch) | |
tree | 96014d6d02c4c8c6db819e36a70bbf4d8d986f78 /drivers/gpu | |
parent | 7e1ee6333c32a4b83aad430a4bcb8a7057f36194 (diff) |
drm/nouveau: expose pstate selection per-power source in sysfs
echo ac:id >> pstate # select mode when on mains power
echo dc:id >> pstate # select mode when on battery
echo id >> pstate # select mode for both
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/device/ctrl.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/class.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_sysfs.c | 38 |
3 files changed, 52 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c index 754fc1da6a0b..fb546f3a1af0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c | |||
@@ -40,15 +40,16 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd, | |||
40 | return -EINVAL; | 40 | return -EINVAL; |
41 | 41 | ||
42 | if (clk) { | 42 | if (clk) { |
43 | args->count = clk->state_nr; | 43 | args->count = clk->state_nr; |
44 | if (clk->pwrsrc) | 44 | args->ustate_ac = clk->ustate_ac; |
45 | args->ustate = clk->ustate_ac; | 45 | args->ustate_dc = clk->ustate_dc; |
46 | else | 46 | args->pwrsrc = clk->pwrsrc; |
47 | args->ustate = clk->ustate_dc; | ||
48 | args->pstate = clk->pstate; | 47 | args->pstate = clk->pstate; |
49 | } else { | 48 | } else { |
50 | args->count = 0; | 49 | args->count = 0; |
51 | args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE; | 50 | args->ustate_ac = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE; |
51 | args->ustate_dc = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE; | ||
52 | args->pwrsrc = -ENOSYS; | ||
52 | args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN; | 53 | args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN; |
53 | } | 54 | } |
54 | 55 | ||
@@ -122,11 +123,19 @@ nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd, | |||
122 | { | 123 | { |
123 | struct nouveau_clock *clk = nouveau_clock(object); | 124 | struct nouveau_clock *clk = nouveau_clock(object); |
124 | struct nv_control_pstate_user *args = data; | 125 | struct nv_control_pstate_user *args = data; |
126 | int ret = 0; | ||
125 | 127 | ||
126 | if (size < sizeof(*args) || !clk) | 128 | if (size < sizeof(*args) || !clk) |
127 | return -EINVAL; | 129 | return -EINVAL; |
128 | 130 | ||
129 | return nouveau_clock_ustate(clk, args->state, clk->pwrsrc); | 131 | if (args->pwrsrc >= 0) { |
132 | ret |= nouveau_clock_ustate(clk, args->ustate, args->pwrsrc); | ||
133 | } else { | ||
134 | ret |= nouveau_clock_ustate(clk, args->ustate, 0); | ||
135 | ret |= nouveau_clock_ustate(clk, args->ustate, 1); | ||
136 | } | ||
137 | |||
138 | return ret; | ||
130 | } | 139 | } |
131 | 140 | ||
132 | struct nouveau_oclass | 141 | struct nouveau_oclass |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index e0c812bc884f..d6fd2cbe4333 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h | |||
@@ -148,7 +148,9 @@ struct nv_perfctr_read { | |||
148 | 148 | ||
149 | struct nv_control_pstate_info { | 149 | struct nv_control_pstate_info { |
150 | u32 count; /* out: number of power states */ | 150 | u32 count; /* out: number of power states */ |
151 | s32 ustate; /* out: current target pstate index */ | 151 | s32 ustate_ac; /* out: target pstate index */ |
152 | s32 ustate_dc; /* out: target pstate index */ | ||
153 | s32 pwrsrc; /* out: current power source */ | ||
152 | u32 pstate; /* out: current pstate index */ | 154 | u32 pstate; /* out: current pstate index */ |
153 | }; | 155 | }; |
154 | 156 | ||
@@ -166,7 +168,8 @@ struct nv_control_pstate_attr { | |||
166 | }; | 168 | }; |
167 | 169 | ||
168 | struct nv_control_pstate_user { | 170 | struct nv_control_pstate_user { |
169 | s32 state; /* in: pstate identifier */ | 171 | s32 ustate; /* in: pstate identifier */ |
172 | s32 pwrsrc; /* in: target power source */ | ||
170 | }; | 173 | }; |
171 | 174 | ||
172 | /* DMA FIFO channel classes | 175 | /* DMA FIFO channel classes |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c index 75dda2b07176..ab5afc50460a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c | |||
@@ -68,7 +68,9 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b) | |||
68 | if (i < info.count) | 68 | if (i < info.count) |
69 | snappendf(buf, cnt, "%02x:", attr.state); | 69 | snappendf(buf, cnt, "%02x:", attr.state); |
70 | else | 70 | else |
71 | snappendf(buf, cnt, "--:"); | 71 | snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" : |
72 | info.pwrsrc == 1 ? "AC" : | ||
73 | "--"); | ||
72 | 74 | ||
73 | attr.index = 0; | 75 | attr.index = 0; |
74 | do { | 76 | do { |
@@ -84,9 +86,20 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b) | |||
84 | snappendf(buf, cnt, " %s", attr.unit); | 86 | snappendf(buf, cnt, " %s", attr.unit); |
85 | } while (attr.index); | 87 | } while (attr.index); |
86 | 88 | ||
87 | if ((state >= 0 && info.pstate == state) || | 89 | if (state >= 0) { |
88 | (state < 0 && info.ustate < 0)) | 90 | if (info.ustate_ac == state) |
89 | snappendf(buf, cnt, " *"); | 91 | snappendf(buf, cnt, " AC"); |
92 | if (info.ustate_dc == state) | ||
93 | snappendf(buf, cnt, " DC"); | ||
94 | if (info.pstate == state) | ||
95 | snappendf(buf, cnt, " *"); | ||
96 | } else { | ||
97 | if (info.ustate_ac < -1) | ||
98 | snappendf(buf, cnt, " AC"); | ||
99 | if (info.ustate_dc < -1) | ||
100 | snappendf(buf, cnt, " DC"); | ||
101 | } | ||
102 | |||
90 | snappendf(buf, cnt, "\n"); | 103 | snappendf(buf, cnt, "\n"); |
91 | } | 104 | } |
92 | 105 | ||
@@ -98,23 +111,32 @@ nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a, | |||
98 | const char *buf, size_t count) | 111 | const char *buf, size_t count) |
99 | { | 112 | { |
100 | struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d)); | 113 | struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d)); |
101 | struct nv_control_pstate_user args; | 114 | struct nv_control_pstate_user args = { .pwrsrc = -EINVAL }; |
102 | long value, ret; | 115 | long value, ret; |
103 | char *tmp; | 116 | char *tmp; |
104 | 117 | ||
105 | if ((tmp = strchr(buf, '\n'))) | 118 | if ((tmp = strchr(buf, '\n'))) |
106 | *tmp = '\0'; | 119 | *tmp = '\0'; |
107 | 120 | ||
121 | if (!strncasecmp(buf, "dc:", 3)) { | ||
122 | args.pwrsrc = 0; | ||
123 | buf += 3; | ||
124 | } else | ||
125 | if (!strncasecmp(buf, "ac:", 3)) { | ||
126 | args.pwrsrc = 1; | ||
127 | buf += 3; | ||
128 | } | ||
129 | |||
108 | if (!strcasecmp(buf, "none")) | 130 | if (!strcasecmp(buf, "none")) |
109 | args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN; | 131 | args.ustate = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN; |
110 | else | 132 | else |
111 | if (!strcasecmp(buf, "auto")) | 133 | if (!strcasecmp(buf, "auto")) |
112 | args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON; | 134 | args.ustate = NV_CONTROL_PSTATE_USER_STATE_PERFMON; |
113 | else { | 135 | else { |
114 | ret = kstrtol(buf, 16, &value); | 136 | ret = kstrtol(buf, 16, &value); |
115 | if (ret) | 137 | if (ret) |
116 | return ret; | 138 | return ret; |
117 | args.state = value; | 139 | args.ustate = value; |
118 | } | 140 | } |
119 | 141 | ||
120 | ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args)); | 142 | ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args)); |