diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 365 | 
1 files changed, 282 insertions, 83 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 361975cf45a9..b455da487782 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
| @@ -77,6 +77,37 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) | |||
| 77 | } | 77 | } | 
| 78 | } | 78 | } | 
| 79 | 79 | ||
| 80 | /** | ||
| 81 | * DOC: power_dpm_state | ||
| 82 | * | ||
| 83 | * This is a legacy interface and is only provided for backwards compatibility. | ||
| 84 | * The amdgpu driver provides a sysfs API for adjusting certain power | ||
| 85 | * related parameters. The file power_dpm_state is used for this. | ||
| 86 | * It accepts the following arguments: | ||
| 87 | * - battery | ||
| 88 | * - balanced | ||
| 89 | * - performance | ||
| 90 | * | ||
| 91 | * battery | ||
| 92 | * | ||
| 93 | * On older GPUs, the vbios provided a special power state for battery | ||
| 94 | * operation. Selecting battery switched to this state. This is no | ||
| 95 | * longer provided on newer GPUs so the option does nothing in that case. | ||
| 96 | * | ||
| 97 | * balanced | ||
| 98 | * | ||
| 99 | * On older GPUs, the vbios provided a special power state for balanced | ||
| 100 | * operation. Selecting balanced switched to this state. This is no | ||
| 101 | * longer provided on newer GPUs so the option does nothing in that case. | ||
| 102 | * | ||
| 103 | * performance | ||
| 104 | * | ||
| 105 | * On older GPUs, the vbios provided a special power state for performance | ||
| 106 | * operation. Selecting performance switched to this state. This is no | ||
| 107 | * longer provided on newer GPUs so the option does nothing in that case. | ||
| 108 | * | ||
| 109 | */ | ||
| 110 | |||
| 80 | static ssize_t amdgpu_get_dpm_state(struct device *dev, | 111 | static ssize_t amdgpu_get_dpm_state(struct device *dev, | 
| 81 | struct device_attribute *attr, | 112 | struct device_attribute *attr, | 
| 82 | char *buf) | 113 | char *buf) | 
| @@ -131,6 +162,59 @@ fail: | |||
| 131 | return count; | 162 | return count; | 
| 132 | } | 163 | } | 
| 133 | 164 | ||
| 165 | |||
| 166 | /** | ||
| 167 | * DOC: power_dpm_force_performance_level | ||
| 168 | * | ||
| 169 | * The amdgpu driver provides a sysfs API for adjusting certain power | ||
| 170 | * related parameters. The file power_dpm_force_performance_level is | ||
| 171 | * used for this. It accepts the following arguments: | ||
| 172 | * - auto | ||
| 173 | * - low | ||
| 174 | * - high | ||
| 175 | * - manual | ||
| 176 | * - GPU fan | ||
| 177 | * - profile_standard | ||
| 178 | * - profile_min_sclk | ||
| 179 | * - profile_min_mclk | ||
| 180 | * - profile_peak | ||
| 181 | * | ||
| 182 | * auto | ||
| 183 | * | ||
| 184 | * When auto is selected, the driver will attempt to dynamically select | ||
| 185 | * the optimal power profile for current conditions in the driver. | ||
| 186 | * | ||
| 187 | * low | ||
| 188 | * | ||
| 189 | * When low is selected, the clocks are forced to the lowest power state. | ||
| 190 | * | ||
| 191 | * high | ||
| 192 | * | ||
| 193 | * When high is selected, the clocks are forced to the highest power state. | ||
| 194 | * | ||
| 195 | * manual | ||
| 196 | * | ||
| 197 | * When manual is selected, the user can manually adjust which power states | ||
| 198 | * are enabled for each clock domain via the sysfs pp_dpm_mclk, pp_dpm_sclk, | ||
| 199 | * and pp_dpm_pcie files and adjust the power state transition heuristics | ||
| 200 | * via the pp_power_profile_mode sysfs file. | ||
| 201 | * | ||
| 202 | * profile_standard | ||
| 203 | * profile_min_sclk | ||
| 204 | * profile_min_mclk | ||
| 205 | * profile_peak | ||
| 206 | * | ||
| 207 | * When the profiling modes are selected, clock and power gating are | ||
| 208 | * disabled and the clocks are set for different profiling cases. This | ||
| 209 | * mode is recommended for profiling specific work loads where you do | ||
| 210 | * not want clock or power gating for clock fluctuation to interfere | ||
| 211 | * with your results. profile_standard sets the clocks to a fixed clock | ||
| 212 | * level which varies from asic to asic. profile_min_sclk forces the sclk | ||
| 213 | * to the lowest level. profile_min_mclk forces the mclk to the lowest level. | ||
| 214 | * profile_peak sets all clocks (mclk, sclk, pcie) to the highest levels. | ||
| 215 | * | ||
| 216 | */ | ||
| 217 | |||
| 134 | static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, | 218 | static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, | 
| 135 | struct device_attribute *attr, | 219 | struct device_attribute *attr, | 
| 136 | char *buf) | 220 | char *buf) | 
| @@ -324,6 +408,17 @@ fail: | |||
| 324 | return count; | 408 | return count; | 
| 325 | } | 409 | } | 
| 326 | 410 | ||
| 411 | /** | ||
| 412 | * DOC: pp_table | ||
| 413 | * | ||
| 414 | * The amdgpu driver provides a sysfs API for uploading new powerplay | ||
| 415 | * tables. The file pp_table is used for this. Reading the file | ||
| 416 | * will dump the current power play table. Writing to the file | ||
| 417 | * will attempt to upload a new powerplay table and re-initialize | ||
| 418 | * powerplay using that new table. | ||
| 419 | * | ||
| 420 | */ | ||
| 421 | |||
| 327 | static ssize_t amdgpu_get_pp_table(struct device *dev, | 422 | static ssize_t amdgpu_get_pp_table(struct device *dev, | 
| 328 | struct device_attribute *attr, | 423 | struct device_attribute *attr, | 
| 329 | char *buf) | 424 | char *buf) | 
| @@ -360,6 +455,29 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, | |||
| 360 | return count; | 455 | return count; | 
| 361 | } | 456 | } | 
| 362 | 457 | ||
| 458 | /** | ||
| 459 | * DOC: pp_od_clk_voltage | ||
| 460 | * | ||
| 461 | * The amdgpu driver provides a sysfs API for adjusting the clocks and voltages | ||
| 462 | * in each power level within a power state. The pp_od_clk_voltage is used for | ||
| 463 | * this. | ||
| 464 | * | ||
| 465 | * Reading the file will display: | ||
| 466 | * - a list of engine clock levels and voltages labeled OD_SCLK | ||
| 467 | * - a list of memory clock levels and voltages labeled OD_MCLK | ||
| 468 | * - a list of valid ranges for sclk, mclk, and voltage labeled OD_RANGE | ||
| 469 | * | ||
| 470 | * To manually adjust these settings, first select manual using | ||
| 471 | * power_dpm_force_performance_level. Enter a new value for each | ||
| 472 | * level by writing a string that contains "s/m level clock voltage" to | ||
| 473 | * the file. E.g., "s 1 500 820" will update sclk level 1 to be 500 MHz | ||
| 474 | * at 820 mV; "m 0 350 810" will update mclk level 0 to be 350 MHz at | ||
| 475 | * 810 mV. When you have edited all of the states as needed, write | ||
| 476 | * "c" (commit) to the file to commit your changes. If you want to reset to the | ||
| 477 | * default power levels, write "r" (reset) to the file to reset them. | ||
| 478 | * | ||
| 479 | */ | ||
| 480 | |||
| 363 | static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, | 481 | static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, | 
| 364 | struct device_attribute *attr, | 482 | struct device_attribute *attr, | 
| 365 | const char *buf, | 483 | const char *buf, | 
| @@ -437,6 +555,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, | |||
| 437 | if (adev->powerplay.pp_funcs->print_clock_levels) { | 555 | if (adev->powerplay.pp_funcs->print_clock_levels) { | 
| 438 | size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); | 556 | size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); | 
| 439 | size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); | 557 | size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); | 
| 558 | size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); | ||
| 440 | return size; | 559 | return size; | 
| 441 | } else { | 560 | } else { | 
| 442 | return snprintf(buf, PAGE_SIZE, "\n"); | 561 | return snprintf(buf, PAGE_SIZE, "\n"); | 
| @@ -444,6 +563,23 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, | |||
| 444 | 563 | ||
| 445 | } | 564 | } | 
| 446 | 565 | ||
| 566 | /** | ||
| 567 | * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie | ||
| 568 | * | ||
| 569 | * The amdgpu driver provides a sysfs API for adjusting what power levels | ||
| 570 | * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk, | ||
| 571 | * and pp_dpm_pcie are used for this. | ||
| 572 | * | ||
| 573 | * Reading back the files will show you the available power levels within | ||
| 574 | * the power state and the clock information for those levels. | ||
| 575 | * | ||
| 576 | * To manually adjust these states, first select manual using | ||
| 577 | * power_dpm_force_performance_level. | ||
| 578 | * Secondly,Enter a new value for each level by inputing a string that | ||
| 579 | * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie" | ||
| 580 | * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6. | ||
| 581 | */ | ||
| 582 | |||
| 447 | static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, | 583 | static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, | 
| 448 | struct device_attribute *attr, | 584 | struct device_attribute *attr, | 
| 449 | char *buf) | 585 | char *buf) | 
| @@ -466,23 +602,27 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, | |||
| 466 | struct amdgpu_device *adev = ddev->dev_private; | 602 | struct amdgpu_device *adev = ddev->dev_private; | 
| 467 | int ret; | 603 | int ret; | 
| 468 | long level; | 604 | long level; | 
| 469 | uint32_t i, mask = 0; | 605 | uint32_t mask = 0; | 
| 470 | char sub_str[2]; | 606 | char *sub_str = NULL; | 
| 607 | char *tmp; | ||
| 608 | char buf_cpy[count]; | ||
| 609 | const char delimiter[3] = {' ', '\n', '\0'}; | ||
| 471 | 610 | ||
| 472 | for (i = 0; i < strlen(buf); i++) { | 611 | memcpy(buf_cpy, buf, count+1); | 
| 473 | if (*(buf + i) == '\n') | 612 | tmp = buf_cpy; | 
| 474 | continue; | 613 | while (tmp[0]) { | 
| 475 | sub_str[0] = *(buf + i); | 614 | sub_str = strsep(&tmp, delimiter); | 
| 476 | sub_str[1] = '\0'; | 615 | if (strlen(sub_str)) { | 
| 477 | ret = kstrtol(sub_str, 0, &level); | 616 | ret = kstrtol(sub_str, 0, &level); | 
| 478 | 617 | ||
| 479 | if (ret) { | 618 | if (ret) { | 
| 480 | count = -EINVAL; | 619 | count = -EINVAL; | 
| 481 | goto fail; | 620 | goto fail; | 
| 482 | } | 621 | } | 
| 483 | mask |= 1 << level; | 622 | mask |= 1 << level; | 
| 623 | } else | ||
| 624 | break; | ||
| 484 | } | 625 | } | 
| 485 | |||
| 486 | if (adev->powerplay.pp_funcs->force_clock_level) | 626 | if (adev->powerplay.pp_funcs->force_clock_level) | 
| 487 | amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); | 627 | amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); | 
| 488 | 628 | ||
| @@ -512,21 +652,26 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, | |||
| 512 | struct amdgpu_device *adev = ddev->dev_private; | 652 | struct amdgpu_device *adev = ddev->dev_private; | 
| 513 | int ret; | 653 | int ret; | 
| 514 | long level; | 654 | long level; | 
| 515 | uint32_t i, mask = 0; | 655 | uint32_t mask = 0; | 
| 516 | char sub_str[2]; | 656 | char *sub_str = NULL; | 
| 657 | char *tmp; | ||
| 658 | char buf_cpy[count]; | ||
| 659 | const char delimiter[3] = {' ', '\n', '\0'}; | ||
| 517 | 660 | ||
| 518 | for (i = 0; i < strlen(buf); i++) { | 661 | memcpy(buf_cpy, buf, count+1); | 
| 519 | if (*(buf + i) == '\n') | 662 | tmp = buf_cpy; | 
| 520 | continue; | 663 | while (tmp[0]) { | 
| 521 | sub_str[0] = *(buf + i); | 664 | sub_str = strsep(&tmp, delimiter); | 
| 522 | sub_str[1] = '\0'; | 665 | if (strlen(sub_str)) { | 
| 523 | ret = kstrtol(sub_str, 0, &level); | 666 | ret = kstrtol(sub_str, 0, &level); | 
| 524 | 667 | ||
| 525 | if (ret) { | 668 | if (ret) { | 
| 526 | count = -EINVAL; | 669 | count = -EINVAL; | 
| 527 | goto fail; | 670 | goto fail; | 
| 528 | } | 671 | } | 
| 529 | mask |= 1 << level; | 672 | mask |= 1 << level; | 
| 673 | } else | ||
| 674 | break; | ||
| 530 | } | 675 | } | 
| 531 | if (adev->powerplay.pp_funcs->force_clock_level) | 676 | if (adev->powerplay.pp_funcs->force_clock_level) | 
| 532 | amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); | 677 | amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); | 
| @@ -557,21 +702,27 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, | |||
| 557 | struct amdgpu_device *adev = ddev->dev_private; | 702 | struct amdgpu_device *adev = ddev->dev_private; | 
| 558 | int ret; | 703 | int ret; | 
| 559 | long level; | 704 | long level; | 
| 560 | uint32_t i, mask = 0; | 705 | uint32_t mask = 0; | 
| 561 | char sub_str[2]; | 706 | char *sub_str = NULL; | 
| 707 | char *tmp; | ||
| 708 | char buf_cpy[count]; | ||
| 709 | const char delimiter[3] = {' ', '\n', '\0'}; | ||
| 562 | 710 | ||
| 563 | for (i = 0; i < strlen(buf); i++) { | 711 | memcpy(buf_cpy, buf, count+1); | 
| 564 | if (*(buf + i) == '\n') | 712 | tmp = buf_cpy; | 
| 565 | continue; | ||
| 566 | sub_str[0] = *(buf + i); | ||
| 567 | sub_str[1] = '\0'; | ||
| 568 | ret = kstrtol(sub_str, 0, &level); | ||
| 569 | 713 | ||
| 570 | if (ret) { | 714 | while (tmp[0]) { | 
| 571 | count = -EINVAL; | 715 | sub_str = strsep(&tmp, delimiter); | 
| 572 | goto fail; | 716 | if (strlen(sub_str)) { | 
| 573 | } | 717 | ret = kstrtol(sub_str, 0, &level); | 
| 574 | mask |= 1 << level; | 718 | |
| 719 | if (ret) { | ||
| 720 | count = -EINVAL; | ||
| 721 | goto fail; | ||
| 722 | } | ||
| 723 | mask |= 1 << level; | ||
| 724 | } else | ||
| 725 | break; | ||
| 575 | } | 726 | } | 
| 576 | if (adev->powerplay.pp_funcs->force_clock_level) | 727 | if (adev->powerplay.pp_funcs->force_clock_level) | 
| 577 | amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); | 728 | amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); | 
| @@ -668,6 +819,26 @@ fail: | |||
| 668 | return count; | 819 | return count; | 
| 669 | } | 820 | } | 
| 670 | 821 | ||
| 822 | /** | ||
| 823 | * DOC: pp_power_profile_mode | ||
| 824 | * | ||
| 825 | * The amdgpu driver provides a sysfs API for adjusting the heuristics | ||
| 826 | * related to switching between power levels in a power state. The file | ||
| 827 | * pp_power_profile_mode is used for this. | ||
| 828 | * | ||
| 829 | * Reading this file outputs a list of all of the predefined power profiles | ||
| 830 | * and the relevant heuristics settings for that profile. | ||
| 831 | * | ||
| 832 | * To select a profile or create a custom profile, first select manual using | ||
| 833 | * power_dpm_force_performance_level. Writing the number of a predefined | ||
| 834 | * profile to pp_power_profile_mode will enable those heuristics. To | ||
| 835 | * create a custom set of heuristics, write a string of numbers to the file | ||
| 836 | * starting with the number of the custom profile along with a setting | ||
| 837 | * for each heuristic parameter. Due to differences across asic families | ||
| 838 | * the heuristic parameters vary from family to family. | ||
| 839 | * | ||
| 840 | */ | ||
| 841 | |||
| 671 | static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, | 842 | static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, | 
| 672 | struct device_attribute *attr, | 843 | struct device_attribute *attr, | 
| 673 | char *buf) | 844 | char *buf) | 
| @@ -1020,8 +1191,8 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, | |||
| 1020 | { | 1191 | { | 
| 1021 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 1192 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 
| 1022 | struct drm_device *ddev = adev->ddev; | 1193 | struct drm_device *ddev = adev->ddev; | 
| 1023 | struct pp_gpu_power query = {0}; | 1194 | u32 query = 0; | 
| 1024 | int r, size = sizeof(query); | 1195 | int r, size = sizeof(u32); | 
| 1025 | unsigned uw; | 1196 | unsigned uw; | 
| 1026 | 1197 | ||
| 1027 | /* Can't get power when the card is off */ | 1198 | /* Can't get power when the card is off */ | 
| @@ -1041,7 +1212,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, | |||
| 1041 | return r; | 1212 | return r; | 
| 1042 | 1213 | ||
| 1043 | /* convert to microwatts */ | 1214 | /* convert to microwatts */ | 
| 1044 | uw = (query.average_gpu_power >> 8) * 1000000; | 1215 | uw = (query >> 8) * 1000000 + (query & 0xff) * 1000; | 
| 1045 | 1216 | ||
| 1046 | return snprintf(buf, PAGE_SIZE, "%u\n", uw); | 1217 | return snprintf(buf, PAGE_SIZE, "%u\n", uw); | 
| 1047 | } | 1218 | } | 
| @@ -1109,6 +1280,46 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, | |||
| 1109 | return count; | 1280 | return count; | 
| 1110 | } | 1281 | } | 
| 1111 | 1282 | ||
| 1283 | |||
| 1284 | /** | ||
| 1285 | * DOC: hwmon | ||
| 1286 | * | ||
| 1287 | * The amdgpu driver exposes the following sensor interfaces: | ||
| 1288 | * - GPU temperature (via the on-die sensor) | ||
| 1289 | * - GPU voltage | ||
| 1290 | * - Northbridge voltage (APUs only) | ||
| 1291 | * - GPU power | ||
| 1292 | * - GPU fan | ||
| 1293 | * | ||
| 1294 | * hwmon interfaces for GPU temperature: | ||
| 1295 | * - temp1_input: the on die GPU temperature in millidegrees Celsius | ||
| 1296 | * - temp1_crit: temperature critical max value in millidegrees Celsius | ||
| 1297 | * - temp1_crit_hyst: temperature hysteresis for critical limit in millidegrees Celsius | ||
| 1298 | * | ||
| 1299 | * hwmon interfaces for GPU voltage: | ||
| 1300 | * - in0_input: the voltage on the GPU in millivolts | ||
| 1301 | * - in1_input: the voltage on the Northbridge in millivolts | ||
| 1302 | * | ||
| 1303 | * hwmon interfaces for GPU power: | ||
| 1304 | * - power1_average: average power used by the GPU in microWatts | ||
| 1305 | * - power1_cap_min: minimum cap supported in microWatts | ||
| 1306 | * - power1_cap_max: maximum cap supported in microWatts | ||
| 1307 | * - power1_cap: selected power cap in microWatts | ||
| 1308 | * | ||
| 1309 | * hwmon interfaces for GPU fan: | ||
| 1310 | * - pwm1: pulse width modulation fan level (0-255) | ||
| 1311 | * - pwm1_enable: pulse width modulation fan control method | ||
| 1312 | * 0: no fan speed control | ||
| 1313 | * 1: manual fan speed control using pwm interface | ||
| 1314 | * 2: automatic fan speed control | ||
| 1315 | * - pwm1_min: pulse width modulation fan control minimum level (0) | ||
| 1316 | * - pwm1_max: pulse width modulation fan control maximum level (255) | ||
| 1317 | * - fan1_input: fan speed in RPM | ||
| 1318 | * | ||
| 1319 | * You can use hwmon tools like sensors to view this information on your system. | ||
| 1320 | * | ||
| 1321 | */ | ||
| 1322 | |||
| 1112 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0); | 1323 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0); | 
| 1113 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0); | 1324 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0); | 
| 1114 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1); | 1325 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1); | 
| @@ -1153,19 +1364,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
| 1153 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 1364 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 
| 1154 | umode_t effective_mode = attr->mode; | 1365 | umode_t effective_mode = attr->mode; | 
| 1155 | 1366 | ||
| 1156 | /* handle non-powerplay limitations */ | 1367 | |
| 1157 | if (!adev->powerplay.pp_handle) { | 1368 | /* Skip fan attributes if fan is not present */ | 
| 1158 | /* Skip fan attributes if fan is not present */ | 1369 | if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || | 
| 1159 | if (adev->pm.no_fan && | 1370 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || | 
| 1160 | (attr == &sensor_dev_attr_pwm1.dev_attr.attr || | 1371 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | 
| 1161 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || | 1372 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || | 
| 1162 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | 1373 | attr == &sensor_dev_attr_fan1_input.dev_attr.attr)) | 
| 1163 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) | 1374 | return 0; | 
| 1164 | return 0; | ||
| 1165 | /* requires powerplay */ | ||
| 1166 | if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr) | ||
| 1167 | return 0; | ||
| 1168 | } | ||
| 1169 | 1375 | ||
| 1170 | /* Skip limit attributes if DPM is not enabled */ | 1376 | /* Skip limit attributes if DPM is not enabled */ | 
| 1171 | if (!adev->pm.dpm_enabled && | 1377 | if (!adev->pm.dpm_enabled && | 
| @@ -1658,9 +1864,6 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) | |||
| 1658 | 1864 | ||
| 1659 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 1865 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 
| 1660 | { | 1866 | { | 
| 1661 | struct drm_device *ddev = adev->ddev; | ||
| 1662 | struct drm_crtc *crtc; | ||
| 1663 | struct amdgpu_crtc *amdgpu_crtc; | ||
| 1664 | int i = 0; | 1867 | int i = 0; | 
| 1665 | 1868 | ||
| 1666 | if (!adev->pm.dpm_enabled) | 1869 | if (!adev->pm.dpm_enabled) | 
| @@ -1676,21 +1879,25 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | |||
| 1676 | } | 1879 | } | 
| 1677 | 1880 | ||
| 1678 | if (adev->powerplay.pp_funcs->dispatch_tasks) { | 1881 | if (adev->powerplay.pp_funcs->dispatch_tasks) { | 
| 1882 | if (!amdgpu_device_has_dc_support(adev)) { | ||
| 1883 | mutex_lock(&adev->pm.mutex); | ||
| 1884 | amdgpu_dpm_get_active_displays(adev); | ||
| 1885 | adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtcs; | ||
| 1886 | adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); | ||
| 1887 | adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); | ||
| 1888 | /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ | ||
| 1889 | if (adev->pm.pm_display_cfg.vrefresh > 120) | ||
| 1890 | adev->pm.pm_display_cfg.min_vblank_time = 0; | ||
| 1891 | if (adev->powerplay.pp_funcs->display_configuration_change) | ||
| 1892 | adev->powerplay.pp_funcs->display_configuration_change( | ||
| 1893 | adev->powerplay.pp_handle, | ||
| 1894 | &adev->pm.pm_display_cfg); | ||
| 1895 | mutex_unlock(&adev->pm.mutex); | ||
| 1896 | } | ||
| 1679 | amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); | 1897 | amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); | 
| 1680 | } else { | 1898 | } else { | 
| 1681 | mutex_lock(&adev->pm.mutex); | 1899 | mutex_lock(&adev->pm.mutex); | 
| 1682 | adev->pm.dpm.new_active_crtcs = 0; | 1900 | amdgpu_dpm_get_active_displays(adev); | 
| 1683 | adev->pm.dpm.new_active_crtc_count = 0; | ||
| 1684 | if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { | ||
| 1685 | list_for_each_entry(crtc, | ||
| 1686 | &ddev->mode_config.crtc_list, head) { | ||
| 1687 | amdgpu_crtc = to_amdgpu_crtc(crtc); | ||
| 1688 | if (amdgpu_crtc->enabled) { | ||
| 1689 | adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); | ||
| 1690 | adev->pm.dpm.new_active_crtc_count++; | ||
| 1691 | } | ||
| 1692 | } | ||
| 1693 | } | ||
| 1694 | /* update battery/ac status */ | 1901 | /* update battery/ac status */ | 
| 1695 | if (power_supply_is_system_supplied() > 0) | 1902 | if (power_supply_is_system_supplied() > 0) | 
| 1696 | adev->pm.dpm.ac_power = true; | 1903 | adev->pm.dpm.ac_power = true; | 
| @@ -1711,7 +1918,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | |||
| 1711 | static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) | 1918 | static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) | 
| 1712 | { | 1919 | { | 
| 1713 | uint32_t value; | 1920 | uint32_t value; | 
| 1714 | struct pp_gpu_power query = {0}; | 1921 | uint32_t query = 0; | 
| 1715 | int size; | 1922 | int size; | 
| 1716 | 1923 | ||
| 1717 | /* sanity check PP is enabled */ | 1924 | /* sanity check PP is enabled */ | 
| @@ -1734,17 +1941,9 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a | |||
| 1734 | seq_printf(m, "\t%u mV (VDDGFX)\n", value); | 1941 | seq_printf(m, "\t%u mV (VDDGFX)\n", value); | 
| 1735 | if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size)) | 1942 | if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size)) | 
| 1736 | seq_printf(m, "\t%u mV (VDDNB)\n", value); | 1943 | seq_printf(m, "\t%u mV (VDDNB)\n", value); | 
| 1737 | size = sizeof(query); | 1944 | size = sizeof(uint32_t); | 
| 1738 | if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size)) { | 1945 | if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size)) | 
| 1739 | seq_printf(m, "\t%u.%u W (VDDC)\n", query.vddc_power >> 8, | 1946 | seq_printf(m, "\t%u.%u W (average GPU)\n", query >> 8, query & 0xff); | 
| 1740 | query.vddc_power & 0xff); | ||
| 1741 | seq_printf(m, "\t%u.%u W (VDDCI)\n", query.vddci_power >> 8, | ||
| 1742 | query.vddci_power & 0xff); | ||
| 1743 | seq_printf(m, "\t%u.%u W (max GPU)\n", query.max_gpu_power >> 8, | ||
| 1744 | query.max_gpu_power & 0xff); | ||
| 1745 | seq_printf(m, "\t%u.%u W (average GPU)\n", query.average_gpu_power >> 8, | ||
| 1746 | query.average_gpu_power & 0xff); | ||
| 1747 | } | ||
| 1748 | size = sizeof(value); | 1947 | size = sizeof(value); | 
| 1749 | seq_printf(m, "\n"); | 1948 | seq_printf(m, "\n"); | 
| 1750 | 1949 | ||
