diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 98 |
1 files changed, 97 insertions, 1 deletions
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) |