|
@@ -255,13 +255,12 @@ static int dce_set_clock(
|
|
|
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;
|
|
@@ -677,6 +676,61 @@ static void dce_update_clocks(struct dccg *dccg,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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,
|
|
@@ -700,7 +754,8 @@ static const struct display_clock_funcs dce112_funcs = {
|
|
|
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 = {
|