diff options
author | Rex Zhu <Rex.Zhu@amd.com> | 2018-01-16 05:35:15 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-02-19 14:18:17 -0500 |
commit | e3933f26b657c341055443103bad331f4537b113 (patch) | |
tree | c846b3c17e07d21987b9d397590d413f4db34173 /drivers/gpu/drm | |
parent | 897e1bbeec6bfb52dc075f9100b2a6f209d16583 (diff) |
drm/amd/pp: Add edit/commit/show OD clock/voltage support in sysfs
when cat pp_od_clk_voltage it show
OD_SCLK:
0: 300Mhz 800 mV
1: 466Mhz 818 mV
2: 751Mhz 824 mV
3: 1019Mhz 987 mV
4: 1074Mhz 1037 mV
5: 1126Mhz 1087 mV
6: 1169Mhz 1137 mV
7: 1206Mhz 1150 mV
OD_MCLK:
0: 300Mhz 800 mV
1: 1650Mhz 1000 mV
echo "s/m level clock voltage" to change
sclk/mclk's clock and voltage
echo "r" to restore default value.
echo "c" to commit the user setting.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 98 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 19 |
4 files changed, 121 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 986f1d568758..4b5755e6e89d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | |||
@@ -374,6 +374,10 @@ enum amdgpu_pcie_gen { | |||
374 | ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ | 374 | ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ |
375 | (adev)->powerplay.pp_handle, parameter, size)) | 375 | (adev)->powerplay.pp_handle, parameter, size)) |
376 | 376 | ||
377 | #define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ | ||
378 | ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ | ||
379 | (adev)->powerplay.pp_handle, type, parameter, size)) | ||
380 | |||
377 | struct amdgpu_dpm { | 381 | struct amdgpu_dpm { |
378 | struct amdgpu_ps *ps; | 382 | struct amdgpu_ps *ps; |
379 | /* number of valid power states */ | 383 | /* number of valid power states */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index ed9012a903b0..fda858ec3cad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
@@ -360,6 +360,90 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, | |||
360 | return count; | 360 | return count; |
361 | } | 361 | } |
362 | 362 | ||
363 | static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, | ||
364 | struct device_attribute *attr, | ||
365 | const char *buf, | ||
366 | size_t count) | ||
367 | { | ||
368 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
369 | struct amdgpu_device *adev = ddev->dev_private; | ||
370 | int ret; | ||
371 | uint32_t parameter_size = 0; | ||
372 | long parameter[64]; | ||
373 | char buf_cpy[128]; | ||
374 | char *tmp_str; | ||
375 | char *sub_str; | ||
376 | const char delimiter[3] = {' ', '\n', '\0'}; | ||
377 | uint32_t type; | ||
378 | |||
379 | if (count > 127) | ||
380 | return -EINVAL; | ||
381 | |||
382 | if (*buf == 's') | ||
383 | type = PP_OD_EDIT_SCLK_VDDC_TABLE; | ||
384 | else if (*buf == 'm') | ||
385 | type = PP_OD_EDIT_MCLK_VDDC_TABLE; | ||
386 | else if(*buf == 'r') | ||
387 | type = PP_OD_RESTORE_DEFAULT_TABLE; | ||
388 | else if (*buf == 'c') | ||
389 | type = PP_OD_COMMIT_DPM_TABLE; | ||
390 | else | ||
391 | return -EINVAL; | ||
392 | |||
393 | memcpy(buf_cpy, buf, count+1); | ||
394 | |||
395 | tmp_str = buf_cpy; | ||
396 | |||
397 | while (isspace(*++tmp_str)); | ||
398 | |||
399 | while (tmp_str[0]) { | ||
400 | sub_str = strsep(&tmp_str, delimiter); | ||
401 | ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); | ||
402 | if (ret) | ||
403 | return -EINVAL; | ||
404 | parameter_size++; | ||
405 | |||
406 | while (isspace(*tmp_str)) | ||
407 | tmp_str++; | ||
408 | } | ||
409 | |||
410 | if (adev->powerplay.pp_funcs->odn_edit_dpm_table) | ||
411 | ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, | ||
412 | parameter, parameter_size); | ||
413 | |||
414 | if (ret) | ||
415 | return -EINVAL; | ||
416 | |||
417 | if (type == PP_OD_COMMIT_DPM_TABLE) { | ||
418 | if (adev->powerplay.pp_funcs->dispatch_tasks) { | ||
419 | amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); | ||
420 | return count; | ||
421 | } else { | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | return count; | ||
427 | } | ||
428 | |||
429 | static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, | ||
430 | struct device_attribute *attr, | ||
431 | char *buf) | ||
432 | { | ||
433 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
434 | struct amdgpu_device *adev = ddev->dev_private; | ||
435 | uint32_t size = 0; | ||
436 | |||
437 | if (adev->powerplay.pp_funcs->print_clock_levels) { | ||
438 | size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); | ||
439 | size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); | ||
440 | return size; | ||
441 | } else { | ||
442 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
443 | } | ||
444 | |||
445 | } | ||
446 | |||
363 | static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, | 447 | static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, |
364 | struct device_attribute *attr, | 448 | struct device_attribute *attr, |
365 | char *buf) | 449 | char *buf) |
@@ -842,6 +926,10 @@ static DEVICE_ATTR(pp_compute_power_profile, S_IRUGO | S_IWUSR, | |||
842 | static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR, | 926 | static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR, |
843 | amdgpu_get_pp_power_profile_mode, | 927 | amdgpu_get_pp_power_profile_mode, |
844 | amdgpu_set_pp_power_profile_mode); | 928 | amdgpu_set_pp_power_profile_mode); |
929 | static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, | ||
930 | amdgpu_get_pp_od_clk_voltage, | ||
931 | amdgpu_set_pp_od_clk_voltage); | ||
932 | |||
845 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, | 933 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, |
846 | struct device_attribute *attr, | 934 | struct device_attribute *attr, |
847 | char *buf) | 935 | char *buf) |
@@ -1481,7 +1569,13 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) | |||
1481 | "pp_power_profile_mode\n"); | 1569 | "pp_power_profile_mode\n"); |
1482 | return ret; | 1570 | return ret; |
1483 | } | 1571 | } |
1484 | 1572 | ret = device_create_file(adev->dev, | |
1573 | &dev_attr_pp_od_clk_voltage); | ||
1574 | if (ret) { | ||
1575 | DRM_ERROR("failed to create device file " | ||
1576 | "pp_od_clk_voltage\n"); | ||
1577 | return ret; | ||
1578 | } | ||
1485 | ret = amdgpu_debugfs_pm_init(adev); | 1579 | ret = amdgpu_debugfs_pm_init(adev); |
1486 | if (ret) { | 1580 | if (ret) { |
1487 | DRM_ERROR("Failed to register debugfs file for dpm!\n"); | 1581 | DRM_ERROR("Failed to register debugfs file for dpm!\n"); |
@@ -1519,6 +1613,8 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) | |||
1519 | &dev_attr_pp_compute_power_profile); | 1613 | &dev_attr_pp_compute_power_profile); |
1520 | device_remove_file(adev->dev, | 1614 | device_remove_file(adev->dev, |
1521 | &dev_attr_pp_power_profile_mode); | 1615 | &dev_attr_pp_power_profile_mode); |
1616 | device_remove_file(adev->dev, | ||
1617 | &dev_attr_pp_od_clk_voltage); | ||
1522 | } | 1618 | } |
1523 | 1619 | ||
1524 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 1620 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) |
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index e35dcd011dcc..b9aa9f416389 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h | |||
@@ -310,6 +310,7 @@ struct amd_pm_funcs { | |||
310 | struct amd_pp_simple_clock_info *clocks); | 310 | struct amd_pp_simple_clock_info *clocks); |
311 | int (*get_power_profile_mode)(void *handle, char *buf); | 311 | int (*get_power_profile_mode)(void *handle, char *buf); |
312 | int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); | 312 | int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); |
313 | int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); | ||
313 | }; | 314 | }; |
314 | 315 | ||
315 | #endif | 316 | #endif |
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index d9cb424ff7e9..854c43c94714 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
@@ -1122,6 +1122,24 @@ static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) | |||
1122 | return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); | 1122 | return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) | ||
1126 | { | ||
1127 | struct pp_hwmgr *hwmgr; | ||
1128 | struct pp_instance *pp_handle = (struct pp_instance *)handle; | ||
1129 | |||
1130 | if (pp_check(pp_handle)) | ||
1131 | return -EINVAL; | ||
1132 | |||
1133 | hwmgr = pp_handle->hwmgr; | ||
1134 | |||
1135 | if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { | ||
1136 | pr_info("%s was not implemented.\n", __func__); | ||
1137 | return -EINVAL; | ||
1138 | } | ||
1139 | |||
1140 | return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size); | ||
1141 | } | ||
1142 | |||
1125 | static int pp_dpm_set_power_profile_state(void *handle, | 1143 | static int pp_dpm_set_power_profile_state(void *handle, |
1126 | struct amd_pp_profile *request) | 1144 | struct amd_pp_profile *request) |
1127 | { | 1145 | { |
@@ -1507,6 +1525,7 @@ const struct amd_pm_funcs pp_dpm_funcs = { | |||
1507 | .notify_smu_memory_info = pp_dpm_notify_smu_memory_info, | 1525 | .notify_smu_memory_info = pp_dpm_notify_smu_memory_info, |
1508 | .get_power_profile_mode = pp_get_power_profile_mode, | 1526 | .get_power_profile_mode = pp_get_power_profile_mode, |
1509 | .set_power_profile_mode = pp_set_power_profile_mode, | 1527 | .set_power_profile_mode = pp_set_power_profile_mode, |
1528 | .odn_edit_dpm_table = pp_odn_edit_dpm_table, | ||
1510 | /* export to DC */ | 1529 | /* export to DC */ |
1511 | .get_sclk = pp_dpm_get_sclk, | 1530 | .get_sclk = pp_dpm_get_sclk, |
1512 | .get_mclk = pp_dpm_get_mclk, | 1531 | .get_mclk = pp_dpm_get_mclk, |