aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2018-08-29 02:38:50 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-09-10 23:39:30 -0400
commitd5bf26539494d16dfabbbea0854a47d202ea15c0 (patch)
treea0a4af89da4fdbbdc1e585d07d6241e20bf4970e
parent6abc0c8f8cf3e0c47707b01f027f9f9b9aa75646 (diff)
drm/amd/powerplay: added vega20 overdrive support V3
Added vega20 overdrive support based on existing OD sysfs APIs. However, the OD logics are simplified on vega20. So, the behavior will be a little different and works only on some limited levels. V2: fix typo fix commit description revise error logs add support for clock OD V3: separate clock from voltage OD settings Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c45
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c289
3 files changed, 335 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index b7b16cb5ff0f..396c826100e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -474,6 +474,8 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
474 * in each power level within a power state. The pp_od_clk_voltage is used for 474 * in each power level within a power state. The pp_od_clk_voltage is used for
475 * this. 475 * this.
476 * 476 *
477 * < For Vega10 and previous ASICs >
478 *
477 * Reading the file will display: 479 * Reading the file will display:
478 * 480 *
479 * - a list of engine clock levels and voltages labeled OD_SCLK 481 * - a list of engine clock levels and voltages labeled OD_SCLK
@@ -491,6 +493,44 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
491 * "c" (commit) to the file to commit your changes. If you want to reset to the 493 * "c" (commit) to the file to commit your changes. If you want to reset to the
492 * default power levels, write "r" (reset) to the file to reset them. 494 * default power levels, write "r" (reset) to the file to reset them.
493 * 495 *
496 *
497 * < For Vega20 >
498 *
499 * Reading the file will display:
500 *
501 * - minimum and maximum engine clock labeled OD_SCLK
502 *
503 * - maximum memory clock labeled OD_MCLK
504 *
505 * - three <frequency, voltage offset> points labeled OD_VDDC_CURVE.
506 * They can be used to calibrate the sclk voltage curve.
507 *
508 * - a list of valid ranges for sclk, mclk, and voltage curve points
509 * labeled OD_RANGE
510 *
511 * To manually adjust these settings:
512 *
513 * - First select manual using power_dpm_force_performance_level
514 *
515 * - For clock frequency setting, enter a new value by writing a
516 * string that contains "s/m index clock" to the file. The index
517 * should be 0 if to set minimum clock. And 1 if to set maximum
518 * clock. E.g., "s 0 500" will update minimum sclk to be 500 MHz.
519 * "m 1 800" will update maximum mclk to be 800Mhz.
520 *
521 * For sclk voltage curve, enter the new values by writing a
522 * string that contains "vc point clock voff" to the file. The
523 * points are indexed by 0, 1 and 2. E.g., "vc 0 300 10" will
524 * update point1 with clock set as 300Mhz and voltage increased
525 * by 10mV. "vc 2 1000 -10" will update point3 with clock set
526 * as 1000Mhz and voltage drop by 10mV.
527 *
528 * - When you have edited all of the states as needed, write "c" (commit)
529 * to the file to commit your changes
530 *
531 * - If you want to reset to the default power levels, write "r" (reset)
532 * to the file to reset them
533 *
494 */ 534 */
495 535
496static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, 536static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
@@ -520,6 +560,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
520 type = PP_OD_RESTORE_DEFAULT_TABLE; 560 type = PP_OD_RESTORE_DEFAULT_TABLE;
521 else if (*buf == 'c') 561 else if (*buf == 'c')
522 type = PP_OD_COMMIT_DPM_TABLE; 562 type = PP_OD_COMMIT_DPM_TABLE;
563 else if (!strncmp(buf, "vc", 2))
564 type = PP_OD_EDIT_VDDC_CURVE;
523 else 565 else
524 return -EINVAL; 566 return -EINVAL;
525 567
@@ -527,6 +569,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
527 569
528 tmp_str = buf_cpy; 570 tmp_str = buf_cpy;
529 571
572 if (type == PP_OD_EDIT_VDDC_CURVE)
573 tmp_str++;
530 while (isspace(*++tmp_str)); 574 while (isspace(*++tmp_str));
531 575
532 while (tmp_str[0]) { 576 while (tmp_str[0]) {
@@ -570,6 +614,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
570 if (adev->powerplay.pp_funcs->print_clock_levels) { 614 if (adev->powerplay.pp_funcs->print_clock_levels) {
571 size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); 615 size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf);
572 size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); 616 size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size);
617 size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size);
573 size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); 618 size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size);
574 return size; 619 return size;
575 } else { 620 } else {
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 6a41b81c7325..448dee481a38 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -94,6 +94,7 @@ enum pp_clock_type {
94 PP_PCIE, 94 PP_PCIE,
95 OD_SCLK, 95 OD_SCLK,
96 OD_MCLK, 96 OD_MCLK,
97 OD_VDDC_CURVE,
97 OD_RANGE, 98 OD_RANGE,
98}; 99};
99 100
@@ -141,6 +142,7 @@ enum {
141enum PP_OD_DPM_TABLE_COMMAND { 142enum PP_OD_DPM_TABLE_COMMAND {
142 PP_OD_EDIT_SCLK_VDDC_TABLE, 143 PP_OD_EDIT_SCLK_VDDC_TABLE,
143 PP_OD_EDIT_MCLK_VDDC_TABLE, 144 PP_OD_EDIT_MCLK_VDDC_TABLE,
145 PP_OD_EDIT_VDDC_CURVE,
144 PP_OD_RESTORE_DEFAULT_TABLE, 146 PP_OD_RESTORE_DEFAULT_TABLE,
145 PP_OD_COMMIT_DPM_TABLE 147 PP_OD_COMMIT_DPM_TABLE
146}; 148};
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index fb32b28afa66..3efd59e984a3 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -2325,11 +2325,207 @@ static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
2325 return 0; 2325 return 0;
2326} 2326}
2327 2327
2328static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2329 enum PP_OD_DPM_TABLE_COMMAND type,
2330 long *input, uint32_t size)
2331{
2332 struct vega20_hwmgr *data =
2333 (struct vega20_hwmgr *)(hwmgr->backend);
2334 struct vega20_od8_single_setting *od8_settings =
2335 data->od8_settings.od8_settings_array;
2336 OverDriveTable_t *od_table =
2337 &(data->smc_state_table.overdrive_table);
2338 struct pp_clock_levels_with_latency clocks;
2339 int32_t input_index, input_clk, input_vol, i;
2340 int ret;
2341
2342 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
2343 return -EINVAL);
2344
2345 switch (type) {
2346 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2347 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2348 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2349 pr_info("Sclk min/max frequency overdrive not supported\n");
2350 return -EOPNOTSUPP;
2351 }
2352
2353 for (i = 0; i < size; i += 2) {
2354 if (i + 2 > size) {
2355 pr_info("invalid number of input parameters %d\n",
2356 size);
2357 return -EINVAL;
2358 }
2359
2360 input_index = input[i];
2361 input_clk = input[i + 1];
2362
2363 if (input_index != 0 && input_index != 1) {
2364 pr_info("Invalid index %d\n", input_index);
2365 pr_info("Support min/max sclk frequency setting only which index by 0/1\n");
2366 return -EINVAL;
2367 }
2368
2369 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2370 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2371 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2372 input_clk,
2373 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2374 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2375 return -EINVAL;
2376 }
2377
2378 if (input_index == 0)
2379 od_table->GfxclkFmin = input_clk;
2380 else
2381 od_table->GfxclkFmax = input_clk;
2382 }
2383
2384 break;
2385
2386 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2387 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2388 pr_info("Mclk max frequency overdrive not supported\n");
2389 return -EOPNOTSUPP;
2390 }
2391
2392 ret = vega20_get_memclocks(hwmgr, &clocks);
2393 PP_ASSERT_WITH_CODE(!ret,
2394 "Attempt to get memory clk levels failed!",
2395 return ret);
2396
2397 for (i = 0; i < size; i += 2) {
2398 if (i + 2 > size) {
2399 pr_info("invalid number of input parameters %d\n",
2400 size);
2401 return -EINVAL;
2402 }
2403
2404 input_index = input[i];
2405 input_clk = input[i + 1];
2406
2407 if (input_index != 1) {
2408 pr_info("Invalid index %d\n", input_index);
2409 pr_info("Support max Mclk frequency setting only which index by 1\n");
2410 return -EINVAL;
2411 }
2412
2413 if (input_clk < clocks.data[0].clocks_in_khz / 100 ||
2414 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) {
2415 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2416 input_clk,
2417 clocks.data[0].clocks_in_khz / 100,
2418 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2419 return -EINVAL;
2420 }
2421
2422 od_table->UclkFmax = input_clk;
2423 }
2424
2425 break;
2426
2427 case PP_OD_EDIT_VDDC_CURVE:
2428 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2429 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2430 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2431 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2432 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2433 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2434 pr_info("Voltage curve calibrate not supported\n");
2435 return -EOPNOTSUPP;
2436 }
2437
2438 for (i = 0; i < size; i += 3) {
2439 if (i + 3 > size) {
2440 pr_info("invalid number of input parameters %d\n",
2441 size);
2442 return -EINVAL;
2443 }
2444
2445 input_index = input[i];
2446 input_clk = input[i + 1];
2447 input_vol = input[i + 2];
2448
2449 if (input_index > 2) {
2450 pr_info("Setting for point %d is not supported\n",
2451 input_index + 1);
2452 pr_info("Three supported points index by 0, 1, 2\n");
2453 return -EINVAL;
2454 }
2455
2456 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2457 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2458 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2459 input_clk,
2460 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2461 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2462 return -EINVAL;
2463 }
2464
2465 /* TODO: suppose voltage1/2/3 has the same min/max value */
2466 if (input_vol < od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value ||
2467 input_vol > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value) {
2468 pr_info("clock voltage offset %d is not within allowed range [%d - %d]\n",
2469 input_vol,
2470 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
2471 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
2472 return -EINVAL;
2473 }
2474
2475 switch (input_index) {
2476 case 0:
2477 od_table->GfxclkFreq1 = input_clk;
2478 od_table->GfxclkOffsetVolt1 = input_vol;
2479 break;
2480 case 1:
2481 od_table->GfxclkFreq2 = input_clk;
2482 od_table->GfxclkOffsetVolt2 = input_vol;
2483 break;
2484 case 2:
2485 od_table->GfxclkFreq3 = input_clk;
2486 od_table->GfxclkOffsetVolt3 = input_vol;
2487 break;
2488 }
2489 }
2490 break;
2491
2492 case PP_OD_RESTORE_DEFAULT_TABLE:
2493 ret = vega20_copy_table_from_smc(hwmgr,
2494 (uint8_t *)od_table,
2495 TABLE_OVERDRIVE);
2496 PP_ASSERT_WITH_CODE(!ret,
2497 "Failed to export overdrive table!",
2498 return ret);
2499 break;
2500
2501 case PP_OD_COMMIT_DPM_TABLE:
2502 ret = vega20_copy_table_to_smc(hwmgr,
2503 (uint8_t *)od_table,
2504 TABLE_OVERDRIVE);
2505 PP_ASSERT_WITH_CODE(!ret,
2506 "Failed to import overdrive table!",
2507 return ret);
2508
2509 break;
2510
2511 default:
2512 return -EINVAL;
2513 }
2514
2515 return 0;
2516}
2517
2328static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, 2518static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2329 enum pp_clock_type type, char *buf) 2519 enum pp_clock_type type, char *buf)
2330{ 2520{
2331 int i, now, size = 0; 2521 struct vega20_hwmgr *data =
2522 (struct vega20_hwmgr *)(hwmgr->backend);
2523 struct vega20_od8_single_setting *od8_settings =
2524 data->od8_settings.od8_settings_array;
2525 OverDriveTable_t *od_table =
2526 &(data->smc_state_table.overdrive_table);
2332 struct pp_clock_levels_with_latency clocks; 2527 struct pp_clock_levels_with_latency clocks;
2528 int i, now, size = 0;
2333 int ret = 0; 2529 int ret = 0;
2334 2530
2335 switch (type) { 2531 switch (type) {
@@ -2370,6 +2566,95 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2370 case PP_PCIE: 2566 case PP_PCIE:
2371 break; 2567 break;
2372 2568
2569 case OD_SCLK:
2570 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2571 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
2572 size = sprintf(buf, "%s:\n", "OD_SCLK");
2573 size += sprintf(buf + size, "0: %10uMhz\n",
2574 od_table->GfxclkFmin);
2575 size += sprintf(buf + size, "1: %10uMhz\n",
2576 od_table->GfxclkFmax);
2577 }
2578 break;
2579
2580 case OD_MCLK:
2581 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2582 size = sprintf(buf, "%s:\n", "OD_MCLK");
2583 size += sprintf(buf + size, "1: %10uMhz\n",
2584 od_table->UclkFmax);
2585 }
2586
2587 break;
2588
2589 case OD_VDDC_CURVE:
2590 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2591 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2592 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2593 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2594 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2595 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
2596 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
2597 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
2598 od_table->GfxclkFreq1,
2599 od_table->GfxclkOffsetVolt1);
2600 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
2601 od_table->GfxclkFreq2,
2602 od_table->GfxclkOffsetVolt2);
2603 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
2604 od_table->GfxclkFreq3,
2605 od_table->GfxclkOffsetVolt3);
2606 }
2607
2608 break;
2609
2610 case OD_RANGE:
2611 size = sprintf(buf, "%s:\n", "OD_RANGE");
2612
2613 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2614 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
2615 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
2616 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2617 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2618 }
2619
2620 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2621 ret = vega20_get_memclocks(hwmgr, &clocks);
2622 PP_ASSERT_WITH_CODE(!ret,
2623 "Fail to get memory clk levels!",
2624 return ret);
2625
2626 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
2627 clocks.data[0].clocks_in_khz / 100,
2628 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2629 }
2630
2631 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2632 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2633 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2634 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2635 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2636 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
2637 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
2638 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
2639 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
2640 size += sprintf(buf + size, "VDDC_CURVE_VOFF[0]: %7dmV %11dmV\n",
2641 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
2642 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
2643 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
2644 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
2645 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
2646 size += sprintf(buf + size, "VDDC_CURVE_VOFF[1]: %7dmV %11dmV\n",
2647 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
2648 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
2649 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
2650 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
2651 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
2652 size += sprintf(buf + size, "VDDC_CURVE_VOFF[2]: %7dmV %11dmV\n",
2653 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
2654 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
2655 }
2656
2657 break;
2373 default: 2658 default:
2374 break; 2659 break;
2375 } 2660 }
@@ -2977,6 +3262,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
2977 vega20_get_mclk_od, 3262 vega20_get_mclk_od,
2978 .set_mclk_od = 3263 .set_mclk_od =
2979 vega20_set_mclk_od, 3264 vega20_set_mclk_od,
3265 .odn_edit_dpm_table =
3266 vega20_odn_edit_dpm_table,
2980 /* for sysfs to retrive/set gfxclk/memclk */ 3267 /* for sysfs to retrive/set gfxclk/memclk */
2981 .force_clock_level = 3268 .force_clock_level =
2982 vega20_force_clock_level, 3269 vega20_force_clock_level,