diff options
author | Eric Huang <JinHuiEric.Huang@amd.com> | 2016-05-24 15:11:17 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-07-07 14:50:55 -0400 |
commit | f2bdc05f773ea68d31e2d50b9e791b7c7dcd1dfa (patch) | |
tree | c96bdf08a1ad3d8c22a8475779996aa8cb869ff7 | |
parent | 6bb6b2972d0affe1f86881d64c787627b916c17e (diff) |
drm/amdgpu: add the common code to support mclk OD
This implements mclk OverDrive(OD) through sysfs.
The new entry pp_mclk_od is read/write. The value of input/output
is an integer of the overclocking percentage.
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 | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 40 | ||||
-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, 107 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index bf398a421de6..33bc79e378e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -1563,6 +1563,8 @@ struct amdgpu_dpm_funcs { | |||
1563 | int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); | 1563 | int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); |
1564 | int (*get_sclk_od)(struct amdgpu_device *adev); | 1564 | int (*get_sclk_od)(struct amdgpu_device *adev); |
1565 | int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); | 1565 | int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); |
1566 | int (*get_mclk_od)(struct amdgpu_device *adev); | ||
1567 | int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); | ||
1566 | }; | 1568 | }; |
1567 | 1569 | ||
1568 | struct amdgpu_dpm { | 1570 | struct amdgpu_dpm { |
@@ -2351,6 +2353,12 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) | |||
2351 | #define amdgpu_dpm_set_sclk_od(adev, value) \ | 2353 | #define amdgpu_dpm_set_sclk_od(adev, value) \ |
2352 | (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) | 2354 | (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) |
2353 | 2355 | ||
2356 | #define amdgpu_dpm_get_mclk_od(adev) \ | ||
2357 | ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) | ||
2358 | |||
2359 | #define amdgpu_dpm_set_mclk_od(adev, value) \ | ||
2360 | ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) | ||
2361 | |||
2354 | #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ | 2362 | #define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ |
2355 | (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) | 2363 | (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) |
2356 | 2364 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index d6484d6e60dd..250f8693f170 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
@@ -527,6 +527,52 @@ fail: | |||
527 | return count; | 527 | return count; |
528 | } | 528 | } |
529 | 529 | ||
530 | static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, | ||
531 | struct device_attribute *attr, | ||
532 | char *buf) | ||
533 | { | ||
534 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
535 | struct amdgpu_device *adev = ddev->dev_private; | ||
536 | uint32_t value = 0; | ||
537 | |||
538 | if (adev->pp_enabled) | ||
539 | value = amdgpu_dpm_get_mclk_od(adev); | ||
540 | else if (adev->pm.funcs->get_mclk_od) | ||
541 | value = adev->pm.funcs->get_mclk_od(adev); | ||
542 | |||
543 | return snprintf(buf, PAGE_SIZE, "%d\n", value); | ||
544 | } | ||
545 | |||
546 | static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, | ||
547 | struct device_attribute *attr, | ||
548 | const char *buf, | ||
549 | size_t count) | ||
550 | { | ||
551 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
552 | struct amdgpu_device *adev = ddev->dev_private; | ||
553 | int ret; | ||
554 | long int value; | ||
555 | |||
556 | ret = kstrtol(buf, 0, &value); | ||
557 | |||
558 | if (ret) { | ||
559 | count = -EINVAL; | ||
560 | goto fail; | ||
561 | } | ||
562 | |||
563 | if (adev->pp_enabled) { | ||
564 | amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); | ||
565 | amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL); | ||
566 | } else if (adev->pm.funcs->set_mclk_od) { | ||
567 | adev->pm.funcs->set_mclk_od(adev, (uint32_t)value); | ||
568 | adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; | ||
569 | amdgpu_pm_compute_clocks(adev); | ||
570 | } | ||
571 | |||
572 | fail: | ||
573 | return count; | ||
574 | } | ||
575 | |||
530 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); | 576 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); |
531 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, | 577 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, |
532 | amdgpu_get_dpm_forced_performance_level, | 578 | amdgpu_get_dpm_forced_performance_level, |
@@ -551,6 +597,9 @@ static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR, | |||
551 | static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR, | 597 | static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR, |
552 | amdgpu_get_pp_sclk_od, | 598 | amdgpu_get_pp_sclk_od, |
553 | amdgpu_set_pp_sclk_od); | 599 | amdgpu_set_pp_sclk_od); |
600 | static DEVICE_ATTR(pp_mclk_od, S_IRUGO | S_IWUSR, | ||
601 | amdgpu_get_pp_mclk_od, | ||
602 | amdgpu_set_pp_mclk_od); | ||
554 | 603 | ||
555 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, | 604 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, |
556 | struct device_attribute *attr, | 605 | struct device_attribute *attr, |
@@ -1191,6 +1240,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) | |||
1191 | DRM_ERROR("failed to create device file pp_sclk_od\n"); | 1240 | DRM_ERROR("failed to create device file pp_sclk_od\n"); |
1192 | return ret; | 1241 | return ret; |
1193 | } | 1242 | } |
1243 | ret = device_create_file(adev->dev, &dev_attr_pp_mclk_od); | ||
1244 | if (ret) { | ||
1245 | DRM_ERROR("failed to create device file pp_mclk_od\n"); | ||
1246 | return ret; | ||
1247 | } | ||
1194 | 1248 | ||
1195 | ret = amdgpu_debugfs_pm_init(adev); | 1249 | ret = amdgpu_debugfs_pm_init(adev); |
1196 | if (ret) { | 1250 | if (ret) { |
@@ -1219,6 +1273,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) | |||
1219 | device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk); | 1273 | device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk); |
1220 | device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); | 1274 | device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); |
1221 | device_remove_file(adev->dev, &dev_attr_pp_sclk_od); | 1275 | device_remove_file(adev->dev, &dev_attr_pp_sclk_od); |
1276 | device_remove_file(adev->dev, &dev_attr_pp_mclk_od); | ||
1222 | } | 1277 | } |
1223 | 1278 | ||
1224 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 1279 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) |
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 8fa6f594d3ad..e931e87757de 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
@@ -848,6 +848,44 @@ static int pp_dpm_set_sclk_od(void *handle, uint32_t value) | |||
848 | return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); | 848 | return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); |
849 | } | 849 | } |
850 | 850 | ||
851 | static int pp_dpm_get_mclk_od(void *handle) | ||
852 | { | ||
853 | struct pp_hwmgr *hwmgr; | ||
854 | |||
855 | if (!handle) | ||
856 | return -EINVAL; | ||
857 | |||
858 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | ||
859 | |||
860 | PP_CHECK_HW(hwmgr); | ||
861 | |||
862 | if (hwmgr->hwmgr_func->get_mclk_od == NULL) { | ||
863 | printk(KERN_INFO "%s was not implemented.\n", __func__); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | return hwmgr->hwmgr_func->get_mclk_od(hwmgr); | ||
868 | } | ||
869 | |||
870 | static int pp_dpm_set_mclk_od(void *handle, uint32_t value) | ||
871 | { | ||
872 | struct pp_hwmgr *hwmgr; | ||
873 | |||
874 | if (!handle) | ||
875 | return -EINVAL; | ||
876 | |||
877 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | ||
878 | |||
879 | PP_CHECK_HW(hwmgr); | ||
880 | |||
881 | if (hwmgr->hwmgr_func->set_mclk_od == NULL) { | ||
882 | printk(KERN_INFO "%s was not implemented.\n", __func__); | ||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); | ||
887 | } | ||
888 | |||
851 | const struct amd_powerplay_funcs pp_dpm_funcs = { | 889 | const struct amd_powerplay_funcs pp_dpm_funcs = { |
852 | .get_temperature = pp_dpm_get_temperature, | 890 | .get_temperature = pp_dpm_get_temperature, |
853 | .load_firmware = pp_dpm_load_fw, | 891 | .load_firmware = pp_dpm_load_fw, |
@@ -872,6 +910,8 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { | |||
872 | .print_clock_levels = pp_dpm_print_clock_levels, | 910 | .print_clock_levels = pp_dpm_print_clock_levels, |
873 | .get_sclk_od = pp_dpm_get_sclk_od, | 911 | .get_sclk_od = pp_dpm_get_sclk_od, |
874 | .set_sclk_od = pp_dpm_set_sclk_od, | 912 | .set_sclk_od = pp_dpm_set_sclk_od, |
913 | .get_mclk_od = pp_dpm_get_mclk_od, | ||
914 | .set_mclk_od = pp_dpm_set_mclk_od, | ||
875 | }; | 915 | }; |
876 | 916 | ||
877 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, | 917 | 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 de1d6a81a6a4..d0dfaf9dfa06 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | |||
@@ -345,6 +345,8 @@ struct amd_powerplay_funcs { | |||
345 | int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); | 345 | int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); |
346 | int (*get_sclk_od)(void *handle); | 346 | int (*get_sclk_od)(void *handle); |
347 | int (*set_sclk_od)(void *handle, uint32_t value); | 347 | int (*set_sclk_od)(void *handle, uint32_t value); |
348 | int (*get_mclk_od)(void *handle); | ||
349 | int (*set_mclk_od)(void *handle, uint32_t value); | ||
348 | }; | 350 | }; |
349 | 351 | ||
350 | struct amd_powerplay { | 352 | struct amd_powerplay { |
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 3d9a413cf9c8..bcb224b01584 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | |||
@@ -340,6 +340,8 @@ struct pp_hwmgr_func { | |||
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); | 341 | int (*get_sclk_od)(struct pp_hwmgr *hwmgr); |
342 | int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); | 342 | int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); |
343 | int (*get_mclk_od)(struct pp_hwmgr *hwmgr); | ||
344 | int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); | ||
343 | }; | 345 | }; |
344 | 346 | ||
345 | struct pp_table_func { | 347 | struct pp_table_func { |