From a39a58166901f7e72088c5eedbd17e481f0722ea Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 20 Jan 2020 12:56:43 -0500 Subject: drm/amd/display: fix inputting clk lvl into dml for RN [Why] Previous logic is only good for 15W parts. Other configuration need a smarter logic to match clk levels with pp table in the fuse. [How] Cache all 8 DPM level's clock data, find lvl that match each pstate in the pp table and build input into DML base on that Signed-off-by: Eric Yang Signed-off-by: Sung Lee Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 165 ++++++++++++++++----- 1 file changed, 125 insertions(+), 40 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dcn21') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 0d506d30d6b6..5f6fb16f16e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -162,10 +162,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { .clock_limits = { { .state = 0, - .dcfclk_mhz = 304.0, - .fabricclk_mhz = 600.0, - .dispclk_mhz = 618.0, - .dppclk_mhz = 440.0, + .dcfclk_mhz = 400.0, + .fabricclk_mhz = 400.0, + .dispclk_mhz = 600.0, + .dppclk_mhz = 400.00, .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 205.67, @@ -173,10 +173,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, { .state = 1, - .dcfclk_mhz = 304.0, - .fabricclk_mhz = 600.0, - .dispclk_mhz = 618.0, - .dppclk_mhz = 618.0, + .dcfclk_mhz = 464.52, + .fabricclk_mhz = 800.0, + .dispclk_mhz = 654.55, + .dppclk_mhz = 626.09, .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 205.67, @@ -184,32 +184,65 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, { .state = 2, - .dcfclk_mhz = 608.0, - .fabricclk_mhz = 1066.0, - .dispclk_mhz = 888.0, - .dppclk_mhz = 888.0, - .phyclk_mhz = 810.0, + .dcfclk_mhz = 514.29, + .fabricclk_mhz = 933.0, + .dispclk_mhz = 757.89, + .dppclk_mhz = 685.71, + .phyclk_mhz = 600.0, .socclk_mhz = 278.0, .dscclk_mhz = 287.67, - .dram_speed_mts = 2133.0, + .dram_speed_mts = 1866.0, }, { .state = 3, - .dcfclk_mhz = 676.0, - .fabricclk_mhz = 1600.0, - .dispclk_mhz = 1015.0, - .dppclk_mhz = 1015.0, - .phyclk_mhz = 810.0, + .dcfclk_mhz = 576.00, + .fabricclk_mhz = 1067.0, + .dispclk_mhz = 847.06, + .dppclk_mhz = 757.89, + .phyclk_mhz = 600.0, .socclk_mhz = 715.0, .dscclk_mhz = 318.334, - .dram_speed_mts = 4266.0, + .dram_speed_mts = 2134.0, }, { .state = 4, - .dcfclk_mhz = 810.0, + .dcfclk_mhz = 626.09, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 900.00, + .dppclk_mhz = 847.06, + .phyclk_mhz = 810.0, + .socclk_mhz = 953.0, + .dscclk_mhz = 489.0, + .dram_speed_mts = 2400.0, + }, + { + .state = 5, + .dcfclk_mhz = 685.71, + .fabricclk_mhz = 1333.0, + .dispclk_mhz = 1028.57, + .dppclk_mhz = 960.00, + .phyclk_mhz = 810.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 287.67, + .dram_speed_mts = 2666.0, + }, + { + .state = 6, + .dcfclk_mhz = 757.89, + .fabricclk_mhz = 1467.0, + .dispclk_mhz = 1107.69, + .dppclk_mhz = 1028.57, + .phyclk_mhz = 810.0, + .socclk_mhz = 715.0, + .dscclk_mhz = 318.334, + .dram_speed_mts = 3200.0, + }, + { + .state = 7, + .dcfclk_mhz = 847.06, .fabricclk_mhz = 1600.0, .dispclk_mhz = 1395.0, - .dppclk_mhz = 1285.0, + .dppclk_mhz = 1285.00, .phyclk_mhz = 1325.0, .socclk_mhz = 953.0, .dscclk_mhz = 489.0, @@ -217,8 +250,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { }, /*Extra state, no dispclk ramping*/ { - .state = 5, - .dcfclk_mhz = 810.0, + .state = 8, + .dcfclk_mhz = 847.06, .fabricclk_mhz = 1600.0, .dispclk_mhz = 1395.0, .dppclk_mhz = 1285.0, @@ -265,7 +298,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { .xfc_bus_transport_time_us = 4, .xfc_xbuf_latency_tolerance_us = 4, .use_urgent_burst_bw = 1, - .num_states = 5 + .num_states = 9 }; #ifndef MAX @@ -1333,26 +1366,78 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param { struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); struct clk_limit_table *clk_table = &bw_params->clk_table; - int i; + unsigned int i, j, k; + int closest_clk_lvl; + + // diags does not retrieve proper values from SMU + // cap states to 5 and make state 5 the max state + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) || IS_DIAG_DC(dc->ctx->dce_environment)) { + dcn2_1_soc.num_states = 5; + + dcn2_1_soc.clock_limits[5].state = 5; + dcn2_1_soc.clock_limits[5].dcfclk_mhz = 810.0; + dcn2_1_soc.clock_limits[5].fabricclk_mhz = 1600.0; + dcn2_1_soc.clock_limits[5].dispclk_mhz = 1395.0; + dcn2_1_soc.clock_limits[5].dppclk_mhz = 1285.0; + dcn2_1_soc.clock_limits[5].phyclk_mhz = 1325.0; + dcn2_1_soc.clock_limits[5].socclk_mhz = 953.0; + dcn2_1_soc.clock_limits[5].dscclk_mhz = 489.0; + dcn2_1_soc.clock_limits[5].dram_speed_mts = 4266.0; + } else { + dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; + dcn2_1_ip.max_num_dpp = pool->base.pipe_count; + dcn2_1_soc.num_chans = bw_params->num_channels; + + /* Vmin: leave lowest DCN clocks, override with dcfclk, fclk, memclk from fuse */ + dcn2_1_soc.clock_limits[0].state = 0; + dcn2_1_soc.clock_limits[0].dcfclk_mhz = clk_table->entries[0].dcfclk_mhz; + dcn2_1_soc.clock_limits[0].fabricclk_mhz = clk_table->entries[0].fclk_mhz; + dcn2_1_soc.clock_limits[0].socclk_mhz = clk_table->entries[0].socclk_mhz; + dcn2_1_soc.clock_limits[0].dram_speed_mts = clk_table->entries[0].memclk_mhz * 2; + + /* + * Other levels: find cloest DCN clocks that fit the given clock limit using dcfclk + * as indicater + */ - dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; - dcn2_1_ip.max_num_dpp = pool->base.pipe_count; - dcn2_1_soc.num_chans = bw_params->num_channels; + closest_clk_lvl = -1; + /* index currently being filled */ + k = 1; + for (i = 1; i < clk_table->num_entries; i++) { + /* loop backwards, skip duplicate state, +1 because SMU has precision issue */ + for (j = dcn2_1_soc.num_states - 2; j >= k; j--) { + if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } - for (i = 0; i < clk_table->num_entries; i++) { + /* if found a lvl that fits, use the DCN clks from it, if not, go to next clk limit*/ + if (closest_clk_lvl != -1) { + dcn2_1_soc.clock_limits[k].state = i; + dcn2_1_soc.clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + dcn2_1_soc.clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + dcn2_1_soc.clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz; + dcn2_1_soc.clock_limits[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + dcn2_1_soc.clock_limits[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + dcn2_1_soc.clock_limits[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + dcn2_1_soc.clock_limits[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + dcn2_1_soc.clock_limits[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + dcn2_1_soc.clock_limits[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + dcn2_1_soc.clock_limits[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + dcn2_1_soc.clock_limits[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + k++; + } + } - dcn2_1_soc.clock_limits[i].state = i; - dcn2_1_soc.clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - dcn2_1_soc.clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn2_1_soc.clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn2_1_soc.clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + /* duplicate last level */ + dcn2_1_soc.clock_limits[k] = dcn2_1_soc.clock_limits[k - 1]; + dcn2_1_soc.clock_limits[k].state = k; + dcn2_1_soc.num_states = k + 1; } - dcn2_1_soc.clock_limits[i] = dcn2_1_soc.clock_limits[i - 1]; - dcn2_1_soc.num_states = i; - // diags does not retrieve proper values from SMU, do not update DML instance for diags - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !IS_DIAG_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); + dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); } /* Temporary Place holder until we can get them from fuse */ -- cgit v1.2.3