Commit 89e94bc5 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher
Browse files

drm/amd/display: optimize prgoram wm and clks



[Why]
In some display configuration like 1080P monitor playing a 1080P video,
if user use ALT+F4 to exit Movie and TV, there is a chance clocks are
same only water mark changed. Current clock optimization machanism will
result in water mark keeps high after exit Movie and TV app.

[How]
Return if watermark need to be optimized when doing program watermark,
perform the optimization after.

Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c479912a
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -1365,7 +1365,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
	int i;
	struct dc_state *context = dc->current_state;

	if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0)
	if ((!dc->clk_optimized_required && !dc->wm_optimized_required) || dc->optimize_seamless_boot_streams > 0)
		return true;

	post_surface_trace(dc);
@@ -1377,8 +1377,6 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
			dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
		}

	dc->optimized_required = false;

	dc->hwss.optimize_bandwidth(dc, context);
	return true;
}
@@ -1826,10 +1824,10 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
		// If there's an available clock comparator, we use that.
		if (dc->clk_mgr->funcs->are_clock_states_equal) {
			if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk))
				dc->optimized_required = true;
				dc->clk_optimized_required = true;
		// Else we fallback to mem compare.
		} else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
			dc->optimized_required = true;
			dc->clk_optimized_required = true;
		}
	}

@@ -2200,7 +2198,7 @@ static void commit_planes_for_stream(struct dc *dc,
			dc->optimize_seamless_boot_streams--;

			if (dc->optimize_seamless_boot_streams == 0)
				dc->optimized_required = true;
				dc->clk_optimized_required = true;
		}
	}

+2 −1
Original line number Diff line number Diff line
@@ -520,7 +520,8 @@ struct dc {
	struct dce_hwseq *hwseq;

	/* Require to optimize clocks and bandwidth for added/removed planes */
	bool optimized_required;
	bool clk_optimized_required;
	bool wm_optimized_required;

	/* Require to maintain clocks and bandwidth for UEFI enabled HW */
	int optimize_seamless_boot_streams;
+74 −27
Original line number Diff line number Diff line
@@ -243,7 +243,7 @@ void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
			DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
}

void hubbub1_program_urgent_watermarks(
bool hubbub1_program_urgent_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
@@ -251,6 +251,7 @@ void hubbub1_program_urgent_watermarks(
{
	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
	uint32_t prog_wm_value;
	bool wm_pending = false;

	/* Repeat for water mark set A, B, C and D. */
	/* clock state A */
@@ -264,7 +265,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->a.urgent_ns, prog_wm_value);
	}
	} else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub1->watermarks.a.pte_meta_urgent_ns) {
		hubbub1->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
@@ -274,7 +276,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->a.pte_meta_urgent_ns, prog_wm_value);
	}
	} else if (watermarks->a.pte_meta_urgent_ns < hubbub1->watermarks.a.pte_meta_urgent_ns)
		wm_pending = true;

	/* clock state B */
	if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
@@ -287,7 +290,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->b.urgent_ns, prog_wm_value);
	}
	} else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub1->watermarks.b.pte_meta_urgent_ns) {
		hubbub1->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
@@ -297,7 +301,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->b.pte_meta_urgent_ns, prog_wm_value);
	}
	} else if (watermarks->b.pte_meta_urgent_ns < hubbub1->watermarks.b.pte_meta_urgent_ns)
		wm_pending = true;

	/* clock state C */
	if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
@@ -310,7 +315,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->c.urgent_ns, prog_wm_value);
	}
	} else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub1->watermarks.c.pte_meta_urgent_ns) {
		hubbub1->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
@@ -320,7 +326,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->c.pte_meta_urgent_ns, prog_wm_value);
	}
	} else if (watermarks->c.pte_meta_urgent_ns < hubbub1->watermarks.c.pte_meta_urgent_ns)
		wm_pending = true;

	/* clock state D */
	if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
@@ -333,7 +340,8 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->d.urgent_ns, prog_wm_value);
	}
	} else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub1->watermarks.d.pte_meta_urgent_ns) {
		hubbub1->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
@@ -343,10 +351,13 @@ void hubbub1_program_urgent_watermarks(
		DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->d.pte_meta_urgent_ns, prog_wm_value);
	}
	} else if (watermarks->d.pte_meta_urgent_ns < hubbub1->watermarks.d.pte_meta_urgent_ns)
		wm_pending = true;

	return wm_pending;
}

void hubbub1_program_stutter_watermarks(
bool hubbub1_program_stutter_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
@@ -354,6 +365,7 @@ void hubbub1_program_stutter_watermarks(
{
	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
	uint32_t prog_wm_value;
	bool wm_pending = false;

	/* clock state A */
	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
@@ -368,7 +380,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
	}
	} else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
			< hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
			> hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
@@ -382,7 +396,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
	}
	} else if (watermarks->a.cstate_pstate.cstate_exit_ns
			< hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns)
		wm_pending = true;

	/* clock state B */
	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
@@ -397,7 +413,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
	}
	} else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
			< hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
			> hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
@@ -411,7 +429,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
	}
	} else if (watermarks->b.cstate_pstate.cstate_exit_ns
			< hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns)
		wm_pending = true;

	/* clock state C */
	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
@@ -426,7 +446,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
	}
	} else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
			< hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
			> hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
@@ -440,7 +462,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
	}
	} else if (watermarks->c.cstate_pstate.cstate_exit_ns
			< hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns)
		wm_pending = true;

	/* clock state D */
	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
