Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Fix dcn21 num_states

[Why]
DML expects num_states to exclude the duplicate state.

[How]
Set num_states to correct value to prevent array off-by-one error. Also
refactor max clock level code for diags.

Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Dmytro Laktyushkin and committed by
Alex Deucher
c42656f8 00755bb7

+18 -30
+1 -1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
··· 3343 3343 void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb, 3344 3344 struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states) 3345 3345 { 3346 - struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES]; 3346 + struct _vcs_dpi_voltage_scaling_st calculated_states[DC__VOLTAGE_STATES]; 3347 3347 int i; 3348 3348 int num_calculated_states = 0; 3349 3349 int min_dcfclk = 0;
+12 -25
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
··· 300 300 .xfc_bus_transport_time_us = 4, 301 301 .xfc_xbuf_latency_tolerance_us = 4, 302 302 .use_urgent_burst_bw = 1, 303 - .num_states = 9 303 + .num_states = 8 304 304 }; 305 305 306 306 #ifndef MAX ··· 1377 1377 unsigned int i, j, k; 1378 1378 int closest_clk_lvl; 1379 1379 1380 - // diags does not retrieve proper values from SMU 1381 - // cap states to 5 and make state 5 the max state 1382 - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) || IS_DIAG_DC(dc->ctx->dce_environment)) { 1383 - dcn2_1_soc.num_states = 5; 1384 - 1385 - dcn2_1_soc.clock_limits[5].state = 5; 1386 - dcn2_1_soc.clock_limits[5].dcfclk_mhz = 810.0; 1387 - dcn2_1_soc.clock_limits[5].fabricclk_mhz = 1600.0; 1388 - dcn2_1_soc.clock_limits[5].dispclk_mhz = 1395.0; 1389 - dcn2_1_soc.clock_limits[5].dppclk_mhz = 1285.0; 1390 - dcn2_1_soc.clock_limits[5].phyclk_mhz = 1325.0; 1391 - dcn2_1_soc.clock_limits[5].socclk_mhz = 953.0; 1392 - dcn2_1_soc.clock_limits[5].dscclk_mhz = 489.0; 1393 - dcn2_1_soc.clock_limits[5].dram_speed_mts = 4266.0; 1394 - } else { 1380 + // Default clock levels are used for diags, which may lead to overclocking. 1381 + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !IS_DIAG_DC(dc->ctx->dce_environment)) { 1395 1382 dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; 1396 1383 dcn2_1_ip.max_num_dpp = pool->base.pipe_count; 1397 1384 dcn2_1_soc.num_chans = bw_params->num_channels; ··· 1391 1404 dcn2_1_soc.clock_limits[0].dram_speed_mts = clk_table->entries[0].memclk_mhz * 2; 1392 1405 1393 1406 /* 1394 - * Other levels: find cloest DCN clocks that fit the given clock limit using dcfclk 1395 - * as indicater 1407 + * Other levels: find closest DCN clocks that fit the given clock limit using dcfclk 1408 + * as indicator 1396 1409 */ 1397 1410 1398 1411 closest_clk_lvl = -1; 1399 1412 /* index currently being filled */ 1400 1413 k = 1; 1401 1414 for (i = 1; i < clk_table->num_entries; i++) { 1402 - /* loop backwards, skip duplicate state, +1 because SMU has precision issue */ 1403 - for (j = dcn2_1_soc.num_states - 2; j >= k; j--) { 1415 + /* loop backwards, skip duplicate state*/ 1416 + for (j = dcn2_1_soc.num_states - 1; j >= k; j--) { 1404 1417 if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { 1405 1418 closest_clk_lvl = j; 1406 1419 break; ··· 1425 1438 k++; 1426 1439 } 1427 1440 } 1428 - 1429 - /* duplicate last level */ 1430 - dcn2_1_soc.clock_limits[k] = dcn2_1_soc.clock_limits[k - 1]; 1431 - dcn2_1_soc.clock_limits[k].state = k; 1432 - dcn2_1_soc.num_states = k + 1; 1441 + dcn2_1_soc.num_states = k; 1433 1442 } 1443 + 1444 + /* duplicate last level */ 1445 + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; 1446 + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; 1434 1447 1435 1448 dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); 1436 1449 }
+1 -1
drivers/gpu/drm/amd/display/dc/dml/dc_features.h
··· 29 29 #define DC__PRESENT 1 30 30 #define DC__PRESENT__1 1 31 31 #define DC__NUM_DPP 4 32 - #define DC__VOLTAGE_STATES 7 32 + #define DC__VOLTAGE_STATES 9 33 33 #define DC__NUM_DPP__4 1 34 34 #define DC__NUM_DPP__0_PRESENT 1 35 35 #define DC__NUM_DPP__1_PRESENT 1
+4 -3
drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
··· 22 22 * Authors: AMD 23 23 * 24 24 */ 25 + 26 + #include "dc_features.h" 27 + 25 28 #ifndef __DISPLAY_MODE_STRUCTS_H__ 26 29 #define __DISPLAY_MODE_STRUCTS_H__ 27 - 28 - #define MAX_CLOCK_LIMIT_STATES 9 29 30 30 31 typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; 31 32 typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; ··· 69 68 }; 70 69 71 70 struct _vcs_dpi_soc_bounding_box_st { 72 - struct _vcs_dpi_voltage_scaling_st clock_limits[MAX_CLOCK_LIMIT_STATES]; 71 + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; 73 72 unsigned int num_states; 74 73 double sr_exit_time_us; 75 74 double sr_enter_plus_exit_time_us;