diff options
author | Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> | 2020-05-21 12:32:53 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2020-07-01 01:59:14 -0400 |
commit | 4d55b0dd1cdd8535ffd6057f210465575117d807 (patch) | |
tree | fa71c4f5002239f2af3941270bdb519203eba520 /drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | |
parent | be547111d2be16e81dc2d9669cf3caa3675fa55d (diff) | |
download | linux-4d55b0dd1cdd8535ffd6057f210465575117d807.tar.gz linux-4d55b0dd1cdd8535ffd6057f210465575117d807.tar.bz2 linux-4d55b0dd1cdd8535ffd6057f210465575117d807.zip |
drm/amd/display: Add DCN3 CLK_MGR
Adds support for handling of clocking relevant to the DCN3 block
Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 153 |
1 files changed, 146 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index d2ad0504b0de..9cc65dc1970f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1004,16 +1004,58 @@ static bool get_pixel_clk_frequency_100hz( return false; } - +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */ -struct pixel_rate_range_table_entry { - unsigned int range_min_khz; - unsigned int range_max_khz; - unsigned int target_pixel_rate_khz; - unsigned short mult_factor; - unsigned short div_factor; +const struct pixel_rate_range_table_entry video_optimized_pixel_rates[] = { + // /1.001 rates + {25170, 25180, 25200, 1000, 1001}, //25.2MHz -> 25.17 + {59340, 59350, 59400, 1000, 1001}, //59.4Mhz -> 59.340 + {74170, 74180, 74250, 1000, 1001}, //74.25Mhz -> 74.1758 + {125870, 125880, 126000, 1000, 1001}, //126Mhz -> 125.87 + {148350, 148360, 148500, 1000, 1001}, //148.5Mhz -> 148.3516 + {167830, 167840, 168000, 1000, 1001}, //168Mhz -> 167.83 + {222520, 222530, 222750, 1000, 1001}, //222.75Mhz -> 222.527 + {257140, 257150, 257400, 1000, 1001}, //257.4Mhz -> 257.1429 + {296700, 296710, 297000, 1000, 1001}, //297Mhz -> 296.7033 + {342850, 342860, 343200, 1000, 1001}, //343.2Mhz -> 342.857 + {395600, 395610, 396000, 1000, 1001}, //396Mhz -> 395.6 + {409090, 409100, 409500, 1000, 1001}, //409.5Mhz -> 409.091 + {445050, 445060, 445500, 1000, 1001}, //445.5Mhz -> 445.055 + {467530, 467540, 468000, 1000, 1001}, //468Mhz -> 467.5325 + {519230, 519240, 519750, 1000, 1001}, //519.75Mhz -> 519.231 + {525970, 525980, 526500, 1000, 1001}, //526.5Mhz -> 525.974 + {545450, 545460, 546000, 1000, 1001}, //546Mhz -> 545.455 + {593400, 593410, 594000, 1000, 1001}, //594Mhz -> 593.4066 + {623370, 623380, 624000, 1000, 1001}, //624Mhz -> 623.377 + {692300, 692310, 693000, 1000, 1001}, //693Mhz -> 692.308 + {701290, 701300, 702000, 1000, 1001}, //702Mhz -> 701.2987 + {791200, 791210, 792000, 1000, 1001}, //792Mhz -> 791.209 + {890100, 890110, 891000, 1000, 1001}, //891Mhz -> 890.1099 + {1186810, 1186820, 1188000, 1000, 1001},//1188Mhz -> 1186.8131 + + // *1.001 rates + {27020, 27030, 27000, 1001, 1000}, //27Mhz + {54050, 54060, 54000, 1001, 1000}, //54Mhz + {108100, 108110, 108000, 1001, 1000},//108Mhz }; +const struct pixel_rate_range_table_entry *look_up_in_video_optimized_rate_tlb( + unsigned int pixel_rate_khz) +{ + int i; + + for (i = 0; i < NUM_ELEMENTS(video_optimized_pixel_rates); i++) { + const struct pixel_rate_range_table_entry *e = &video_optimized_pixel_rates[i]; + + if (e->range_min_khz <= pixel_rate_khz && pixel_rate_khz <= e->range_max_khz) { + return e; + } + } + + return NULL; +} +#endif + static bool dcn20_program_pix_clk( struct clock_source *clock_source, struct pixel_clk_params *pix_clk_params, @@ -1031,6 +1073,85 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = { .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz }; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +static bool dcn3_program_pix_clk( + struct clock_source *clock_source, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz; + const struct pixel_rate_range_table_entry *e = + look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10); + + // For these signal types Driver to program DP_DTO without calling VBIOS Command table + if (dc_is_dp_signal(pix_clk_params->signal_type)) { + if (e) { + /* Set DTO values: phase = target clock, modulo = reference clock*/ + REG_WRITE(PHASE[inst], e->target_pixel_rate_khz * e->mult_factor); + REG_WRITE(MODULO[inst], dp_dto_ref_khz * e->div_factor); + } else { + /* Set DTO values: phase = target clock, modulo = reference clock*/ + REG_WRITE(PHASE[inst], pll_settings->actual_pix_clk_100hz * 100); + REG_WRITE(MODULO[inst], dp_dto_ref_khz * 1000); + } + REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); + } else + // For other signal types(HDMI_TYPE_A, DVI) Driver still to call VBIOS Command table + dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings); + + return true; +} + +static uint32_t dcn3_get_pix_clk_dividers( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + unsigned long long actual_pix_clk_100Hz = pix_clk_params->requested_pix_clk_100hz; + struct dce110_clk_src *clk_src; + + clk_src = TO_DCE110_CLK_SRC(cs); + DC_LOGGER_INIT(); + + if (pix_clk_params == NULL || pll_settings == NULL + || pix_clk_params->requested_pix_clk_100hz == 0) { + DC_LOG_ERROR( + "%s: Invalid parameters!!\n", __func__); + return -1; + } + + memset(pll_settings, 0, sizeof(*pll_settings)); + /* Adjust for HDMI Type A deep color */ + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 5) >> 2; + break; + case COLOR_DEPTH_121212: + actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 6) >> 2; + break; + case COLOR_DEPTH_161616: + actual_pix_clk_100Hz = actual_pix_clk_100Hz * 2; + break; + default: + break; + } + } + pll_settings->actual_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz; + pll_settings->adjusted_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz; + pll_settings->calculated_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz; + + return 0; +} + +static const struct clock_source_funcs dcn3_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dcn3_program_pix_clk, + .get_pix_clk_dividers = dcn3_get_pix_clk_dividers +}; +#endif /*****************************************/ /* Constructor */ /*****************************************/ @@ -1415,3 +1536,21 @@ bool dcn20_clk_src_construct( return ret; } + +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +bool dcn3_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask); + + clk_src->base.funcs = &dcn3_clk_src_funcs; + + return ret; +} +#endif |