xref: /linux/drivers/gpu/drm/amd/display/modules/power/power_psr.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
1*b11107cbSLohita Mudimela // SPDX-License-Identifier: MIT
2*b11107cbSLohita Mudimela //
3*b11107cbSLohita Mudimela // Copyright 2026 Advanced Micro Devices, Inc.
4*b11107cbSLohita Mudimela 
5*b11107cbSLohita Mudimela #include "dm_services.h"
6*b11107cbSLohita Mudimela #include "dc.h"
7*b11107cbSLohita Mudimela #include "mod_power.h"
8*b11107cbSLohita Mudimela #include "core_types.h"
9*b11107cbSLohita Mudimela #include "dmcu.h"
10*b11107cbSLohita Mudimela #include "abm.h"
11*b11107cbSLohita Mudimela #include "power_helpers.h"
12*b11107cbSLohita Mudimela #include "dce/dmub_psr.h"
13*b11107cbSLohita Mudimela #include "dal_asic_id.h"
14*b11107cbSLohita Mudimela #include "link_service.h"
15*b11107cbSLohita Mudimela #include <linux/math.h>
16*b11107cbSLohita Mudimela 
17*b11107cbSLohita Mudimela #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
18*b11107cbSLohita Mudimela #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */
19*b11107cbSLohita Mudimela #include "dc/inc/hw/dmcu.h"
20*b11107cbSLohita Mudimela #include "dc/inc/hw/abm.h"
21*b11107cbSLohita Mudimela #include "dmub_cmd.h"
22*b11107cbSLohita Mudimela 
23*b11107cbSLohita Mudimela #define MOD_POWER_TO_CORE(mod_power)\
24*b11107cbSLohita Mudimela 		container_of(mod_power, struct core_power, mod_public)
25*b11107cbSLohita Mudimela 
26*b11107cbSLohita Mudimela static unsigned int calc_psr_num_static_frames(unsigned int vsync_rate_hz)
27*b11107cbSLohita Mudimela {
28*b11107cbSLohita Mudimela 	/* Initialize fail-safe to 2 static frames. */
29*b11107cbSLohita Mudimela 	unsigned int num_frames_static = 2;
30*b11107cbSLohita Mudimela 
31*b11107cbSLohita Mudimela 	/* Calculate number of frames such that at least 30 ms has passed.
32*b11107cbSLohita Mudimela 	 * Round up to ensure the static period is not shorter than 30 ms.
33*b11107cbSLohita Mudimela 	 */
34*b11107cbSLohita Mudimela 	if (vsync_rate_hz != 0)
35*b11107cbSLohita Mudimela 		num_frames_static = DIV_ROUND_UP(30000 * vsync_rate_hz, 1000000);
36*b11107cbSLohita Mudimela 
37*b11107cbSLohita Mudimela 	return num_frames_static;
38*b11107cbSLohita Mudimela }
39*b11107cbSLohita Mudimela 
40*b11107cbSLohita Mudimela bool mod_power_psr_notify_mode_change(struct mod_power *mod_power,
41*b11107cbSLohita Mudimela 	const struct dc_stream_state *stream,
42*b11107cbSLohita Mudimela 	struct dc_link *link,
43*b11107cbSLohita Mudimela 	unsigned int stream_index)
44*b11107cbSLohita Mudimela {
45*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
46*b11107cbSLohita Mudimela 	struct dc *dc = NULL;
47*b11107cbSLohita Mudimela 	struct psr_config psr_config = {0};
48*b11107cbSLohita Mudimela 	struct psr_context psr_context = {0};
49*b11107cbSLohita Mudimela 	int active_psr_events = 0;
50*b11107cbSLohita Mudimela 
51*b11107cbSLohita Mudimela 	if ((mod_power == NULL) || (stream == NULL) || (link == NULL))
52*b11107cbSLohita Mudimela 		return false;
53*b11107cbSLohita Mudimela 
54*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
55*b11107cbSLohita Mudimela 	dc = core_power->dc;
56*b11107cbSLohita Mudimela 
57*b11107cbSLohita Mudimela 	// NO num_entities check here - already validated by caller
58*b11107cbSLohita Mudimela 	// stream_index is passed as validated parameter
59*b11107cbSLohita Mudimela 	active_psr_events = core_power->map[stream_index].psr_events;
60*b11107cbSLohita Mudimela 
61*b11107cbSLohita Mudimela 	/* Calculate PSR configurations */
62*b11107cbSLohita Mudimela 	mod_power_calc_psr_configs(&psr_config, link, stream);
63*b11107cbSLohita Mudimela 
64*b11107cbSLohita Mudimela 	psr_config.psr_exit_link_training_required =
65*b11107cbSLohita Mudimela 			core_power->map[stream_index].caps->psr_exit_link_training_required;
66*b11107cbSLohita Mudimela 	if (dc->ctx->asic_id.chip_family >= AMDGPU_FAMILY_GC_11_0_1)
67*b11107cbSLohita Mudimela 		psr_config.allow_smu_optimizations =
68*b11107cbSLohita Mudimela 				core_power->psr_smu_optimizations_support && dc_is_embedded_signal(stream->signal);
69*b11107cbSLohita Mudimela 	else
70*b11107cbSLohita Mudimela 		psr_config.allow_smu_optimizations =
71*b11107cbSLohita Mudimela 				core_power->psr_smu_optimizations_support &&
72*b11107cbSLohita Mudimela 				mod_power_only_edp(dc->current_state, stream);
73*b11107cbSLohita Mudimela 
74*b11107cbSLohita Mudimela 	psr_config.allow_multi_disp_optimizations = core_power->multi_disp_optimizations_support;
75*b11107cbSLohita Mudimela 
76*b11107cbSLohita Mudimela 	psr_config.rate_control_caps = core_power->map[stream_index].caps->rate_control_caps;
77*b11107cbSLohita Mudimela 
78*b11107cbSLohita Mudimela 	if (active_psr_events & psr_event_os_request_force_ffu)
79*b11107cbSLohita Mudimela 		psr_config.os_request_force_ffu = true;
80*b11107cbSLohita Mudimela 
81*b11107cbSLohita Mudimela 	/*
82*b11107cbSLohita Mudimela 	 * DSC support:
83*b11107cbSLohita Mudimela 	 * DSC slice height value must be 'mod' by su_y_granularity.
84*b11107cbSLohita Mudimela 	 * According to Panel Vendor, there might be varied conditions to fulfill.
85*b11107cbSLohita Mudimela 	 * Right now, DSC slice height value must be multiple of su_y_granularity.
86*b11107cbSLohita Mudimela 	 *
87*b11107cbSLohita Mudimela 	 * The value of DSC slice height is determined in DSC Driver but it does not
88*b11107cbSLohita Mudimela 	 * propagated out here, so we need to calculate it as below 'slice_height'.
89*b11107cbSLohita Mudimela 	 */
90*b11107cbSLohita Mudimela 	psr_su_set_dsc_slice_height(dc, link,
91*b11107cbSLohita Mudimela 				(struct dc_stream_state *) stream,
92*b11107cbSLohita Mudimela 				&psr_config);
93*b11107cbSLohita Mudimela 
94*b11107cbSLohita Mudimela 	dc_link_setup_psr(link, stream, &psr_config, &psr_context);
95*b11107cbSLohita Mudimela 
96*b11107cbSLohita Mudimela 	return true;
97*b11107cbSLohita Mudimela }
98*b11107cbSLohita Mudimela 
99*b11107cbSLohita Mudimela static void mod_power_psr_set_power_opt(struct mod_power *mod_power,
100*b11107cbSLohita Mudimela 	struct dc_stream_state *stream,
101*b11107cbSLohita Mudimela 	unsigned int active_psr_events,
102*b11107cbSLohita Mudimela 	bool psr_enable_request)
103*b11107cbSLohita Mudimela {
104*b11107cbSLohita Mudimela 	(void)psr_enable_request;
105*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
106*b11107cbSLohita Mudimela 	struct dc_link *link = NULL;
107*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
108*b11107cbSLohita Mudimela 	unsigned int power_opt = 0;
109*b11107cbSLohita Mudimela 
110*b11107cbSLohita Mudimela 	if (!stream)
111*b11107cbSLohita Mudimela 		return;
112*b11107cbSLohita Mudimela 
113*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
114*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
115*b11107cbSLohita Mudimela 	if (!core_power->map[stream_index].caps->psr_version)
116*b11107cbSLohita Mudimela 		return;
117*b11107cbSLohita Mudimela 
118*b11107cbSLohita Mudimela 	link = dc_stream_get_link(stream);
119*b11107cbSLohita Mudimela 
120*b11107cbSLohita Mudimela 	if (active_psr_events == 0) {
121*b11107cbSLohita Mudimela 		/* Static Screen */
122*b11107cbSLohita Mudimela 		power_opt |= (psr_power_opt_smu_opt_static_screen | psr_power_opt_z10_static_screen |
123*b11107cbSLohita Mudimela 					psr_power_opt_ds_disable_allow);
124*b11107cbSLohita Mudimela 	}
125*b11107cbSLohita Mudimela 
126*b11107cbSLohita Mudimela 	/* psr_power_opt_flag is a configuration parameter into the module that determines
127*b11107cbSLohita Mudimela 	 * which optimizations to enable during psr
128*b11107cbSLohita Mudimela 	 */
129*b11107cbSLohita Mudimela 	power_opt &= core_power->map[stream_index].caps->psr_power_opt_flag;
130*b11107cbSLohita Mudimela 	if (core_power->map[stream_index].psr_power_opt != power_opt) {
131*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
132*b11107cbSLohita Mudimela 				WPP_BIT_FLAG_Firmware_PsrState,
133*b11107cbSLohita Mudimela 				"mod_power set_power_opt: psr_power_opt=0x%04x, power_opt=0x%04x active_psr_events=0x%04x, psr_power_opt_flag=0x%04x",
134*b11107cbSLohita Mudimela 				core_power->map[stream_index].psr_power_opt,
135*b11107cbSLohita Mudimela 				power_opt,
136*b11107cbSLohita Mudimela 				active_psr_events,
137*b11107cbSLohita Mudimela 				core_power->map[stream_index].caps->psr_power_opt_flag);
138*b11107cbSLohita Mudimela 		dc_link_set_psr_allow_active(link, NULL, false, false, &power_opt);
139*b11107cbSLohita Mudimela 		core_power->map[stream_index].psr_power_opt = power_opt;
140*b11107cbSLohita Mudimela 	}
141*b11107cbSLohita Mudimela }
142*b11107cbSLohita Mudimela 
143*b11107cbSLohita Mudimela static bool set_psr_enable(struct mod_power *mod_power,
144*b11107cbSLohita Mudimela 		struct dc_stream_state *stream,
145*b11107cbSLohita Mudimela 		bool psr_enable,
146*b11107cbSLohita Mudimela 		bool wait,
147*b11107cbSLohita Mudimela 		bool force_static)
148*b11107cbSLohita Mudimela {
149*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
150*b11107cbSLohita Mudimela 	enum dc_psr_state state = PSR_STATE0;
151*b11107cbSLohita Mudimela 	unsigned int retry_count;
152*b11107cbSLohita Mudimela 	const unsigned int max_retry = 1000;
153*b11107cbSLohita Mudimela 	struct dc_link *link = NULL;
154*b11107cbSLohita Mudimela 
155*b11107cbSLohita Mudimela 	if (mod_power == NULL)
156*b11107cbSLohita Mudimela 		return false;
157*b11107cbSLohita Mudimela 
158*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
159*b11107cbSLohita Mudimela 
160*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0) {
161*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
162*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
163*b11107cbSLohita Mudimela 							"set psr enable: ERROR: stream=%p num_entities=%u",
164*b11107cbSLohita Mudimela 							stream,
165*b11107cbSLohita Mudimela 							core_power->num_entities);
166*b11107cbSLohita Mudimela 		return false;
167*b11107cbSLohita Mudimela 	}
168*b11107cbSLohita Mudimela 
169*b11107cbSLohita Mudimela 	if (psr_enable)	{
170*b11107cbSLohita Mudimela 		unsigned int vsync_rate_hz;
171*b11107cbSLohita Mudimela 		struct dc_static_screen_params params = {0};
172*b11107cbSLohita Mudimela 
173*b11107cbSLohita Mudimela 		vsync_rate_hz = (unsigned int)div_u64(div_u64((
174*b11107cbSLohita Mudimela 				stream->timing.pix_clk_100hz * 100),
175*b11107cbSLohita Mudimela 				stream->timing.v_total),
176*b11107cbSLohita Mudimela 				stream->timing.h_total);
177*b11107cbSLohita Mudimela 
178*b11107cbSLohita Mudimela 		params.triggers.cursor_update = true;
179*b11107cbSLohita Mudimela 		params.triggers.overlay_update = true;
180*b11107cbSLohita Mudimela 		params.triggers.surface_update = true;
181*b11107cbSLohita Mudimela 		params.num_frames = calc_psr_num_static_frames(vsync_rate_hz);
182*b11107cbSLohita Mudimela 
183*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
184*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
185*b11107cbSLohita Mudimela 							"set psr enable: CALCS: pix_clk_100hz=%u v_total=%u h_total=%u vsync_rate_hz=%u num_frames=%u",
186*b11107cbSLohita Mudimela 							stream->timing.pix_clk_100hz,
187*b11107cbSLohita Mudimela 							stream->timing.v_total,
188*b11107cbSLohita Mudimela 							stream->timing.h_total,
189*b11107cbSLohita Mudimela 							vsync_rate_hz,
190*b11107cbSLohita Mudimela 							params.num_frames);
191*b11107cbSLohita Mudimela 
192*b11107cbSLohita Mudimela 		dc_stream_set_static_screen_params(core_power->dc,
193*b11107cbSLohita Mudimela 						   &stream, 1,
194*b11107cbSLohita Mudimela 						   &params);
195*b11107cbSLohita Mudimela 	}
196*b11107cbSLohita Mudimela 
197*b11107cbSLohita Mudimela 	link = dc_stream_get_link(stream);
198*b11107cbSLohita Mudimela 
199*b11107cbSLohita Mudimela 	if (!dc_link_set_psr_allow_active(link, &psr_enable, false, force_static, NULL)) {
200*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
201*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
202*b11107cbSLohita Mudimela 							"set psr enable: ERROR: stream=%p link=%p psr_enable=%d",
203*b11107cbSLohita Mudimela 							stream,
204*b11107cbSLohita Mudimela 							link,
205*b11107cbSLohita Mudimela 							psr_enable);
206*b11107cbSLohita Mudimela 		return false;
207*b11107cbSLohita Mudimela 	}
208*b11107cbSLohita Mudimela 
209*b11107cbSLohita Mudimela 	if (wait == true) {
210*b11107cbSLohita Mudimela 
211*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
212*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
213*b11107cbSLohita Mudimela 							"set psr enable: BEGIN WAIT: psr_enable=%d",
214*b11107cbSLohita Mudimela 							(int)psr_enable);
215*b11107cbSLohita Mudimela 
216*b11107cbSLohita Mudimela 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
217*b11107cbSLohita Mudimela 			dc_link_get_psr_state(link, &state);
218*b11107cbSLohita Mudimela 			if (psr_enable) {
219*b11107cbSLohita Mudimela 				if (state != PSR_STATE0 &&
220*b11107cbSLohita Mudimela 						(!force_static || state == PSR_STATE3))
221*b11107cbSLohita Mudimela 					break;
222*b11107cbSLohita Mudimela 			} else {
223*b11107cbSLohita Mudimela 				if (state == PSR_STATE0)
224*b11107cbSLohita Mudimela 					break;
225*b11107cbSLohita Mudimela 			}
226*b11107cbSLohita Mudimela 			udelay(500);
227*b11107cbSLohita Mudimela 		}
228*b11107cbSLohita Mudimela 
229*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
230*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
231*b11107cbSLohita Mudimela 							"set psr enable: END WAIT: psr_enable=%d",
232*b11107cbSLohita Mudimela 							(int)psr_enable);
233*b11107cbSLohita Mudimela 
234*b11107cbSLohita Mudimela 		/* assert if max retry hit */
235*b11107cbSLohita Mudimela 		if (retry_count >= max_retry) {
236*b11107cbSLohita Mudimela 			ASSERT(0);
237*b11107cbSLohita Mudimela 			DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
238*b11107cbSLohita Mudimela 								WPP_BIT_FLAG_Firmware_PsrState,
239*b11107cbSLohita Mudimela 								"set psr enable: ERROR: retry_count=%u: Unexpectedly long wait for PSR state change.",
240*b11107cbSLohita Mudimela 								retry_count);
241*b11107cbSLohita Mudimela 		}
242*b11107cbSLohita Mudimela 	} else {
243*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
244*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
245*b11107cbSLohita Mudimela 							"set psr enable: PSR state change initiated (wait=false): psr_enable=%d",
246*b11107cbSLohita Mudimela 							(int)psr_enable);
247*b11107cbSLohita Mudimela 	}
248*b11107cbSLohita Mudimela 
249*b11107cbSLohita Mudimela 	return true;
250*b11107cbSLohita Mudimela }
251*b11107cbSLohita Mudimela 
252*b11107cbSLohita Mudimela bool mod_power_get_psr_event(struct mod_power *mod_power,
253*b11107cbSLohita Mudimela 			struct dc_stream_state *stream,
254*b11107cbSLohita Mudimela 			unsigned int *active_psr_events)
255*b11107cbSLohita Mudimela {
256*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
257*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
258*b11107cbSLohita Mudimela 
259*b11107cbSLohita Mudimela 	if (mod_power == NULL)
260*b11107cbSLohita Mudimela 		return false;
261*b11107cbSLohita Mudimela 
262*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
263*b11107cbSLohita Mudimela 
264*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
265*b11107cbSLohita Mudimela 		return false;
266*b11107cbSLohita Mudimela 
267*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
268*b11107cbSLohita Mudimela 
269*b11107cbSLohita Mudimela 	if (!core_power->map[stream_index].caps->psr_version)
270*b11107cbSLohita Mudimela 		return false;
271*b11107cbSLohita Mudimela 
272*b11107cbSLohita Mudimela 	*active_psr_events = core_power->map[stream_index].psr_events;
273*b11107cbSLohita Mudimela 
274*b11107cbSLohita Mudimela 	return true;
275*b11107cbSLohita Mudimela }
276*b11107cbSLohita Mudimela 
277*b11107cbSLohita Mudimela bool mod_power_set_psr_event(struct mod_power *mod_power,
278*b11107cbSLohita Mudimela 		struct dc_stream_state *stream, bool set_event,
279*b11107cbSLohita Mudimela 		enum psr_event event, bool wait)
280*b11107cbSLohita Mudimela {
281*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
282*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
283*b11107cbSLohita Mudimela 	unsigned int active_psr_events = 0;
284*b11107cbSLohita Mudimela 	bool psr_enable_request = false;
285*b11107cbSLohita Mudimela 	bool force_static = false;
286*b11107cbSLohita Mudimela 
287*b11107cbSLohita Mudimela 	if (mod_power == NULL || stream == NULL)
288*b11107cbSLohita Mudimela 		return false;
289*b11107cbSLohita Mudimela 
290*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
291*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
292*b11107cbSLohita Mudimela 
293*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0) {
294*b11107cbSLohita Mudimela 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
295*b11107cbSLohita Mudimela 							WPP_BIT_FLAG_Firmware_PsrState,
296*b11107cbSLohita Mudimela 							"mod_power set_psr_event: ERROR: stream=%p event=%d num_entities=%u",
297*b11107cbSLohita Mudimela 							stream,
298*b11107cbSLohita Mudimela 							(int)event,
299*b11107cbSLohita Mudimela 							core_power->num_entities);
300*b11107cbSLohita Mudimela 		return false;
301*b11107cbSLohita Mudimela 	}
302*b11107cbSLohita Mudimela 
303*b11107cbSLohita Mudimela 	if (!core_power->map[stream_index].caps->psr_version)
304*b11107cbSLohita Mudimela 		return false;
305*b11107cbSLohita Mudimela 
306*b11107cbSLohita Mudimela 	if (set_event)
307*b11107cbSLohita Mudimela 		core_power->map[stream_index].psr_events |= event;
308*b11107cbSLohita Mudimela 	else
309*b11107cbSLohita Mudimela 		core_power->map[stream_index].psr_events &= ~event;
310*b11107cbSLohita Mudimela 
311*b11107cbSLohita Mudimela 	active_psr_events = core_power->map[stream_index].psr_events;
312*b11107cbSLohita Mudimela 
313*b11107cbSLohita Mudimela 	// ignore other events when we're in forced psr enabled state
314*b11107cbSLohita Mudimela 	if (active_psr_events & psr_event_dynamic_display_switch &&
315*b11107cbSLohita Mudimela 			event != psr_event_dynamic_display_switch)
316*b11107cbSLohita Mudimela 		return false;
317*b11107cbSLohita Mudimela 
318*b11107cbSLohita Mudimela 	// ignore other events when we're in forced psr enabled state
319*b11107cbSLohita Mudimela 	if (active_psr_events & psr_event_os_override_hold &&
320*b11107cbSLohita Mudimela 			event != psr_event_os_override_hold)
321*b11107cbSLohita Mudimela 		return false;
322*b11107cbSLohita Mudimela 
323*b11107cbSLohita Mudimela 	// ignore other events when we're in forced psr enabled state
324*b11107cbSLohita Mudimela 	// dds events need to be processed while in dynamic_link_rate_control
325*b11107cbSLohita Mudimela 	if (active_psr_events & psr_event_dynamic_link_rate_control &&
326*b11107cbSLohita Mudimela 			event != psr_event_dynamic_link_rate_control &&
327*b11107cbSLohita Mudimela 			event != psr_event_dds_defer_stream_enable &&
328*b11107cbSLohita Mudimela 			event != psr_event_dynamic_display_switch)
329*b11107cbSLohita Mudimela 		return false;
330*b11107cbSLohita Mudimela 
331*b11107cbSLohita Mudimela 	if (active_psr_events & (psr_event_test_harness_disable_psr | psr_event_os_request_disable))
332*b11107cbSLohita Mudimela 		psr_enable_request = false;
333*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_pause)
334*b11107cbSLohita Mudimela 		psr_enable_request = false;
335*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_test_harness_enable_psr)
336*b11107cbSLohita Mudimela 		psr_enable_request = true;
337*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_dynamic_display_switch) {
338*b11107cbSLohita Mudimela 		psr_enable_request = true;
339*b11107cbSLohita Mudimela 		force_static = true;
340*b11107cbSLohita Mudimela 	} else if (active_psr_events & psr_event_dynamic_link_rate_control) {
341*b11107cbSLohita Mudimela 		psr_enable_request = true;
342*b11107cbSLohita Mudimela 		force_static = true;
343*b11107cbSLohita Mudimela 	} else if (active_psr_events & psr_event_edp_panel_off_disable_psr)
344*b11107cbSLohita Mudimela 		psr_enable_request = false;
345*b11107cbSLohita Mudimela 	else if (active_psr_events & (psr_event_hw_programming |
346*b11107cbSLohita Mudimela 			psr_event_defer_enable |
347*b11107cbSLohita Mudimela 			psr_event_dds_defer_stream_enable |
348*b11107cbSLohita Mudimela 			psr_event_vrr_transition |
349*b11107cbSLohita Mudimela 			psr_event_immediate_flip))
350*b11107cbSLohita Mudimela 		psr_enable_request = false;
351*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_big_screen_video)
352*b11107cbSLohita Mudimela 		psr_enable_request = true;
353*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_full_screen)
354*b11107cbSLohita Mudimela 		psr_enable_request = false;
355*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_mpo_video_selective_update)
356*b11107cbSLohita Mudimela 		psr_enable_request = true;
357*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_vsync)
358*b11107cbSLohita Mudimela 		psr_enable_request = false;
359*b11107cbSLohita Mudimela 	else if (active_psr_events & psr_event_crc_window_active)
360*b11107cbSLohita Mudimela 		psr_enable_request = false;
361*b11107cbSLohita Mudimela 	else
362*b11107cbSLohita Mudimela 		psr_enable_request = true;
363*b11107cbSLohita Mudimela 
364*b11107cbSLohita Mudimela 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
365*b11107cbSLohita Mudimela 						WPP_BIT_FLAG_Firmware_PsrState,
366*b11107cbSLohita Mudimela 						"mod_power set_psr_event: before: psr_enabled=%d -> request: set_event=%d event=0x%04x -> result: psr_events=0x%04x psr_enable_request=%d",
367*b11107cbSLohita Mudimela 						(int)core_power->map[stream_index].psr_enabled,
368*b11107cbSLohita Mudimela 						(int)set_event,
369*b11107cbSLohita Mudimela 						(unsigned int)event,
370*b11107cbSLohita Mudimela 						(unsigned int)core_power->map[stream_index].psr_events,
371*b11107cbSLohita Mudimela 						(int)psr_enable_request);
372*b11107cbSLohita Mudimela 	mod_power_psr_set_power_opt(mod_power, stream, active_psr_events, psr_enable_request);
373*b11107cbSLohita Mudimela 
374*b11107cbSLohita Mudimela 	if (core_power->map[stream_index].psr_enabled != psr_enable_request || force_static) {
375*b11107cbSLohita Mudimela 		if (set_psr_enable(mod_power, stream, psr_enable_request, wait, force_static))
376*b11107cbSLohita Mudimela 			core_power->map[stream_index].psr_enabled = psr_enable_request;
377*b11107cbSLohita Mudimela 	}
378*b11107cbSLohita Mudimela 
379*b11107cbSLohita Mudimela 	return true;
380*b11107cbSLohita Mudimela }
381*b11107cbSLohita Mudimela 
382*b11107cbSLohita Mudimela bool mod_power_get_psr_state(struct mod_power *mod_power,
383*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream,
384*b11107cbSLohita Mudimela 		enum dc_psr_state *state)
385*b11107cbSLohita Mudimela {
386*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
387*b11107cbSLohita Mudimela 	const struct dc_link *link = NULL;
388*b11107cbSLohita Mudimela 
389*b11107cbSLohita Mudimela 	if (!stream)
390*b11107cbSLohita Mudimela 		return false;
391*b11107cbSLohita Mudimela 
392*b11107cbSLohita Mudimela 	if (mod_power == NULL)
393*b11107cbSLohita Mudimela 		return false;
394*b11107cbSLohita Mudimela 
395*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
396*b11107cbSLohita Mudimela 
397*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
398*b11107cbSLohita Mudimela 		return false;
399*b11107cbSLohita Mudimela 
400*b11107cbSLohita Mudimela 	link = dc_stream_get_link(stream);
401*b11107cbSLohita Mudimela 	return dc_link_get_psr_state(link, state);
402*b11107cbSLohita Mudimela }
403*b11107cbSLohita Mudimela 
404*b11107cbSLohita Mudimela bool mod_power_get_psr_enabled_status(struct mod_power *mod_power,
405*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream,
406*b11107cbSLohita Mudimela 		bool *psr_enabled)
407*b11107cbSLohita Mudimela {
408*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
409*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
410*b11107cbSLohita Mudimela 
411*b11107cbSLohita Mudimela 	if (mod_power == NULL)
412*b11107cbSLohita Mudimela 		return false;
413*b11107cbSLohita Mudimela 
414*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
415*b11107cbSLohita Mudimela 
416*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
417*b11107cbSLohita Mudimela 		return false;
418*b11107cbSLohita Mudimela 
419*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
420*b11107cbSLohita Mudimela 
421*b11107cbSLohita Mudimela 	if (!core_power->map[stream_index].caps->psr_version)
422*b11107cbSLohita Mudimela 		return false;
423*b11107cbSLohita Mudimela 
424*b11107cbSLohita Mudimela 	*psr_enabled = core_power->map[stream_index].psr_enabled;
425*b11107cbSLohita Mudimela 
426*b11107cbSLohita Mudimela 	return true;
427*b11107cbSLohita Mudimela }
428*b11107cbSLohita Mudimela 
429*b11107cbSLohita Mudimela void mod_power_psr_residency(struct mod_power *mod_power,
430*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream,
431*b11107cbSLohita Mudimela 		unsigned int *residency,
432*b11107cbSLohita Mudimela 		const uint8_t mode)
433*b11107cbSLohita Mudimela {
434*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
435*b11107cbSLohita Mudimela 	const struct dc_link *link = NULL;
436*b11107cbSLohita Mudimela 
437*b11107cbSLohita Mudimela 	if (!stream)
438*b11107cbSLohita Mudimela 		return;
439*b11107cbSLohita Mudimela 
440*b11107cbSLohita Mudimela 	if (mod_power == NULL)
441*b11107cbSLohita Mudimela 		return;
442*b11107cbSLohita Mudimela 
443*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
444*b11107cbSLohita Mudimela 
445*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
446*b11107cbSLohita Mudimela 		return;
447*b11107cbSLohita Mudimela 
448*b11107cbSLohita Mudimela 	link = dc_stream_get_link(stream);
449*b11107cbSLohita Mudimela 
450*b11107cbSLohita Mudimela 	if (link != NULL)
451*b11107cbSLohita Mudimela 		link->dc->link_srv->edp_get_psr_residency(link, residency, mode);
452*b11107cbSLohita Mudimela }
453*b11107cbSLohita Mudimela bool mod_power_psr_get_active_psr_events(struct mod_power *mod_power,
454*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream, unsigned int *active_psr_events)
455*b11107cbSLohita Mudimela {
456*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
457*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
458*b11107cbSLohita Mudimela 
459*b11107cbSLohita Mudimela 	if (!stream)
460*b11107cbSLohita Mudimela 		return false;
461*b11107cbSLohita Mudimela 
462*b11107cbSLohita Mudimela 	if (mod_power == NULL)
463*b11107cbSLohita Mudimela 		return false;
464*b11107cbSLohita Mudimela 
465*b11107cbSLohita Mudimela 	if (active_psr_events == NULL)
466*b11107cbSLohita Mudimela 		return false;
467*b11107cbSLohita Mudimela 
468*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
469*b11107cbSLohita Mudimela 
470*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
471*b11107cbSLohita Mudimela 		return false;
472*b11107cbSLohita Mudimela 
473*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
474*b11107cbSLohita Mudimela 
475*b11107cbSLohita Mudimela 	*active_psr_events = core_power->map[stream_index].psr_events;
476*b11107cbSLohita Mudimela 	return true;
477*b11107cbSLohita Mudimela }
478*b11107cbSLohita Mudimela 
479*b11107cbSLohita Mudimela bool mod_power_psr_set_sink_vtotal_in_psr_active(struct mod_power *mod_power,
480*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream,
481*b11107cbSLohita Mudimela 		uint16_t psr_vtotal_idle,
482*b11107cbSLohita Mudimela 		uint16_t psr_vtotal_su)
483*b11107cbSLohita Mudimela {
484*b11107cbSLohita Mudimela 	struct core_power *core_power = NULL;
485*b11107cbSLohita Mudimela 	unsigned int stream_index = 0;
486*b11107cbSLohita Mudimela 	const struct dc_link *link = NULL;
487*b11107cbSLohita Mudimela 
488*b11107cbSLohita Mudimela 	if (!stream)
489*b11107cbSLohita Mudimela 		return false;
490*b11107cbSLohita Mudimela 
491*b11107cbSLohita Mudimela 	if (mod_power == NULL)
492*b11107cbSLohita Mudimela 		return false;
493*b11107cbSLohita Mudimela 
494*b11107cbSLohita Mudimela 	core_power = MOD_POWER_TO_CORE(mod_power);
495*b11107cbSLohita Mudimela 
496*b11107cbSLohita Mudimela 	if (core_power->num_entities == 0)
497*b11107cbSLohita Mudimela 		return false;
498*b11107cbSLohita Mudimela 
499*b11107cbSLohita Mudimela 	stream_index = map_index_from_stream(core_power, stream);
500*b11107cbSLohita Mudimela 
501*b11107cbSLohita Mudimela 	if (!core_power->map[stream_index].caps->psr_version)
502*b11107cbSLohita Mudimela 		return false;
503*b11107cbSLohita Mudimela 
504*b11107cbSLohita Mudimela 	link = dc_stream_get_link(stream);
505*b11107cbSLohita Mudimela 
506*b11107cbSLohita Mudimela 	return link->dc->link_srv->edp_set_sink_vtotal_in_psr_active(
507*b11107cbSLohita Mudimela 			link, psr_vtotal_idle, psr_vtotal_su);
508*b11107cbSLohita Mudimela }
509*b11107cbSLohita Mudimela /*
510*b11107cbSLohita Mudimela  * is_psr_su_specific_panel() - check if sink is AMD vendor-specific PSR-SU
511*b11107cbSLohita Mudimela  * supported eDP device.
512*b11107cbSLohita Mudimela  *
513*b11107cbSLohita Mudimela  * @link: dc link pointer
514*b11107cbSLohita Mudimela  *
515*b11107cbSLohita Mudimela  * Return: true if AMDGPU vendor specific PSR-SU eDP panel
516*b11107cbSLohita Mudimela  */
517*b11107cbSLohita Mudimela bool is_psr_su_specific_panel(struct dc_link *link)
518*b11107cbSLohita Mudimela {
519*b11107cbSLohita Mudimela 	bool isPSRSUSupported = false;
520*b11107cbSLohita Mudimela 	struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
521*b11107cbSLohita Mudimela 
522*b11107cbSLohita Mudimela 	if (dpcd_caps->edp_rev >= DP_EDP_14) {
523*b11107cbSLohita Mudimela 		if (dpcd_caps->psr_info.psr_version >= DP_PSR2_WITH_Y_COORD_ET_SUPPORTED)
524*b11107cbSLohita Mudimela 			isPSRSUSupported = true;
525*b11107cbSLohita Mudimela 		/*
526*b11107cbSLohita Mudimela 		 * Some panels will report PSR capabilities over additional DPCD bits.
527*b11107cbSLohita Mudimela 		 * Such panels are approved despite reporting only PSR v3, as long as
528*b11107cbSLohita Mudimela 		 * the additional bits are reported.
529*b11107cbSLohita Mudimela 		 */
530*b11107cbSLohita Mudimela 		if (dpcd_caps->sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) {
531*b11107cbSLohita Mudimela 			/*
532*b11107cbSLohita Mudimela 			 * This is the temporary workaround to disable PSRSU when system turned on
533*b11107cbSLohita Mudimela 			 * DSC function on the sepcific sink.
534*b11107cbSLohita Mudimela 			 */
535*b11107cbSLohita Mudimela 			if (dpcd_caps->psr_info.psr_version < DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)
536*b11107cbSLohita Mudimela 				isPSRSUSupported = false;
537*b11107cbSLohita Mudimela 			else if (dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
538*b11107cbSLohita Mudimela 				((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) ||
539*b11107cbSLohita Mudimela 				(dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07)))
540*b11107cbSLohita Mudimela 				isPSRSUSupported = false;
541*b11107cbSLohita Mudimela 			else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03)
542*b11107cbSLohita Mudimela 				isPSRSUSupported = false;
543*b11107cbSLohita Mudimela 			else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x01)
544*b11107cbSLohita Mudimela 				isPSRSUSupported = false;
545*b11107cbSLohita Mudimela 			else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1)
546*b11107cbSLohita Mudimela 				isPSRSUSupported = true;
547*b11107cbSLohita Mudimela 		}
548*b11107cbSLohita Mudimela 	}
549*b11107cbSLohita Mudimela 
550*b11107cbSLohita Mudimela 	return isPSRSUSupported;
551*b11107cbSLohita Mudimela }
552*b11107cbSLohita Mudimela 
553*b11107cbSLohita Mudimela /**
554*b11107cbSLohita Mudimela  * mod_power_calc_psr_configs() - calculate/update generic psr configuration fields.
555*b11107cbSLohita Mudimela  * @psr_config: [output], psr configuration structure to be updated
556*b11107cbSLohita Mudimela  * @link: [input] dc link pointer
557*b11107cbSLohita Mudimela  * @stream: [input] dc stream state pointer
558*b11107cbSLohita Mudimela  *
559*b11107cbSLohita Mudimela  * calculate and update the psr configuration fields that are not DM specific, i.e. such
560*b11107cbSLohita Mudimela  * fields which are based on DPCD caps or timing information. To setup PSR in DMUB FW,
561*b11107cbSLohita Mudimela  * this helper is assumed to be called before the call of the DC helper dc_link_setup_psr().
562*b11107cbSLohita Mudimela  *
563*b11107cbSLohita Mudimela  * PSR config fields to be updated within the helper:
564*b11107cbSLohita Mudimela  * - psr_rfb_setup_time
565*b11107cbSLohita Mudimela  * - psr_sdp_transmit_line_num_deadline
566*b11107cbSLohita Mudimela  * - line_time_in_us
567*b11107cbSLohita Mudimela  * - su_y_granularity
568*b11107cbSLohita Mudimela  * - su_granularity_required
569*b11107cbSLohita Mudimela  * - psr_frame_capture_indication_req
570*b11107cbSLohita Mudimela  * - psr_exit_link_training_required
571*b11107cbSLohita Mudimela  *
572*b11107cbSLohita Mudimela  * PSR config fields that are DM specific and NOT updated within the helper:
573*b11107cbSLohita Mudimela  * - allow_smu_optimizations
574*b11107cbSLohita Mudimela  * - allow_multi_disp_optimizations
575*b11107cbSLohita Mudimela  */
576*b11107cbSLohita Mudimela void mod_power_calc_psr_configs(struct psr_config *psr_config,
577*b11107cbSLohita Mudimela 		struct dc_link *link,
578*b11107cbSLohita Mudimela 		const struct dc_stream_state *stream)
579*b11107cbSLohita Mudimela {
580*b11107cbSLohita Mudimela 	unsigned int num_vblank_lines = 0;
581*b11107cbSLohita Mudimela 	unsigned int vblank_time_in_us = 0;
582*b11107cbSLohita Mudimela 	unsigned int sdp_tx_deadline_in_us = 0;
583*b11107cbSLohita Mudimela 	unsigned int line_time_in_us = 0;
584*b11107cbSLohita Mudimela 	struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
585*b11107cbSLohita Mudimela 	const int psr_setup_time_step_in_us = 55;	/* refer to eDP spec DPCD 0x071h */
586*b11107cbSLohita Mudimela 
587*b11107cbSLohita Mudimela 	/* timing parameters */
588*b11107cbSLohita Mudimela 	num_vblank_lines = stream->timing.v_total -
589*b11107cbSLohita Mudimela 			 stream->timing.v_addressable -
590*b11107cbSLohita Mudimela 			 stream->timing.v_border_top -
591*b11107cbSLohita Mudimela 			 stream->timing.v_border_bottom;
592*b11107cbSLohita Mudimela 
593*b11107cbSLohita Mudimela 	vblank_time_in_us = (stream->timing.h_total * num_vblank_lines * 1000) / (stream->timing.pix_clk_100hz / 10);
594*b11107cbSLohita Mudimela 
595*b11107cbSLohita Mudimela 	line_time_in_us = ((stream->timing.h_total * 1000) / (stream->timing.pix_clk_100hz / 10)) + 1;
596*b11107cbSLohita Mudimela 
597*b11107cbSLohita Mudimela 	/**
598*b11107cbSLohita Mudimela 	 * psr configuration fields
599*b11107cbSLohita Mudimela 	 *
600*b11107cbSLohita Mudimela 	 * as per eDP 1.5 pg. 377 of 459, DPCD 0x071h bits [3:1], psr setup time bits interpreted as below
601*b11107cbSLohita Mudimela 	 * 000b <--> 330 us (default)
602*b11107cbSLohita Mudimela 	 * 001b <--> 275 us
603*b11107cbSLohita Mudimela 	 * 010b <--> 220 us
604*b11107cbSLohita Mudimela 	 * 011b <--> 165 us
605*b11107cbSLohita Mudimela 	 * 100b <--> 110 us
606*b11107cbSLohita Mudimela 	 * 101b <--> 055 us
607*b11107cbSLohita Mudimela 	 * 110b <--> 000 us
608*b11107cbSLohita Mudimela 	 */
609*b11107cbSLohita Mudimela 	psr_config->psr_rfb_setup_time =
610*b11107cbSLohita Mudimela 		(6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * psr_setup_time_step_in_us;
611*b11107cbSLohita Mudimela 
612*b11107cbSLohita Mudimela 	if (psr_config->psr_rfb_setup_time > vblank_time_in_us) {
613*b11107cbSLohita Mudimela 		link->psr_settings.psr_frame_capture_indication_req = true;
614*b11107cbSLohita Mudimela 		link->psr_settings.psr_sdp_transmit_line_num_deadline = num_vblank_lines;
615*b11107cbSLohita Mudimela 	} else {
616*b11107cbSLohita Mudimela 		sdp_tx_deadline_in_us = vblank_time_in_us - psr_config->psr_rfb_setup_time;
617*b11107cbSLohita Mudimela 
618*b11107cbSLohita Mudimela 		/* Set the last possible line SDP may be transmitted without violating the RFB setup time */
619*b11107cbSLohita Mudimela 		link->psr_settings.psr_frame_capture_indication_req = false;
620*b11107cbSLohita Mudimela 		link->psr_settings.psr_sdp_transmit_line_num_deadline = sdp_tx_deadline_in_us / line_time_in_us;
621*b11107cbSLohita Mudimela 	}
622*b11107cbSLohita Mudimela 
623*b11107cbSLohita Mudimela 	psr_config->psr_sdp_transmit_line_num_deadline = link->psr_settings.psr_sdp_transmit_line_num_deadline;
624*b11107cbSLohita Mudimela 	psr_config->line_time_in_us = line_time_in_us;
625*b11107cbSLohita Mudimela 	psr_config->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap;
626*b11107cbSLohita Mudimela 	psr_config->su_granularity_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED;
627*b11107cbSLohita Mudimela 	psr_config->psr_frame_capture_indication_req = link->psr_settings.psr_frame_capture_indication_req;
628*b11107cbSLohita Mudimela 	psr_config->psr_exit_link_training_required =
629*b11107cbSLohita Mudimela 		!link->dpcd_caps.psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED;
630*b11107cbSLohita Mudimela }
631*b11107cbSLohita Mudimela 
632*b11107cbSLohita Mudimela bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
633*b11107cbSLohita Mudimela 			      struct dc_stream_state *stream,
634*b11107cbSLohita Mudimela 			      struct psr_config *config)
635*b11107cbSLohita Mudimela {
636*b11107cbSLohita Mudimela 	uint32_t pic_height;
637*b11107cbSLohita Mudimela 	uint32_t slice_height;
638*b11107cbSLohita Mudimela 
639*b11107cbSLohita Mudimela 	config->dsc_slice_height = 0;
640*b11107cbSLohita Mudimela 	if (!(link->connector_signal & SIGNAL_TYPE_EDP) ||
641*b11107cbSLohita Mudimela 	    !dc->caps.edp_dsc_support ||
642*b11107cbSLohita Mudimela 	    link->panel_config.dsc.disable_dsc_edp ||
643*b11107cbSLohita Mudimela 	    !link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT ||
644*b11107cbSLohita Mudimela 	    !stream->timing.dsc_cfg.num_slices_v)
645*b11107cbSLohita Mudimela 		return true;
646*b11107cbSLohita Mudimela 
647*b11107cbSLohita Mudimela 	pic_height = stream->timing.v_addressable +
648*b11107cbSLohita Mudimela 		stream->timing.v_border_top + stream->timing.v_border_bottom;
649*b11107cbSLohita Mudimela 
650*b11107cbSLohita Mudimela 	if (stream->timing.dsc_cfg.num_slices_v == 0)
651*b11107cbSLohita Mudimela 		return false;
652*b11107cbSLohita Mudimela 
653*b11107cbSLohita Mudimela 	slice_height = pic_height / stream->timing.dsc_cfg.num_slices_v;
654*b11107cbSLohita Mudimela 	config->dsc_slice_height = (uint16_t)slice_height;
655*b11107cbSLohita Mudimela 
656*b11107cbSLohita Mudimela 	if (slice_height) {
657*b11107cbSLohita Mudimela 		if (config->su_y_granularity &&
658*b11107cbSLohita Mudimela 		    (slice_height % config->su_y_granularity)) {
659*b11107cbSLohita Mudimela 			ASSERT(0);
660*b11107cbSLohita Mudimela 			return false;
661*b11107cbSLohita Mudimela 		}
662*b11107cbSLohita Mudimela 	}
663*b11107cbSLohita Mudimela 
664*b11107cbSLohita Mudimela 	return true;
665*b11107cbSLohita Mudimela }
666