summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c63
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h5
4 files changed, 76 insertions, 6 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
index 0782b74624d7..103dc3cf1c43 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
@@ -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 = {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
index 8a6b2d328467..8b5a53e98ad9 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
@@ -78,6 +78,8 @@ struct dce_dccg {
/* Cache the status of DFS-bypass feature*/
bool dfs_bypass_enabled;
+ /* True if the DFS-bypass feature is enabled and active. */
+ bool dfs_bypass_active;
/* Cache the display clock returned by VBIOS if DFS-bypass is enabled.
* This is basically "Crystal Frequency In KHz" (XTALIN) frequency */
int dfs_bypass_disp_clk;
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 14384d9675a8..2f2c5155c5aa 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -2566,6 +2566,7 @@ void dce110_set_bandwidth(
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);
@@ -2575,8 +2576,15 @@ void dce110_set_bandwidth(
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);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
index 3c7ccb68ecdb..689faa16c0ae 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
@@ -53,6 +53,11 @@ struct display_clock_funcs {
int requested_clock_khz);
int (*get_dp_ref_clk_frequency)(struct dccg *dccg);
+
+ bool (*update_dfs_bypass)(struct dccg *dccg,
+ struct dc *dc,
+ struct dc_state *context,
+ int requested_clock_khz);
};
#endif /* __DISPLAY_CLOCK_H__ */