diff options
author | Eric Huang <JinHuiEric.Huang@amd.com> | 2016-05-12 14:51:21 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-07-07 14:50:40 -0400 |
commit | 428bafa86c99f1888254aec63bbcb1a2001e8770 (patch) | |
tree | 0f661e0245d686d184a8d38c5b750e7ef0734187 | |
parent | b2ea0dcd2790949802230bada9416d2362280138 (diff) |
drm/amdgpu: add powerplay sclk OD support through sysfs (v2)
Add a new sysfs entry pp_sclk_od to support sclk overdrive(OD) overclocking,
the entry is read/write, the value of input/output is an integer which is the
over percentage of the highest sclk.
v2: drop extra semicolon
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>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 |
5 files changed, 103 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ac8e02f9105a..611d33d855ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -2342,6 +2342,12 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) | |||
2342 | #define amdgpu_dpm_force_clock_level(adev, type, level) \ | 2342 | #define amdgpu_dpm_force_clock_level(adev, type, level) \ |
2343 | (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level) | 2343 | (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level) |
2344 | 2344 | ||
2345 | #define amdgpu_dpm_get_sclk_od(adev) \ | ||
2346 | (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle) | ||
2347 | |||
2348 | #define amdgpu_dpm_set_sclk_od(adev, value) \ | ||
2349 | (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) | ||
2350 | |||
2345 | #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ | 2351 | #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ |
2346 | (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) | 2352 | (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) |
2347 | 2353 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 0e13d80d2a95..191c28ff0d93 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
@@ -469,6 +469,46 @@ fail: | |||
469 | return count; | 469 | return count; |
470 | } | 470 | } |
471 | 471 | ||
472 | static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, | ||
473 | struct device_attribute *attr, | ||
474 | char *buf) | ||
475 | { | ||
476 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
477 | struct amdgpu_device *adev = ddev->dev_private; | ||
478 | uint32_t value = 0; | ||
479 | |||
480 | if (adev->pp_enabled) | ||
481 | value = amdgpu_dpm_get_sclk_od(adev); | ||
482 | |||
483 | return snprintf(buf, PAGE_SIZE, "%d\n", value); | ||
484 | } | ||
485 | |||
486 | static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, | ||
487 | struct device_attribute *attr, | ||
488 | const char *buf, | ||
489 | size_t count) | ||
490 | { | ||
491 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
492 | struct amdgpu_device *adev = ddev->dev_private; | ||
493 | int ret; | ||
494 | long int value; | ||
495 | |||
496 | ret = kstrtol(buf, 0, &value); | ||
497 | |||
498 | if (ret) { | ||
499 | count = -EINVAL; | ||
500 | goto fail; | ||
501 | } | ||
502 | |||
503 | if (adev->pp_enabled) | ||
504 | amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); | ||
505 | |||
506 | amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL); | ||
507 | |||
508 | fail: | ||
509 | return count; | ||
510 | } | ||
511 | |||
472 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); | 512 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); |
473 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, | 513 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, |
474 | amdgpu_get_dpm_forced_performance_level, | 514 | amdgpu_get_dpm_forced_performance_level, |
@@ -490,6 +530,9 @@ static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR, | |||
490 | static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR, | 530 | static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR, |
491 | amdgpu_get_pp_dpm_pcie, | 531 | amdgpu_get_pp_dpm_pcie, |
492 | amdgpu_set_pp_dpm_pcie); | 532 | amdgpu_set_pp_dpm_pcie); |
533 | static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR, | ||
534 | amdgpu_get_pp_sclk_od, | ||
535 | amdgpu_set_pp_sclk_od); | ||
493 | 536 | ||
494 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, | 537 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, |
495 | struct device_attribute *attr, | 538 | struct device_attribute *attr, |
@@ -1123,6 +1166,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) | |||
1123 | DRM_ERROR("failed to create device file pp_dpm_pcie\n"); | 1166 | DRM_ERROR("failed to create device file pp_dpm_pcie\n"); |
1124 | return ret; | 1167 | return ret; |
1125 | } | 1168 | } |
1169 | ret = device_create_file(adev->dev, &dev_attr_pp_sclk_od); | ||
1170 | if (ret) { | ||
1171 | DRM_ERROR("failed to create device file pp_sclk_od\n"); | ||
1172 | return ret; | ||
1173 | } | ||
1126 | } | 1174 | } |
1127 | ret = amdgpu_debugfs_pm_init(adev); | 1175 | ret = amdgpu_debugfs_pm_init(adev); |
1128 | if (ret) { | 1176 | if (ret) { |
@@ -1149,6 +1197,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) | |||
1149 | device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk); | 1197 | device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk); |
1150 | device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk); | 1198 | device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk); |
1151 | device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); | 1199 | device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); |
1200 | device_remove_file(adev->dev, &dev_attr_pp_sclk_od); | ||
1152 | } | 1201 | } |
1153 | } | 1202 | } |
1154 | 1203 | ||
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index e629f8a9fe93..8fa6f594d3ad 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
@@ -536,6 +536,10 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, | |||
536 | case AMD_PP_EVENT_COMPLETE_INIT: | 536 | case AMD_PP_EVENT_COMPLETE_INIT: |
537 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); | 537 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); |
538 | break; | 538 | break; |
539 | case AMD_PP_EVENT_READJUST_POWER_STATE: | ||
540 | pp_handle->hwmgr->current_ps = pp_handle->hwmgr->boot_ps; | ||
541 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); | ||
542 | break; | ||
539 | default: | 543 | default: |
540 | break; | 544 | break; |
541 | } | 545 | } |
@@ -806,6 +810,44 @@ static int pp_dpm_print_clock_levels(void *handle, | |||
806 | return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); | 810 | return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); |
807 | } | 811 | } |
808 | 812 | ||
813 | static int pp_dpm_get_sclk_od(void *handle) | ||
814 | { | ||
815 | struct pp_hwmgr *hwmgr; | ||
816 | |||
817 | if (!handle) | ||
818 | return -EINVAL; | ||
819 | |||
820 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | ||
821 | |||
822 | PP_CHECK_HW(hwmgr); | ||
823 | |||
824 | if (hwmgr->hwmgr_func->get_sclk_od == NULL) { | ||
825 | printk(KERN_INFO "%s was not implemented.\n", __func__); | ||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | return hwmgr->hwmgr_func->get_sclk_od(hwmgr); | ||
830 | } | ||
831 | |||
832 | static int pp_dpm_set_sclk_od(void *handle, uint32_t value) | ||
833 | { | ||
834 | struct pp_hwmgr *hwmgr; | ||
835 | |||
836 | if (!handle) | ||
837 | return -EINVAL; | ||
838 | |||
839 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | ||
840 | |||
841 | PP_CHECK_HW(hwmgr); | ||
842 | |||
843 | if (hwmgr->hwmgr_func->set_sclk_od == NULL) { | ||
844 | printk(KERN_INFO "%s was not implemented.\n", __func__); | ||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); | ||
849 | } | ||
850 | |||
809 | const struct amd_powerplay_funcs pp_dpm_funcs = { | 851 | const struct amd_powerplay_funcs pp_dpm_funcs = { |
810 | .get_temperature = pp_dpm_get_temperature, | 852 | .get_temperature = pp_dpm_get_temperature, |
811 | .load_firmware = pp_dpm_load_fw, | 853 | .load_firmware = pp_dpm_load_fw, |
@@ -828,6 +870,8 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { | |||
828 | .set_pp_table = pp_dpm_set_pp_table, | 870 | .set_pp_table = pp_dpm_set_pp_table, |
829 | .force_clock_level = pp_dpm_force_clock_level, | 871 | .force_clock_level = pp_dpm_force_clock_level, |
830 | .print_clock_levels = pp_dpm_print_clock_levels, | 872 | .print_clock_levels = pp_dpm_print_clock_levels, |
873 | .get_sclk_od = pp_dpm_get_sclk_od, | ||
874 | .set_sclk_od = pp_dpm_set_sclk_od, | ||
831 | }; | 875 | }; |
832 | 876 | ||
833 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, | 877 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, |
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 50b367d44307..154d406d4373 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | |||
@@ -342,6 +342,8 @@ struct amd_powerplay_funcs { | |||
342 | int (*set_pp_table)(void *handle, const char *buf, size_t size); | 342 | int (*set_pp_table)(void *handle, const char *buf, size_t size); |
343 | int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); | 343 | int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); |
344 | int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); | 344 | int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); |
345 | int (*get_sclk_od)(void *handle); | ||
346 | int (*set_sclk_od)(void *handle, uint32_t value); | ||
345 | }; | 347 | }; |
346 | 348 | ||
347 | struct amd_powerplay { | 349 | struct amd_powerplay { |
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 28f571449495..37ebfa296497 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | |||
@@ -338,6 +338,8 @@ struct pp_hwmgr_func { | |||
338 | int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); | 338 | int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); |
339 | int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); | 339 | int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); |
340 | int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable); | 340 | int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable); |
341 | int (*get_sclk_od)(struct pp_hwmgr *hwmgr); | ||
342 | int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); | ||
341 | }; | 343 | }; |
342 | 344 | ||
343 | struct pp_table_func { | 345 | struct pp_table_func { |