aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
diff options
context:
space:
mode:
authorEric Huang <JinHuiEric.Huang@amd.com>2015-12-11 16:24:34 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-02-10 14:16:59 -0500
commitf3898ea12fc1f18a4fa9034b169076e8e72d122a (patch)
treeadc3c4774b449fa8d6ff7f6b5cdedc436ea8b412 /drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
parentc7e6be2303d0b6ee983eb72fee457967b85c91a6 (diff)
drm/amd/powerplay: add some sysfs interfaces for powerplay.
The new sysfs interfaces: pp_num_states: Read-only, return the number of all pp states, 0 if powerplay is not available. pp_cur_state: Read-only, return the index number of current pp state. pp_force_state: Read-write, to write a power state index will switch to selected state forcedly and enable forced state mode, disable forced state mode. such as "echo >...". pp_table: Read-write, binary output, to be used to read or write the dpm table, the maximum file size is 4KB of page size. pp_dpm_sclk: Read-write, reading will return a dpm levels list, to write an index number will force powerplay to set the corresponding dpm level. pp_dpm_mclk: same as sclk. pp_dpm_pcie: same as sclk. And add new setting "manual" to the existing interface power_dpm_force_performance_level. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c336
1 files changed, 335 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index a0da563c8c82..d77b2bdbe800 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -119,7 +119,9 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
119 level = amdgpu_dpm_get_performance_level(adev); 119 level = amdgpu_dpm_get_performance_level(adev);
120 return snprintf(buf, PAGE_SIZE, "%s\n", 120 return snprintf(buf, PAGE_SIZE, "%s\n",
121 (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : 121 (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" :
122 (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); 122 (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" :
123 (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" :
124 (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : "unknown");
123 } else { 125 } else {
124 enum amdgpu_dpm_forced_level level; 126 enum amdgpu_dpm_forced_level level;
125 127
@@ -146,6 +148,8 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
146 level = AMDGPU_DPM_FORCED_LEVEL_HIGH; 148 level = AMDGPU_DPM_FORCED_LEVEL_HIGH;
147 } else if (strncmp("auto", buf, strlen("auto")) == 0) { 149 } else if (strncmp("auto", buf, strlen("auto")) == 0) {
148 level = AMDGPU_DPM_FORCED_LEVEL_AUTO; 150 level = AMDGPU_DPM_FORCED_LEVEL_AUTO;
151 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
152 level = AMDGPU_DPM_FORCED_LEVEL_MANUAL;
149 } else { 153 } else {
150 count = -EINVAL; 154 count = -EINVAL;
151 goto fail; 155 goto fail;
@@ -172,10 +176,293 @@ fail:
172 return count; 176 return count;
173} 177}
174 178
179static ssize_t amdgpu_get_pp_num_states(struct device *dev,
180 struct device_attribute *attr,
181 char *buf)
182{
183 struct drm_device *ddev = dev_get_drvdata(dev);
184 struct amdgpu_device *adev = ddev->dev_private;
185 struct pp_states_info data;
186 int i, buf_len;
187
188 if (adev->pp_enabled)
189 amdgpu_dpm_get_pp_num_states(adev, &data);
190
191 buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums);
192 for (i = 0; i < data.nums; i++)
193 buf_len += snprintf(buf + buf_len, PAGE_SIZE, "%d %s\n", i,
194 (data.states[i] == POWER_STATE_TYPE_INTERNAL_BOOT) ? "boot" :
195 (data.states[i] == POWER_STATE_TYPE_BATTERY) ? "battery" :
196 (data.states[i] == POWER_STATE_TYPE_BALANCED) ? "balanced" :
197 (data.states[i] == POWER_STATE_TYPE_PERFORMANCE) ? "performance" : "default");
198
199 return buf_len;
200}
201
202static ssize_t amdgpu_get_pp_cur_state(struct device *dev,
203 struct device_attribute *attr,
204 char *buf)
205{
206 struct drm_device *ddev = dev_get_drvdata(dev);
207 struct amdgpu_device *adev = ddev->dev_private;
208 struct pp_states_info data;
209 enum amd_pm_state_type pm = 0;
210 int i = 0;
211
212 if (adev->pp_enabled) {
213
214 pm = amdgpu_dpm_get_current_power_state(adev);
215 amdgpu_dpm_get_pp_num_states(adev, &data);
216
217 for (i = 0; i < data.nums; i++) {
218 if (pm == data.states[i])
219 break;
220 }
221
222 if (i == data.nums)
223 i = -EINVAL;
224 }
225
226 return snprintf(buf, PAGE_SIZE, "%d\n", i);
227}
228
229static ssize_t amdgpu_get_pp_force_state(struct device *dev,
230 struct device_attribute *attr,
231 char *buf)
232{
233 struct drm_device *ddev = dev_get_drvdata(dev);
234 struct amdgpu_device *adev = ddev->dev_private;
235 struct pp_states_info data;
236 enum amd_pm_state_type pm = 0;
237 int i;
238
239 if (adev->pp_force_state_enabled && adev->pp_enabled) {
240 pm = amdgpu_dpm_get_current_power_state(adev);
241 amdgpu_dpm_get_pp_num_states(adev, &data);
242
243 for (i = 0; i < data.nums; i++) {
244 if (pm == data.states[i])
245 break;
246 }
247
248 if (i == data.nums)
249 i = -EINVAL;
250
251 return snprintf(buf, PAGE_SIZE, "%d\n", i);
252
253 } else
254 return snprintf(buf, PAGE_SIZE, "\n");
255}
256
257static ssize_t amdgpu_set_pp_force_state(struct device *dev,
258 struct device_attribute *attr,
259 const char *buf,
260 size_t count)
261{
262 struct drm_device *ddev = dev_get_drvdata(dev);
263 struct amdgpu_device *adev = ddev->dev_private;
264 enum amd_pm_state_type state = 0;
265 long idx;
266 int ret;
267
268 if (strlen(buf) == 1)
269 adev->pp_force_state_enabled = false;
270 else {
271 ret = kstrtol(buf, 0, &idx);
272
273 if (ret) {
274 count = -EINVAL;
275 goto fail;
276 }
277
278 if (adev->pp_enabled) {
279 struct pp_states_info data;
280 amdgpu_dpm_get_pp_num_states(adev, &data);
281 state = data.states[idx];
282 /* only set user selected power states */
283 if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
284 state != POWER_STATE_TYPE_DEFAULT) {
285 amdgpu_dpm_dispatch_task(adev,
286 AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
287 adev->pp_force_state_enabled = true;
288 }
289 }
290 }
291fail:
292 return count;
293}
294
295static ssize_t amdgpu_get_pp_table(struct device *dev,
296 struct device_attribute *attr,
297 char *buf)
298{
299 struct drm_device *ddev = dev_get_drvdata(dev);
300 struct amdgpu_device *adev = ddev->dev_private;
301 char *table = NULL;
302 int size, i;
303
304 if (adev->pp_enabled)
305 size = amdgpu_dpm_get_pp_table(adev, &table);
306 else
307 return 0;
308
309 if (size >= PAGE_SIZE)
310 size = PAGE_SIZE - 1;
311
312 for (i = 0; i < size; i++) {
313 sprintf(buf + i, "%02x", table[i]);
314 }
315 sprintf(buf + i, "\n");
316
317 return size;
318}
319
320static ssize_t amdgpu_set_pp_table(struct device *dev,
321 struct device_attribute *attr,
322 const char *buf,
323 size_t count)
324{
325 struct drm_device *ddev = dev_get_drvdata(dev);
326 struct amdgpu_device *adev = ddev->dev_private;
327
328 if (adev->pp_enabled)
329 amdgpu_dpm_set_pp_table(adev, buf, count);
330
331 return count;
332}
333
334static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
335 struct device_attribute *attr,
336 char *buf)
337{
338 struct drm_device *ddev = dev_get_drvdata(dev);
339 struct amdgpu_device *adev = ddev->dev_private;
340 ssize_t size = 0;
341
342 if (adev->pp_enabled)
343 size = amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf);
344
345 return size;
346}
347
348static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
349 struct device_attribute *attr,
350 const char *buf,
351 size_t count)
352{
353 struct drm_device *ddev = dev_get_drvdata(dev);
354 struct amdgpu_device *adev = ddev->dev_private;
355 int ret;
356 long level;
357
358 ret = kstrtol(buf, 0, &level);
359
360 if (ret) {
361 count = -EINVAL;
362 goto fail;
363 }
364
365 if (adev->pp_enabled)
366 amdgpu_dpm_force_clock_level(adev, PP_SCLK, level);
367fail:
368 return count;
369}
370
371static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev,
372 struct device_attribute *attr,
373 char *buf)
374{
375 struct drm_device *ddev = dev_get_drvdata(dev);
376 struct amdgpu_device *adev = ddev->dev_private;
377 ssize_t size = 0;
378
379 if (adev->pp_enabled)
380 size = amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf);
381
382 return size;
383}
384
385static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
386 struct device_attribute *attr,
387 const char *buf,
388 size_t count)
389{
390 struct drm_device *ddev = dev_get_drvdata(dev);
391 struct amdgpu_device *adev = ddev->dev_private;
392 int ret;
393 long level;
394
395 ret = kstrtol(buf, 0, &level);
396
397 if (ret) {
398 count = -EINVAL;
399 goto fail;
400 }
401
402 if (adev->pp_enabled)
403 amdgpu_dpm_force_clock_level(adev, PP_MCLK, level);
404fail:
405 return count;
406}
407
408static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
409 struct device_attribute *attr,
410 char *buf)
411{
412 struct drm_device *ddev = dev_get_drvdata(dev);
413 struct amdgpu_device *adev = ddev->dev_private;
414 ssize_t size = 0;
415
416 if (adev->pp_enabled)
417 size = amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf);
418
419 return size;
420}
421
422static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
423 struct device_attribute *attr,
424 const char *buf,
425 size_t count)
426{
427 struct drm_device *ddev = dev_get_drvdata(dev);
428 struct amdgpu_device *adev = ddev->dev_private;
429 int ret;
430 long level;
431
432 ret = kstrtol(buf, 0, &level);
433
434 if (ret) {
435 count = -EINVAL;
436 goto fail;
437 }
438
439 if (adev->pp_enabled)
440 amdgpu_dpm_force_clock_level(adev, PP_PCIE, level);
441fail:
442 return count;
443}
444
175static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); 445static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
176static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, 446static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
177 amdgpu_get_dpm_forced_performance_level, 447 amdgpu_get_dpm_forced_performance_level,
178 amdgpu_set_dpm_forced_performance_level); 448 amdgpu_set_dpm_forced_performance_level);
449static DEVICE_ATTR(pp_num_states, S_IRUGO, amdgpu_get_pp_num_states, NULL);
450static DEVICE_ATTR(pp_cur_state, S_IRUGO, amdgpu_get_pp_cur_state, NULL);
451static DEVICE_ATTR(pp_force_state, S_IRUGO | S_IWUSR,
452 amdgpu_get_pp_force_state,
453 amdgpu_set_pp_force_state);
454static DEVICE_ATTR(pp_table, S_IRUGO | S_IWUSR,
455 amdgpu_get_pp_table,
456 amdgpu_set_pp_table);
457static DEVICE_ATTR(pp_dpm_sclk, S_IRUGO | S_IWUSR,
458 amdgpu_get_pp_dpm_sclk,
459 amdgpu_set_pp_dpm_sclk);
460static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
461 amdgpu_get_pp_dpm_mclk,
462 amdgpu_set_pp_dpm_mclk);
463static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
464 amdgpu_get_pp_dpm_pcie,
465 amdgpu_set_pp_dpm_pcie);
179 466
180static ssize_t amdgpu_hwmon_show_temp(struct device *dev, 467static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
181 struct device_attribute *attr, 468 struct device_attribute *attr,
@@ -765,6 +1052,44 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
765 DRM_ERROR("failed to create device file for dpm state\n"); 1052 DRM_ERROR("failed to create device file for dpm state\n");
766 return ret; 1053 return ret;
767 } 1054 }
1055
1056 if (adev->pp_enabled) {
1057 ret = device_create_file(adev->dev, &dev_attr_pp_num_states);
1058 if (ret) {
1059 DRM_ERROR("failed to create device file pp_num_states\n");
1060 return ret;
1061 }
1062 ret = device_create_file(adev->dev, &dev_attr_pp_cur_state);
1063 if (ret) {
1064 DRM_ERROR("failed to create device file pp_cur_state\n");
1065 return ret;
1066 }
1067 ret = device_create_file(adev->dev, &dev_attr_pp_force_state);
1068 if (ret) {
1069 DRM_ERROR("failed to create device file pp_force_state\n");
1070 return ret;
1071 }
1072 ret = device_create_file(adev->dev, &dev_attr_pp_table);
1073 if (ret) {
1074 DRM_ERROR("failed to create device file pp_table\n");
1075 return ret;
1076 }
1077 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_sclk);
1078 if (ret) {
1079 DRM_ERROR("failed to create device file pp_dpm_sclk\n");
1080 return ret;
1081 }
1082 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_mclk);
1083 if (ret) {
1084 DRM_ERROR("failed to create device file pp_dpm_mclk\n");
1085 return ret;
1086 }
1087 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
1088 if (ret) {
1089 DRM_ERROR("failed to create device file pp_dpm_pcie\n");
1090 return ret;
1091 }
1092 }
768 ret = amdgpu_debugfs_pm_init(adev); 1093 ret = amdgpu_debugfs_pm_init(adev);
769 if (ret) { 1094 if (ret) {
770 DRM_ERROR("Failed to register debugfs file for dpm!\n"); 1095 DRM_ERROR("Failed to register debugfs file for dpm!\n");
@@ -782,6 +1107,15 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
782 hwmon_device_unregister(adev->pm.int_hwmon_dev); 1107 hwmon_device_unregister(adev->pm.int_hwmon_dev);
783 device_remove_file(adev->dev, &dev_attr_power_dpm_state); 1108 device_remove_file(adev->dev, &dev_attr_power_dpm_state);
784 device_remove_file(adev->dev, &dev_attr_power_dpm_force_performance_level); 1109 device_remove_file(adev->dev, &dev_attr_power_dpm_force_performance_level);
1110 if (adev->pp_enabled) {
1111 device_remove_file(adev->dev, &dev_attr_pp_num_states);
1112 device_remove_file(adev->dev, &dev_attr_pp_cur_state);
1113 device_remove_file(adev->dev, &dev_attr_pp_force_state);
1114 device_remove_file(adev->dev, &dev_attr_pp_table);
1115 device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
1116 device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
1117 device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
1118 }
785} 1119}
786 1120
787void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) 1121void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)