1 /* Copyright 2015 Advanced Micro Devices, Inc. */
2 
3 
4 #include "dm_services.h"
5 #include "dc.h"
6 #include "inc/core_types.h"
7 #include "include/ddc_service_types.h"
8 #include "include/i2caux_interface.h"
9 #include "link_hwss.h"
10 #include "hw_sequencer.h"
11 #include "dc_link_dp.h"
12 #include "dc_link_ddc.h"
13 #include "dm_helpers.h"
14 #include "dpcd_defs.h"
15 #include "dsc.h"
16 #include "resource.h"
17 #include "link_enc_cfg.h"
18 #include "clk_mgr.h"
19 #include "inc/link_dpcd.h"
20 
convert_to_count(uint8_t lttpr_repeater_count)21 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
22 {
23 	switch (lttpr_repeater_count) {
24 	case 0x80: // 1 lttpr repeater
25 		return 1;
26 	case 0x40: // 2 lttpr repeaters
27 		return 2;
28 	case 0x20: // 3 lttpr repeaters
29 		return 3;
30 	case 0x10: // 4 lttpr repeaters
31 		return 4;
32 	case 0x08: // 5 lttpr repeaters
33 		return 5;
34 	case 0x04: // 6 lttpr repeaters
35 		return 6;
36 	case 0x02: // 7 lttpr repeaters
37 		return 7;
38 	case 0x01: // 8 lttpr repeaters
39 		return 8;
40 	default:
41 		break;
42 	}
43 	return 0; // invalid value
44 }
45 
is_immediate_downstream(struct dc_link * link,uint32_t offset)46 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
47 {
48 	return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
49 }
50 
dp_receiver_power_ctrl(struct dc_link * link,bool on)51 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
52 {
53 	uint8_t state;
54 
55 	state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
56 
57 	if (link->sync_lt_in_progress)
58 		return;
59 
60 	core_link_write_dpcd(link, DP_SET_POWER, &state,
61 			sizeof(state));
62 }
63 
dp_enable_link_phy(struct dc_link * link,enum signal_type signal,enum clock_source_id clock_source,const struct dc_link_settings * link_settings)64 void dp_enable_link_phy(
65 	struct dc_link *link,
66 	enum signal_type signal,
67 	enum clock_source_id clock_source,
68 	const struct dc_link_settings *link_settings)
69 {
70 	struct link_encoder *link_enc;
71 	struct dc  *dc = link->ctx->dc;
72 	struct dmcu *dmcu = dc->res_pool->dmcu;
73 
74 	struct pipe_ctx *pipes =
75 			link->dc->current_state->res_ctx.pipe_ctx;
76 	struct clock_source *dp_cs =
77 			link->dc->res_pool->dp_clock_source;
78 	unsigned int i;
79 
80 	/* Link should always be assigned encoder when en-/disabling. */
81 	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
82 		link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
83 	else
84 		link_enc = link->link_enc;
85 	ASSERT(link_enc);
86 
87 	if (link->connector_signal == SIGNAL_TYPE_EDP) {
88 		link->dc->hwss.edp_power_control(link, true);
89 		link->dc->hwss.edp_wait_for_hpd_ready(link, true);
90 	}
91 
92 	/* If the current pixel clock source is not DTO(happens after
93 	 * switching from HDMI passive dongle to DP on the same connector),
94 	 * switch the pixel clock source to DTO.
95 	 */
96 	for (i = 0; i < MAX_PIPES; i++) {
97 		if (pipes[i].stream != NULL &&
98 			pipes[i].stream->link == link) {
99 			if (pipes[i].clock_source != NULL &&
100 					pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
101 				pipes[i].clock_source = dp_cs;
102 				pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
103 						pipes[i].stream->timing.pix_clk_100hz;
104 				pipes[i].clock_source->funcs->program_pix_clk(
105 							pipes[i].clock_source,
106 							&pipes[i].stream_res.pix_clk_params,
107 							&pipes[i].pll_settings);
108 			}
109 		}
110 	}
111 
112 	link->cur_link_settings = *link_settings;
113 
114 	if (dc->clk_mgr->funcs->notify_link_rate_change)
115 		dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
116 
117 	if (dmcu != NULL && dmcu->funcs->lock_phy)
118 		dmcu->funcs->lock_phy(dmcu);
119 
120 	if (dc_is_dp_sst_signal(signal)) {
121 		link_enc->funcs->enable_dp_output(
122 						link_enc,
123 						link_settings,
124 						clock_source);
125 	} else {
126 		link_enc->funcs->enable_dp_mst_output(
127 						link_enc,
128 						link_settings,
129 						clock_source);
130 	}
131 
132 	if (dmcu != NULL && dmcu->funcs->unlock_phy)
133 		dmcu->funcs->unlock_phy(dmcu);
134 
135 	dp_receiver_power_ctrl(link, true);
136 }
137 
edp_add_delay_for_T9(struct dc_link * link)138 void edp_add_delay_for_T9(struct dc_link *link)
139 {
140 	if (link->local_sink &&
141 			link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
142 		udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
143 }
144 
edp_receiver_ready_T9(struct dc_link * link)145 bool edp_receiver_ready_T9(struct dc_link *link)
146 {
147 	unsigned int tries = 0;
148 	unsigned char sinkstatus = 0;
149 	unsigned char edpRev = 0;
150 	enum dc_status result;
151 
152 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
153 
154     /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
155 	if (result == DC_OK && edpRev >= DP_EDP_12) {
156 		do {
157 			sinkstatus = 1;
158 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
159 			if (sinkstatus == 0)
160 				break;
161 			if (result != DC_OK)
162 				break;
163 			udelay(100); //MAx T9
164 		} while (++tries < 50);
165 	}
166 
167 	return result;
168 }
edp_receiver_ready_T7(struct dc_link * link)169 bool edp_receiver_ready_T7(struct dc_link *link)
170 {
171 	unsigned char sinkstatus = 0;
172 	unsigned char edpRev = 0;
173 	enum dc_status result;
174 
175 	/* use absolute time stamp to constrain max T7*/
176 	unsigned long long enter_timestamp = 0;
177 	unsigned long long finish_timestamp = 0;
178 	unsigned long long time_taken_in_ns = 0;
179 
180 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
181 
182 	if (result == DC_OK && edpRev >= DP_EDP_12) {
183 		/* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
184 		enter_timestamp = dm_get_timestamp(link->ctx);
185 		do {
186 			sinkstatus = 0;
187 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
188 			if (sinkstatus == 1)
189 				break;
190 			if (result != DC_OK)
191 				break;
192 			udelay(25);
193 			finish_timestamp = dm_get_timestamp(link->ctx);
194 			time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
195 		} while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
196 	}
197 
198 	if (link->local_sink &&
199 			link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
200 		udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
201 
202 	return result;
203 }
204 
dp_disable_link_phy(struct dc_link * link,enum signal_type signal)205 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
206 {
207 	struct dc  *dc = link->ctx->dc;
208 	struct dmcu *dmcu = dc->res_pool->dmcu;
209 	struct link_encoder *link_enc;
210 
211 	/* Link should always be assigned encoder when en-/disabling. */
212 	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
213 		link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
214 	else
215 		link_enc = link->link_enc;
216 	ASSERT(link_enc);
217 
218 	if (!link->wa_flags.dp_keep_receiver_powered)
219 		dp_receiver_power_ctrl(link, false);
220 
221 	if (signal == SIGNAL_TYPE_EDP) {
222 		if (link->dc->hwss.edp_backlight_control)
223 			link->dc->hwss.edp_backlight_control(link, false);
224 		link_enc->funcs->disable_output(link_enc, signal);
225 		link->dc->hwss.edp_power_control(link, false);
226 	} else {
227 		if (dmcu != NULL && dmcu->funcs->lock_phy)
228 			dmcu->funcs->lock_phy(dmcu);
229 
230 		link_enc->funcs->disable_output(link_enc, signal);
231 
232 		if (dmcu != NULL && dmcu->funcs->unlock_phy)
233 			dmcu->funcs->unlock_phy(dmcu);
234 	}
235 
236 	/* Clear current link setting.*/
237 	memset(&link->cur_link_settings, 0,
238 			sizeof(link->cur_link_settings));
239 
240 	if (dc->clk_mgr->funcs->notify_link_rate_change)
241 		dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
242 }
243 
dp_disable_link_phy_mst(struct dc_link * link,enum signal_type signal)244 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
245 {
246 	/* MST disable link only when no stream use the link */
247 	if (link->mst_stream_alloc_table.stream_count > 0)
248 		return;
249 
250 	dp_disable_link_phy(link, signal);
251 
252 	/* set the sink to SST mode after disabling the link */
253 	dp_enable_mst_on_sink(link, false);
254 }
255 
dp_set_hw_training_pattern(struct dc_link * link,enum dc_dp_training_pattern pattern,uint32_t offset)256 bool dp_set_hw_training_pattern(
257 	struct dc_link *link,
258 	enum dc_dp_training_pattern pattern,
259 	uint32_t offset)
260 {
261 	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
262 
263 	switch (pattern) {
264 	case DP_TRAINING_PATTERN_SEQUENCE_1:
265 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
266 		break;
267 	case DP_TRAINING_PATTERN_SEQUENCE_2:
268 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
269 		break;
270 	case DP_TRAINING_PATTERN_SEQUENCE_3:
271 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
272 		break;
273 	case DP_TRAINING_PATTERN_SEQUENCE_4:
274 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
275 		break;
276 	default:
277 		break;
278 	}
279 
280 	dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
281 
282 	return true;
283 }
284 
dp_set_hw_lane_settings(struct dc_link * link,const struct link_training_settings * link_settings,uint32_t offset)285 void dp_set_hw_lane_settings(
286 	struct dc_link *link,
287 	const struct link_training_settings *link_settings,
288 	uint32_t offset)
289 {
290 	struct link_encoder *encoder = link->link_enc;
291 
292 	if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
293 		return;
294 
295 	/* call Encoder to set lane settings */
296 	encoder->funcs->dp_set_lane_settings(encoder, link_settings);
297 }
298 
dp_set_hw_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,uint8_t * custom_pattern,uint32_t custom_pattern_size)299 void dp_set_hw_test_pattern(
300 	struct dc_link *link,
301 	enum dp_test_pattern test_pattern,
302 	uint8_t *custom_pattern,
303 	uint32_t custom_pattern_size)
304 {
305 	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
306 	struct link_encoder *encoder;
307 
308 	/* Access link encoder based on whether it is statically
309 	 * or dynamically assigned to a link.
310 	 */
311 	if (link->is_dig_mapping_flexible &&
312 			link->dc->res_pool->funcs->link_encs_assign)
313 		encoder = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
314 	else
315 		encoder = link->link_enc;
316 
317 	pattern_param.dp_phy_pattern = test_pattern;
318 	pattern_param.custom_pattern = custom_pattern;
319 	pattern_param.custom_pattern_size = custom_pattern_size;
320 	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
321 
322 	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
323 }
324 
dp_retrain_link_dp_test(struct dc_link * link,struct dc_link_settings * link_setting,bool skip_video_pattern)325 void dp_retrain_link_dp_test(struct dc_link *link,
326 			struct dc_link_settings *link_setting,
327 			bool skip_video_pattern)
328 {
329 	struct pipe_ctx *pipes =
330 			&link->dc->current_state->res_ctx.pipe_ctx[0];
331 	unsigned int i;
332 
333 	for (i = 0; i < MAX_PIPES; i++) {
334 		if (pipes[i].stream != NULL &&
335 			!pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
336 			pipes[i].stream->link != NULL &&
337 			pipes[i].stream_res.stream_enc != NULL &&
338 			pipes[i].stream->link == link) {
339 			udelay(100);
340 
341 			pipes[i].stream_res.stream_enc->funcs->dp_blank(
342 					pipes[i].stream_res.stream_enc);
343 
344 			/* disable any test pattern that might be active */
345 			dp_set_hw_test_pattern(link,
346 					DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
347 
348 			dp_receiver_power_ctrl(link, false);
349 
350 			link->dc->hwss.disable_stream(&pipes[i]);
351 			if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
352 				(&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
353 
354 			link->link_enc->funcs->disable_output(
355 					link->link_enc,
356 					SIGNAL_TYPE_DISPLAY_PORT);
357 
358 			/* Clear current link setting. */
359 			memset(&link->cur_link_settings, 0,
360 				sizeof(link->cur_link_settings));
361 
362 			perform_link_training_with_retries(
363 					link_setting,
364 					skip_video_pattern,
365 					LINK_TRAINING_ATTEMPTS,
366 					&pipes[i],
367 					SIGNAL_TYPE_DISPLAY_PORT,
368 					false);
369 
370 			link->dc->hwss.enable_stream(&pipes[i]);
371 
372 			link->dc->hwss.unblank_stream(&pipes[i],
373 					link_setting);
374 
375 			if (pipes[i].stream_res.audio) {
376 				/* notify audio driver for
377 				 * audio modes of monitor */
378 				pipes[i].stream_res.audio->funcs->az_enable(
379 						pipes[i].stream_res.audio);
380 
381 				/* un-mute audio */
382 				/* TODO: audio should be per stream rather than
383 				 * per link */
384 				pipes[i].stream_res.stream_enc->funcs->
385 				audio_mute_control(
386 					pipes[i].stream_res.stream_enc, false);
387 			}
388 		}
389 	}
390 }
391 
392 #define DC_LOGGER \
393 	dsc->ctx->logger
dsc_optc_config_log(struct display_stream_compressor * dsc,struct dsc_optc_config * config)394 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
395 		struct dsc_optc_config *config)
396 {
397 	uint32_t precision = 1 << 28;
398 	uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
399 	uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
400 	uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
401 
402 	/* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
403 	 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
404 	 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
405 	 */
406 	ll_bytes_per_pix_fraq *= 10000000;
407 	ll_bytes_per_pix_fraq /= precision;
408 
409 	DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
410 			config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
411 	DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
412 	DC_LOG_DSC("\tslice_width %d", config->slice_width);
413 }
414 
dp_set_dsc_on_rx(struct pipe_ctx * pipe_ctx,bool enable)415 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
416 {
417 	struct dc *dc = pipe_ctx->stream->ctx->dc;
418 	struct dc_stream_state *stream = pipe_ctx->stream;
419 	bool result = false;
420 
421 	if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
422 		result = true;
423 	else
424 		result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
425 	return result;
426 }
427 
428 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
429  * i.e. after dp_enable_dsc_on_rx() had been called
430  */
dp_set_dsc_on_stream(struct pipe_ctx * pipe_ctx,bool enable)431 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
432 {
433 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
434 	struct dc *dc = pipe_ctx->stream->ctx->dc;
435 	struct dc_stream_state *stream = pipe_ctx->stream;
436 	struct pipe_ctx *odm_pipe;
437 	int opp_cnt = 1;
438 
439 	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
440 		opp_cnt++;
441 
442 	if (enable) {
443 		struct dsc_config dsc_cfg;
444 		struct dsc_optc_config dsc_optc_cfg;
445 		enum optc_dsc_mode optc_dsc_mode;
446 
447 		/* Enable DSC hw block */
448 		dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
449 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
450 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
451 		dsc_cfg.color_depth = stream->timing.display_color_depth;
452 		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
453 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
454 		ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
455 		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
456 
457 		dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
458 		dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
459 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
460 			struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
461 
462 			odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
463 			odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
464 		}
465 		dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
466 		dsc_cfg.pic_width *= opp_cnt;
467 
468 		optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
469 
470 		/* Enable DSC in encoder */
471 		if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
472 			DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
473 			dsc_optc_config_log(dsc, &dsc_optc_cfg);
474 			pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
475 									optc_dsc_mode,
476 									dsc_optc_cfg.bytes_per_pixel,
477 									dsc_optc_cfg.slice_width);
478 
479 			/* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
480 		}
481 
482 		/* Enable DSC in OPTC */
483 		DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
484 		dsc_optc_config_log(dsc, &dsc_optc_cfg);
485 		pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
486 							optc_dsc_mode,
487 							dsc_optc_cfg.bytes_per_pixel,
488 							dsc_optc_cfg.slice_width);
489 	} else {
490 		/* disable DSC in OPTC */
491 		pipe_ctx->stream_res.tg->funcs->set_dsc_config(
492 				pipe_ctx->stream_res.tg,
493 				OPTC_DSC_DISABLED, 0, 0);
494 
495 		/* disable DSC in stream encoder */
496 		if (dc_is_dp_signal(stream->signal)) {
497 
498 			if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
499 				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
500 						pipe_ctx->stream_res.stream_enc,
501 						OPTC_DSC_DISABLED, 0, 0);
502 				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
503 							pipe_ctx->stream_res.stream_enc, false, NULL);
504 			}
505 		}
506 
507 		/* disable DSC block */
508 		pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
509 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
510 			odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
511 	}
512 }
513 
dp_set_dsc_enable(struct pipe_ctx * pipe_ctx,bool enable)514 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
515 {
516 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
517 	bool result = false;
518 
519 	if (!pipe_ctx->stream->timing.flags.DSC)
520 		goto out;
521 	if (!dsc)
522 		goto out;
523 
524 	if (enable) {
525 		{
526 			dp_set_dsc_on_stream(pipe_ctx, true);
527 			result = true;
528 		}
529 	} else {
530 		dp_set_dsc_on_rx(pipe_ctx, false);
531 		dp_set_dsc_on_stream(pipe_ctx, false);
532 		result = true;
533 	}
534 out:
535 	return result;
536 }
537 
dp_set_dsc_pps_sdp(struct pipe_ctx * pipe_ctx,bool enable)538 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
539 {
540 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
541 	struct dc_stream_state *stream = pipe_ctx->stream;
542 
543 	if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
544 		return false;
545 
546 	if (enable) {
547 		struct dsc_config dsc_cfg;
548 		uint8_t dsc_packed_pps[128];
549 
550 		memset(&dsc_cfg, 0, sizeof(dsc_cfg));
551 		memset(dsc_packed_pps, 0, 128);
552 
553 		/* Enable DSC hw block */
554 		dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
555 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
556 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
557 		dsc_cfg.color_depth = stream->timing.display_color_depth;
558 		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
559 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
560 
561 		DC_LOG_DSC(" ");
562 		dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
563 		if (dc_is_dp_signal(stream->signal)) {
564 			DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
565 			pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
566 									pipe_ctx->stream_res.stream_enc,
567 									true,
568 									&dsc_packed_pps[0]);
569 		}
570 	} else {
571 		/* disable DSC PPS in stream encoder */
572 		if (dc_is_dp_signal(stream->signal)) {
573 			pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
574 						pipe_ctx->stream_res.stream_enc, false, NULL);
575 		}
576 	}
577 
578 	return true;
579 }
580 
581 
dp_update_dsc_config(struct pipe_ctx * pipe_ctx)582 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
583 {
584 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
585 
586 	if (!pipe_ctx->stream->timing.flags.DSC)
587 		return false;
588 	if (!dsc)
589 		return false;
590 
591 	dp_set_dsc_on_stream(pipe_ctx, true);
592 	dp_set_dsc_pps_sdp(pipe_ctx, true);
593 	return true;
594 }
595 
596