pxl_clk_params.target_pixel_clock = requested_clk_khz;
pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
- if (clk_dce->dfs_bypass_enabled)
+ if (clk_dce->dfs_bypass_active)
pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
- if (clk_dce->dfs_bypass_enabled) {
-
+ if (clk_dce->dfs_bypass_active) {
/* Cache the fixed display clock*/
clk_dce->dfs_bypass_disp_clk =
pxl_clk_params.dfs_bypass_display_clock;
}
}
+static bool dce_update_dfs_bypass(
+ struct dccg *dccg,
+ struct dc *dc,
+ struct dc_state *context,
+ int requested_clock_khz)
+{
+ struct dce_dccg *clk_dce = TO_DCE_CLOCKS(dccg);
+ struct resource_context *res_ctx = &context->res_ctx;
+ enum signal_type signal_type = SIGNAL_TYPE_NONE;
+ bool was_active = clk_dce->dfs_bypass_active;
+ int i;
+
+ /* Disable DFS bypass by default. */
+ clk_dce->dfs_bypass_active = false;
+
+ /* Check that DFS bypass is available. */
+ if (!clk_dce->dfs_bypass_enabled)
+ goto update;
+
+ /* Check if the requested display clock is below the threshold. */
+ if (requested_clock_khz >= 400000)
+ goto update;
+
+ /* DFS-bypass should only be enabled on single stream setups */
+ if (context->stream_count != 1)
+ goto update;
+
+ /* Check that the stream's signal type is an embedded panel */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (res_ctx->pipe_ctx[i].stream) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+ signal_type = pipe_ctx->stream->sink->link->connector_signal;
+ break;
+ }
+ }
+
+ if (signal_type == SIGNAL_TYPE_EDP ||
+ signal_type == SIGNAL_TYPE_LVDS)
+ clk_dce->dfs_bypass_active = true;
+
+update:
+ /* Update the clock state. We don't need to respect safe_to_lower
+ * because DFS bypass should always be greater than the current
+ * display clock frequency.
+ */
+ if (was_active != clk_dce->dfs_bypass_active) {
+ dccg->clks.dispclk_khz =
+ dccg->funcs->set_dispclk(dccg, dccg->clks.dispclk_khz);
+ return true;
+ }
+
+ return false;
+}
+
#ifdef CONFIG_DRM_AMD_DC_DCN1_0
static const struct display_clock_funcs dcn1_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
static const struct display_clock_funcs dce110_funcs = {
.get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
.set_dispclk = dce_psr_set_clock,
- .update_clocks = dce_update_clocks
+ .update_clocks = dce_update_clocks,
+ .update_dfs_bypass = dce_update_dfs_bypass
};
static const struct display_clock_funcs dce_funcs = {
bool decrease_allowed)
{
struct dc_clocks req_clks;
+ struct dccg *dccg = dc->res_pool->dccg;
req_clks.dispclk_khz = context->bw.dce.dispclk_khz;
req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context);
else
dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
- dc->res_pool->dccg->funcs->update_clocks(
- dc->res_pool->dccg,
+ if (dccg->funcs->update_dfs_bypass)
+ dccg->funcs->update_dfs_bypass(
+ dccg,
+ dc,
+ context,
+ req_clks.dispclk_khz);
+
+ dccg->funcs->update_clocks(
+ dccg,
&req_clks,
decrease_allowed);
pplib_apply_display_requirements(dc, context);