@@ -455,7 +479,9 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
	}
	} else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
			< hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
		wm_pending = true;

	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
			> hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
@@ -469,11 +495,14 @@ void hubbub1_program_stutter_watermarks(
		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
			"HW register value = 0x%x\n",
			watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
	}
	} else if (watermarks->d.cstate_pstate.cstate_exit_ns
			< hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns)
		wm_pending = true;

	return wm_pending;
}

void hubbub1_program_pstate_watermarks(
bool hubbub1_program_pstate_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
@@ -481,6 +510,7 @@ void hubbub1_program_pstate_watermarks(
{
	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
	uint32_t prog_wm_value;
	bool wm_pending = false;

	/* clock state A */
	if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
@@ -495,7 +525,9 @@ void hubbub1_program_pstate_watermarks(
		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
			"HW register value = 0x%x\n\n",
			watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
	}
	} else if (watermarks->a.cstate_pstate.pstate_change_ns
			< hubbub1->watermarks.a.cstate_pstate.pstate_change_ns)
		wm_pending = true;

	/* clock state B */
	if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
@@ -510,7 +542,9 @@ void hubbub1_program_pstate_watermarks(
		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
			"HW register value = 0x%x\n\n",
			watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
	}
	} else if (watermarks->b.cstate_pstate.pstate_change_ns
			< hubbub1->watermarks.b.cstate_pstate.pstate_change_ns)
		wm_pending = true;

	/* clock state C */
	if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
@@ -525,7 +559,9 @@ void hubbub1_program_pstate_watermarks(
		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
			"HW register value = 0x%x\n\n",
			watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
	}
	} else if (watermarks->c.cstate_pstate.pstate_change_ns
			< hubbub1->watermarks.c.cstate_pstate.pstate_change_ns)
		wm_pending = true;

	/* clock state D */
	if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
@@ -540,23 +576,33 @@ void hubbub1_program_pstate_watermarks(
		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
			"HW register value = 0x%x\n\n",
			watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
	}
	} else if (watermarks->d.cstate_pstate.pstate_change_ns
			< hubbub1->watermarks.d.cstate_pstate.pstate_change_ns)
		wm_pending = true;

	return wm_pending;
}

void hubbub1_program_watermarks(
bool hubbub1_program_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
		bool safe_to_lower)
{
	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
	bool wm_pending = false;
	/*
	 * Need to clamp to max of the register values (i.e. no wrap)
	 * for dcn1, all wm registers are 21-bit wide
	 */
	hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
	hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
	hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
	if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
		wm_pending = true;

	if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
		wm_pending = true;

	if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
		wm_pending = true;

	REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
@@ -570,6 +616,7 @@ void hubbub1_program_watermarks(
			DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
			DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
#endif
	return wm_pending;
}

void hubbub1_update_dchub(
+4 −4
Original line number Diff line number Diff line
@@ -308,7 +308,7 @@ bool hubbub1_verify_allow_pstate_change_high(

void hubbub1_wm_change_req_wa(struct hubbub *hubbub);

void hubbub1_program_watermarks(
bool hubbub1_program_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
@@ -331,17 +331,17 @@ void hubbub1_construct(struct hubbub *hubbub,
	const struct dcn_hubbub_shift *hubbub_shift,
	const struct dcn_hubbub_mask *hubbub_mask);

void hubbub1_program_urgent_watermarks(
bool hubbub1_program_urgent_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
		bool safe_to_lower);
void hubbub1_program_stutter_watermarks(
bool hubbub1_program_stutter_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
		bool safe_to_lower);
void hubbub1_program_pstate_watermarks(
bool hubbub1_program_pstate_watermarks(
		struct hubbub *hubbub,
		struct dcn_watermark_set *watermarks,
		unsigned int refclk_mhz,
+22 −11
Original line number Diff line number Diff line
@@ -1048,7 +1048,7 @@ void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
	if (opp != NULL)
		opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;

	dc->optimized_required = true;
	dc->clk_optimized_required = true;

	if (hubp->funcs->hubp_disconnect)
		hubp->funcs->hubp_disconnect(hubp);
@@ -1099,7 +1099,7 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
				false);

	hubp->power_gated = true;
	dc->optimized_required = false; /* We're powering off, no need to optimize */
	dc->clk_optimized_required = false; /* We're powering off, no need to optimize */

	hws->funcs.plane_atomic_power_down(dc,
			pipe_ctx->plane_res.dpp,
@@ -2693,7 +2693,7 @@ void dcn10_prepare_bandwidth(
				false);
	}

	hubbub->funcs->program_watermarks(hubbub,
	dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
			&context->bw_ctx.bw.dcn.watermarks,
			dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
			true);
@@ -2717,19 +2717,30 @@ void dcn10_optimize_bandwidth(
		hws->funcs.verify_allow_pstate_change_high(dc);

	if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
		if (context->stream_count == 0)
		if (context->stream_count == 0) {
			context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;

			dc->clk_mgr->funcs->update_clocks(
					dc->clk_mgr,
					context,
					true);
		} else if (dc->clk_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) {
			dc->clk_mgr->funcs->update_clocks(
								dc->clk_mgr,
								context,
								true);
		}
	}

	if (dc->wm_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) {
		hubbub->funcs->program_watermarks(hubbub,
				&context->bw_ctx.bw.dcn.watermarks,
				dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
				true);
	}

	dc->clk_optimized_required = false;
	dc->wm_optimized_required = false;
	dcn10_stereo_hw_frame_pack_wa(dc, context);

	if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
Loading