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 #include "dccg.h"
21 
convert_to_count(uint8_t lttpr_repeater_count)22 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
23 {
24 	switch (lttpr_repeater_count) {
25 	case 0x80: // 1 lttpr repeater
26 		return 1;
27 	case 0x40: // 2 lttpr repeaters
28 		return 2;
29 	case 0x20: // 3 lttpr repeaters
30 		return 3;
31 	case 0x10: // 4 lttpr repeaters
32 		return 4;
33 	case 0x08: // 5 lttpr repeaters
34 		return 5;
35 	case 0x04: // 6 lttpr repeaters
36 		return 6;
37 	case 0x02: // 7 lttpr repeaters
38 		return 7;
39 	case 0x01: // 8 lttpr repeaters
40 		return 8;
41 	default:
42 		break;
43 	}
44 	return 0; // invalid value
45 }
46 
is_immediate_downstream(struct dc_link * link,uint32_t offset)47 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
48 {
49 	return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
50 }
51 
dp_receiver_power_ctrl(struct dc_link * link,bool on)52 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
53 {
54 	uint8_t state;
55 
56 	state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
57 
58 	if (link->sync_lt_in_progress)
59 		return;
60 
61 	core_link_write_dpcd(link, DP_SET_POWER, &state,
62 			sizeof(state));
63 }
64 
dp_source_sequence_trace(struct dc_link * link,uint8_t dp_test_mode)65 void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
66 {
67 	if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
68 		core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
69 					&dp_test_mode, sizeof(dp_test_mode));
70 }
71 
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)72 void dp_enable_link_phy(
73 	struct dc_link *link,
74 	enum signal_type signal,
75 	enum clock_source_id clock_source,
76 	const struct dc_link_settings *link_settings)
77 {
78 	struct link_encoder *link_enc;
79 	struct dc  *dc = link->ctx->dc;
80 	struct dmcu *dmcu = dc->res_pool->dmcu;
81 
82 	struct pipe_ctx *pipes =
83 			link->dc->current_state->res_ctx.pipe_ctx;
84 	struct clock_source *dp_cs =
85 			link->dc->res_pool->dp_clock_source;
86 	unsigned int i;
87 
88 	/* Link should always be assigned encoder when en-/disabling. */
89 	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
90 		link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link);
91 	else
92 		link_enc = link->link_enc;
93 	ASSERT(link_enc);
94 
95 	if (link->connector_signal == SIGNAL_TYPE_EDP) {
96 		link->dc->hwss.edp_power_control(link, true);
97 		link->dc->hwss.edp_wait_for_hpd_ready(link, true);
98 	}
99 
100 	/* If the current pixel clock source is not DTO(happens after
101 	 * switching from HDMI passive dongle to DP on the same connector),
102 	 * switch the pixel clock source to DTO.
103 	 */
104 	for (i = 0; i < MAX_PIPES; i++) {
105 		if (pipes[i].stream != NULL &&
106 			pipes[i].stream->link == link) {
107 			if (pipes[i].clock_source != NULL &&
108 					pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
109 				pipes[i].clock_source = dp_cs;
110 				pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
111 						pipes[i].stream->timing.pix_clk_100hz;
112 				pipes[i].clock_source->funcs->program_pix_clk(
113 							pipes[i].clock_source,
114 							&pipes[i].stream_res.pix_clk_params,
115 							&pipes[i].pll_settings);
116 			}
117 		}
118 	}
119 
120 	link->cur_link_settings = *link_settings;
121 
122 #if defined(CONFIG_DRM_AMD_DC_DCN)
123 	if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
124 		/* TODO - DP2.0 HW: notify link rate change here */
125 	} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
126 		if (dc->clk_mgr->funcs->notify_link_rate_change)
127 			dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
128 	}
129 #else
130 	if (dc->clk_mgr->funcs->notify_link_rate_change)
131 		dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
132 #endif
133 	if (dmcu != NULL && dmcu->funcs->lock_phy)
134 		dmcu->funcs->lock_phy(dmcu);
135 
136 #if defined(CONFIG_DRM_AMD_DC_DCN)
137 	if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
138 		enable_dp_hpo_output(link, link_settings);
139 	} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
140 		if (dc_is_dp_sst_signal(signal)) {
141 			link_enc->funcs->enable_dp_output(
142 							link_enc,
143 							link_settings,
144 							clock_source);
145 		} else {
146 			link_enc->funcs->enable_dp_mst_output(
147 							link_enc,
148 							link_settings,
149 							clock_source);
150 		}
151 	}
152 #else
153 	if (dc_is_dp_sst_signal(signal)) {
154 		link_enc->funcs->enable_dp_output(
155 						link_enc,
156 						link_settings,
157 						clock_source);
158 	} else {
159 		link_enc->funcs->enable_dp_mst_output(
160 						link_enc,
161 						link_settings,
162 						clock_source);
163 	}
164 #endif
165 	if (dmcu != NULL && dmcu->funcs->unlock_phy)
166 		dmcu->funcs->unlock_phy(dmcu);
167 
168 	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
169 	dp_receiver_power_ctrl(link, true);
170 }
171 
edp_add_delay_for_T9(struct dc_link * link)172 void edp_add_delay_for_T9(struct dc_link *link)
173 {
174 	if (link->local_sink &&
175 			link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
176 		udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
177 }
178 
edp_receiver_ready_T9(struct dc_link * link)179 bool edp_receiver_ready_T9(struct dc_link *link)
180 {
181 	unsigned int tries = 0;
182 	unsigned char sinkstatus = 0;
183 	unsigned char edpRev = 0;
184 	enum dc_status result;
185 
186 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
187 
188     /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
189 	if (result == DC_OK && edpRev >= DP_EDP_12) {
190 		do {
191 			sinkstatus = 1;
192 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
193 			if (sinkstatus == 0)
194 				break;
195 			if (result != DC_OK)
196 				break;
197 			udelay(100); //MAx T9
198 		} while (++tries < 50);
199 	}
200 
201 	return result;
202 }
edp_receiver_ready_T7(struct dc_link * link)203 bool edp_receiver_ready_T7(struct dc_link *link)
204 {
205 	unsigned char sinkstatus = 0;
206 	unsigned char edpRev = 0;
207 	enum dc_status result;
208 
209 	/* use absolute time stamp to constrain max T7*/
210 	unsigned long long enter_timestamp = 0;
211 	unsigned long long finish_timestamp = 0;
212 	unsigned long long time_taken_in_ns = 0;
213 
214 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
215 
216 	if (result == DC_OK && edpRev >= DP_EDP_12) {
217 		/* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
218 		enter_timestamp = dm_get_timestamp(link->ctx);
219 		do {
220 			sinkstatus = 0;
221 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
222 			if (sinkstatus == 1)
223 				break;
224 			if (result != DC_OK)
225 				break;
226 			udelay(25);
227 			finish_timestamp = dm_get_timestamp(link->ctx);
228 			time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
229 		} while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
230 	}
231 
232 	if (link->local_sink &&
233 			link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
234 		udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
235 
236 	return result;
237 }
238 
dp_disable_link_phy(struct dc_link * link,enum signal_type signal)239 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
240 {
241 	struct dc  *dc = link->ctx->dc;
242 	struct dmcu *dmcu = dc->res_pool->dmcu;
243 #if defined(CONFIG_DRM_AMD_DC_DCN)
244 	struct hpo_dp_link_encoder *hpo_link_enc = link->hpo_dp_link_enc;
245 #endif
246 	struct link_encoder *link_enc;
247 
248 	/* Link should always be assigned encoder when en-/disabling. */
249 	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
250 		link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link);
251 	else
252 		link_enc = link->link_enc;
253 	ASSERT(link_enc);
254 
255 	if (!link->wa_flags.dp_keep_receiver_powered)
256 		dp_receiver_power_ctrl(link, false);
257 
258 	if (signal == SIGNAL_TYPE_EDP) {
259 		if (link->dc->hwss.edp_backlight_control)
260 			link->dc->hwss.edp_backlight_control(link, false);
261 #if defined(CONFIG_DRM_AMD_DC_DCN)
262 		if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING)
263 			disable_dp_hpo_output(link, signal);
264 		else
265 			link_enc->funcs->disable_output(link_enc, signal);
266 #else
267 		link_enc->funcs->disable_output(link_enc, signal);
268 #endif
269 		link->dc->hwss.edp_power_control(link, false);
270 	} else {
271 		if (dmcu != NULL && dmcu->funcs->lock_phy)
272 			dmcu->funcs->lock_phy(dmcu);
273 
274 #if defined(CONFIG_DRM_AMD_DC_DCN)
275 		if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING &&
276 				hpo_link_enc)
277 			disable_dp_hpo_output(link, signal);
278 		else
279 			link_enc->funcs->disable_output(link_enc, signal);
280 #else
281 		link_enc->funcs->disable_output(link_enc, signal);
282 #endif
283 		if (dmcu != NULL && dmcu->funcs->unlock_phy)
284 			dmcu->funcs->unlock_phy(dmcu);
285 	}
286 
287 	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
288 
289 	/* Clear current link setting.*/
290 	memset(&link->cur_link_settings, 0,
291 			sizeof(link->cur_link_settings));
292 
293 	if (dc->clk_mgr->funcs->notify_link_rate_change)
294 		dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
295 }
296 
dp_disable_link_phy_mst(struct dc_link * link,enum signal_type signal)297 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
298 {
299 	/* MST disable link only when no stream use the link */
300 	if (link->mst_stream_alloc_table.stream_count > 0)
301 		return;
302 
303 	dp_disable_link_phy(link, signal);
304 
305 	/* set the sink to SST mode after disabling the link */
306 	dp_enable_mst_on_sink(link, false);
307 }
308 
dp_set_hw_training_pattern(struct dc_link * link,enum dc_dp_training_pattern pattern,uint32_t offset)309 bool dp_set_hw_training_pattern(
310 	struct dc_link *link,
311 	enum dc_dp_training_pattern pattern,
312 	uint32_t offset)
313 {
314 	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
315 
316 	switch (pattern) {
317 	case DP_TRAINING_PATTERN_SEQUENCE_1:
318 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
319 		break;
320 	case DP_TRAINING_PATTERN_SEQUENCE_2:
321 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
322 		break;
323 	case DP_TRAINING_PATTERN_SEQUENCE_3:
324 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
325 		break;
326 	case DP_TRAINING_PATTERN_SEQUENCE_4:
327 		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
328 		break;
329 #if defined(CONFIG_DRM_AMD_DC_DCN)
330 	case DP_128b_132b_TPS1:
331 		test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
332 		break;
333 	case DP_128b_132b_TPS2:
334 		test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
335 		break;
336 #endif
337 	default:
338 		break;
339 	}
340 
341 	dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
342 
343 	return true;
344 }
345 
346 #if defined(CONFIG_DRM_AMD_DC_DCN)
347 #define DC_LOGGER \
348 	link->ctx->logger
349 #endif
dp_set_hw_lane_settings(struct dc_link * link,const struct link_training_settings * link_settings,uint32_t offset)350 void dp_set_hw_lane_settings(
351 	struct dc_link *link,
352 	const struct link_training_settings *link_settings,
353 	uint32_t offset)
354 {
355 	struct link_encoder *encoder = link->link_enc;
356 
357 	if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
358 		return;
359 
360 	/* call Encoder to set lane settings */
361 #if defined(CONFIG_DRM_AMD_DC_DCN)
362 	if (dp_get_link_encoding_format(&link_settings->link_settings) ==
363 			DP_128b_132b_ENCODING) {
364 		link->hpo_dp_link_enc->funcs->set_ffe(
365 				link->hpo_dp_link_enc,
366 				&link_settings->link_settings,
367 				link_settings->lane_settings[0].FFE_PRESET.raw);
368 	} else if (dp_get_link_encoding_format(&link_settings->link_settings)
369 			== DP_8b_10b_ENCODING) {
370 		encoder->funcs->dp_set_lane_settings(encoder, link_settings);
371 	}
372 #else
373 	encoder->funcs->dp_set_lane_settings(encoder, link_settings);
374 #endif
375 	memmove(link->cur_lane_setting,
376 			link_settings->lane_settings,
377 			sizeof(link->cur_lane_setting));
378 }
379 
dp_set_hw_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,uint8_t * custom_pattern,uint32_t custom_pattern_size)380 void dp_set_hw_test_pattern(
381 	struct dc_link *link,
382 	enum dp_test_pattern test_pattern,
383 	uint8_t *custom_pattern,
384 	uint32_t custom_pattern_size)
385 {
386 	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
387 	struct link_encoder *encoder;
388 #if defined(CONFIG_DRM_AMD_DC_DCN)
389 	enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings);
390 #endif
391 
392 	/* Access link encoder based on whether it is statically
393 	 * or dynamically assigned to a link.
394 	 */
395 	if (link->is_dig_mapping_flexible &&
396 			link->dc->res_pool->funcs->link_encs_assign)
397 		encoder = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link);
398 	else
399 		encoder = link->link_enc;
400 
401 	pattern_param.dp_phy_pattern = test_pattern;
402 	pattern_param.custom_pattern = custom_pattern;
403 	pattern_param.custom_pattern_size = custom_pattern_size;
404 	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
405 
406 #if defined(CONFIG_DRM_AMD_DC_DCN)
407 	switch (link_encoding_format) {
408 	case DP_128b_132b_ENCODING:
409 		link->hpo_dp_link_enc->funcs->set_link_test_pattern(
410 				link->hpo_dp_link_enc, &pattern_param);
411 		break;
412 	case DP_8b_10b_ENCODING:
413 		ASSERT(encoder);
414 		encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
415 		break;
416 	default:
417 		DC_LOG_ERROR("%s: Unknown link encoding format.", __func__);
418 		break;
419 	}
420 #else
421 	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
422 #endif
423 	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
424 }
425 #if defined(CONFIG_DRM_AMD_DC_DCN)
426 #undef DC_LOGGER
427 #endif
428 
dp_retrain_link_dp_test(struct dc_link * link,struct dc_link_settings * link_setting,bool skip_video_pattern)429 void dp_retrain_link_dp_test(struct dc_link *link,
430 			struct dc_link_settings *link_setting,
431 			bool skip_video_pattern)
432 {
433 	struct pipe_ctx *pipes =
434 			&link->dc->current_state->res_ctx.pipe_ctx[0];
435 	unsigned int i;
436 
437 	for (i = 0; i < MAX_PIPES; i++) {
438 		if (pipes[i].stream != NULL &&
439 			!pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
440 			pipes[i].stream->link != NULL &&
441 			pipes[i].stream_res.stream_enc != NULL &&
442 			pipes[i].stream->link == link) {
443 			udelay(100);
444 
445 			pipes[i].stream_res.stream_enc->funcs->dp_blank(link,
446 					pipes[i].stream_res.stream_enc);
447 
448 			/* disable any test pattern that might be active */
449 			dp_set_hw_test_pattern(link,
450 					DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
451 
452 			dp_receiver_power_ctrl(link, false);
453 
454 			link->dc->hwss.disable_stream(&pipes[i]);
455 			if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
456 				(&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
457 
458 			if (link->link_enc)
459 				link->link_enc->funcs->disable_output(
460 						link->link_enc,
461 						SIGNAL_TYPE_DISPLAY_PORT);
462 
463 			/* Clear current link setting. */
464 			memset(&link->cur_link_settings, 0,
465 				sizeof(link->cur_link_settings));
466 
467 			perform_link_training_with_retries(
468 					link_setting,
469 					skip_video_pattern,
470 					LINK_TRAINING_ATTEMPTS,
471 					&pipes[i],
472 					SIGNAL_TYPE_DISPLAY_PORT,
473 					false);
474 
475 			link->dc->hwss.enable_stream(&pipes[i]);
476 
477 			link->dc->hwss.unblank_stream(&pipes[i],
478 					link_setting);
479 
480 			if (pipes[i].stream_res.audio) {
481 				/* notify audio driver for
482 				 * audio modes of monitor */
483 				pipes[i].stream_res.audio->funcs->az_enable(
484 						pipes[i].stream_res.audio);
485 
486 				/* un-mute audio */
487 				/* TODO: audio should be per stream rather than
488 				 * per link */
489 				pipes[i].stream_res.stream_enc->funcs->
490 				audio_mute_control(
491 					pipes[i].stream_res.stream_enc, false);
492 			}
493 		}
494 	}
495 }
496 
497 #define DC_LOGGER \
498 	dsc->ctx->logger
dsc_optc_config_log(struct display_stream_compressor * dsc,struct dsc_optc_config * config)499 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
500 		struct dsc_optc_config *config)
501 {
502 	uint32_t precision = 1 << 28;
503 	uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
504 	uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
505 	uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
506 
507 	/* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
508 	 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
509 	 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
510 	 */
511 	ll_bytes_per_pix_fraq *= 10000000;
512 	ll_bytes_per_pix_fraq /= precision;
513 
514 	DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
515 			config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
516 	DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
517 	DC_LOG_DSC("\tslice_width %d", config->slice_width);
518 }
519 
dp_set_dsc_on_rx(struct pipe_ctx * pipe_ctx,bool enable)520 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
521 {
522 	struct dc *dc = pipe_ctx->stream->ctx->dc;
523 	struct dc_stream_state *stream = pipe_ctx->stream;
524 	bool result = false;
525 
526 	if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
527 		result = true;
528 	else
529 		result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
530 	return result;
531 }
532 
533 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
534  * i.e. after dp_enable_dsc_on_rx() had been called
535  */
dp_set_dsc_on_stream(struct pipe_ctx * pipe_ctx,bool enable)536 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
537 {
538 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
539 	struct dc *dc = pipe_ctx->stream->ctx->dc;
540 	struct dc_stream_state *stream = pipe_ctx->stream;
541 	struct pipe_ctx *odm_pipe;
542 	int opp_cnt = 1;
543 
544 	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
545 		opp_cnt++;
546 
547 	if (enable) {
548 		struct dsc_config dsc_cfg;
549 		struct dsc_optc_config dsc_optc_cfg;
550 		enum optc_dsc_mode optc_dsc_mode;
551 
552 		/* Enable DSC hw block */
553 		dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
554 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
555 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
556 		dsc_cfg.color_depth = stream->timing.display_color_depth;
557 		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
558 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
559 		ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
560 		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
561 
562 		dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
563 		dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
564 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
565 			struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
566 
567 			odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
568 			odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
569 		}
570 		dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
571 		dsc_cfg.pic_width *= opp_cnt;
572 
573 		optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
574 
575 		/* Enable DSC in encoder */
576 #if defined(CONFIG_DRM_AMD_DC_DCN)
577 		if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
578 				&& !is_dp_128b_132b_signal(pipe_ctx)) {
579 #else
580 		if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
581 #endif
582 			DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
583 			dsc_optc_config_log(dsc, &dsc_optc_cfg);
584 			pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
585 									optc_dsc_mode,
586 									dsc_optc_cfg.bytes_per_pixel,
587 									dsc_optc_cfg.slice_width);
588 
589 			/* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
590 		}
591 
592 		/* Enable DSC in OPTC */
593 		DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
594 		dsc_optc_config_log(dsc, &dsc_optc_cfg);
595 		pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
596 							optc_dsc_mode,
597 							dsc_optc_cfg.bytes_per_pixel,
598 							dsc_optc_cfg.slice_width);
599 	} else {
600 		/* disable DSC in OPTC */
601 		pipe_ctx->stream_res.tg->funcs->set_dsc_config(
602 				pipe_ctx->stream_res.tg,
603 				OPTC_DSC_DISABLED, 0, 0);
604 
605 		/* disable DSC in stream encoder */
606 		if (dc_is_dp_signal(stream->signal)) {
607 
608 #if defined(CONFIG_DRM_AMD_DC_DCN)
609 			if (is_dp_128b_132b_signal(pipe_ctx))
610 				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
611 										pipe_ctx->stream_res.hpo_dp_stream_enc,
612 										false,
613 										NULL,
614 										true);
615 			else
616 #endif
617 				if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
618 					pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
619 							pipe_ctx->stream_res.stream_enc,
620 							OPTC_DSC_DISABLED, 0, 0);
621 					pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
622 								pipe_ctx->stream_res.stream_enc, false, NULL, true);
623 				}
624 		}
625 
626 		/* disable DSC block */
627 		pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
628 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
629 			odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
630 	}
631 }
632 
633 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
634 {
635 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
636 	bool result = false;
637 
638 	if (!pipe_ctx->stream->timing.flags.DSC)
639 		goto out;
640 	if (!dsc)
641 		goto out;
642 
643 	if (enable) {
644 		{
645 			dp_set_dsc_on_stream(pipe_ctx, true);
646 			result = true;
647 		}
648 	} else {
649 		dp_set_dsc_on_rx(pipe_ctx, false);
650 		dp_set_dsc_on_stream(pipe_ctx, false);
651 		result = true;
652 	}
653 out:
654 	return result;
655 }
656 
657 /*
658  * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
659  * hence PPS info packet update need to use frame update instead of immediate update.
660  * Added parameter immediate_update for this purpose.
661  * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
662  * which is the only place where a "false" would be passed in for param immediate_update.
663  *
664  * immediate_update is only applicable when DSC is enabled.
665  */
666 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
667 {
668 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
669 	struct dc_stream_state *stream = pipe_ctx->stream;
670 
671 	if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
672 		return false;
673 
674 	if (enable) {
675 		struct dsc_config dsc_cfg;
676 		uint8_t dsc_packed_pps[128];
677 
678 		memset(&dsc_cfg, 0, sizeof(dsc_cfg));
679 		memset(dsc_packed_pps, 0, 128);
680 
681 		/* Enable DSC hw block */
682 		dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
683 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
684 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
685 		dsc_cfg.color_depth = stream->timing.display_color_depth;
686 		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
687 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
688 
689 		DC_LOG_DSC(" ");
690 		dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
691 		if (dc_is_dp_signal(stream->signal)) {
692 			DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
693 #if defined(CONFIG_DRM_AMD_DC_DCN)
694 			if (is_dp_128b_132b_signal(pipe_ctx))
695 				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
696 										pipe_ctx->stream_res.hpo_dp_stream_enc,
697 										true,
698 										&dsc_packed_pps[0],
699 										immediate_update);
700 			else
701 #endif
702 				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
703 										pipe_ctx->stream_res.stream_enc,
704 										true,
705 										&dsc_packed_pps[0],
706 										immediate_update);
707 		}
708 	} else {
709 		/* disable DSC PPS in stream encoder */
710 		if (dc_is_dp_signal(stream->signal)) {
711 #if defined(CONFIG_DRM_AMD_DC_DCN)
712 			if (is_dp_128b_132b_signal(pipe_ctx))
713 				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
714 										pipe_ctx->stream_res.hpo_dp_stream_enc,
715 										false,
716 										NULL,
717 										true);
718 			else
719 #endif
720 				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
721 							pipe_ctx->stream_res.stream_enc, false, NULL, true);
722 		}
723 	}
724 
725 	return true;
726 }
727 
728 
729 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
730 {
731 	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
732 
733 	if (!pipe_ctx->stream->timing.flags.DSC)
734 		return false;
735 	if (!dsc)
736 		return false;
737 
738 	dp_set_dsc_on_stream(pipe_ctx, true);
739 	dp_set_dsc_pps_sdp(pipe_ctx, true, false);
740 	return true;
741 }
742 
743 #if defined(CONFIG_DRM_AMD_DC_DCN)
744 #undef DC_LOGGER
745 #define DC_LOGGER \
746 	link->ctx->logger
747 
748 static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
749 {
750 	switch (link->link_enc->transmitter) {
751 	case TRANSMITTER_UNIPHY_A:
752 		return PHYD32CLKA;
753 	case TRANSMITTER_UNIPHY_B:
754 		return PHYD32CLKB;
755 	case TRANSMITTER_UNIPHY_C:
756 		return PHYD32CLKC;
757 	case TRANSMITTER_UNIPHY_D:
758 		return PHYD32CLKD;
759 	case TRANSMITTER_UNIPHY_E:
760 		return PHYD32CLKE;
761 	default:
762 		return PHYD32CLKA;
763 	}
764 }
765 
766 void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings)
767 {
768 	const struct dc *dc = link->dc;
769 	enum phyd32clk_clock_source phyd32clk;
770 
771 	/* Enable PHY PLL at target bit rate
772 	 *   UHBR10 = 10Gbps (SYMCLK32 = 312.5MHz)
773 	 *   UBR13.5 = 13.5Gbps (SYMCLK32 = 421.875MHz)
774 	 *   UHBR20 = 20Gbps (SYMCLK32 = 625MHz)
775 	 */
776 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
777 		switch (link_settings->link_rate) {
778 		case LINK_RATE_UHBR10:
779 			dm_set_phyd32clk(dc->ctx, 312500);
780 			break;
781 		case LINK_RATE_UHBR13_5:
782 			dm_set_phyd32clk(dc->ctx, 412875);
783 			break;
784 		case LINK_RATE_UHBR20:
785 			dm_set_phyd32clk(dc->ctx, 625000);
786 			break;
787 		default:
788 			return;
789 		}
790 	} else {
791 		/* DP2.0 HW: call transmitter control to enable PHY */
792 		link->hpo_dp_link_enc->funcs->enable_link_phy(
793 				link->hpo_dp_link_enc,
794 				link_settings,
795 				link->link_enc->transmitter);
796 	}
797 
798 	/* DCCG muxing and DTBCLK DTO */
799 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
800 		dc->res_pool->dccg->funcs->set_physymclk(
801 				dc->res_pool->dccg,
802 				link->link_enc_hw_inst,
803 				PHYSYMCLK_FORCE_SRC_PHYD32CLK,
804 				true);
805 
806 		phyd32clk = get_phyd32clk_src(link);
807 		dc->res_pool->dccg->funcs->enable_symclk32_le(
808 				dc->res_pool->dccg,
809 				link->hpo_dp_link_enc->inst,
810 				phyd32clk);
811 		link->hpo_dp_link_enc->funcs->link_enable(
812 					link->hpo_dp_link_enc,
813 					link_settings->lane_count);
814 	}
815 }
816 
817 void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal)
818 {
819 	const struct dc *dc = link->dc;
820 
821 	link->hpo_dp_link_enc->funcs->link_disable(link->hpo_dp_link_enc);
822 
823 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
824 		dc->res_pool->dccg->funcs->disable_symclk32_le(
825 					dc->res_pool->dccg,
826 					link->hpo_dp_link_enc->inst);
827 
828 		dc->res_pool->dccg->funcs->set_physymclk(
829 					dc->res_pool->dccg,
830 					link->link_enc_hw_inst,
831 					PHYSYMCLK_FORCE_SRC_SYMCLK,
832 					false);
833 
834 		dm_set_phyd32clk(dc->ctx, 0);
835 	} else {
836 		/* DP2.0 HW: call transmitter control to disable PHY */
837 		link->hpo_dp_link_enc->funcs->disable_link_phy(
838 				link->hpo_dp_link_enc,
839 				signal);
840 	}
841 }
842 
843 void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable)
844 {
845 	struct dc_stream_state *stream = pipe_ctx->stream;
846 	struct dc *dc = pipe_ctx->stream->ctx->dc;
847 	struct pipe_ctx *odm_pipe;
848 	int odm_combine_num_segments = 1;
849 	enum phyd32clk_clock_source phyd32clk;
850 
851 	if (enable) {
852 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
853 				odm_combine_num_segments++;
854 
855 		dc->res_pool->dccg->funcs->set_dpstreamclk(
856 				dc->res_pool->dccg,
857 				DTBCLK0,
858 				pipe_ctx->stream_res.tg->inst);
859 
860 		phyd32clk = get_phyd32clk_src(stream->link);
861 		dc->res_pool->dccg->funcs->enable_symclk32_se(
862 				dc->res_pool->dccg,
863 				pipe_ctx->stream_res.hpo_dp_stream_enc->inst,
864 				phyd32clk);
865 
866 		dc->res_pool->dccg->funcs->set_dtbclk_dto(
867 				dc->res_pool->dccg,
868 				pipe_ctx->stream_res.tg->inst,
869 				stream->phy_pix_clk,
870 				odm_combine_num_segments,
871 				&stream->timing);
872 	} else {
873 		dc->res_pool->dccg->funcs->set_dtbclk_dto(
874 				dc->res_pool->dccg,
875 				pipe_ctx->stream_res.tg->inst,
876 				0,
877 				0,
878 				&stream->timing);
879 		dc->res_pool->dccg->funcs->disable_symclk32_se(
880 				dc->res_pool->dccg,
881 				pipe_ctx->stream_res.hpo_dp_stream_enc->inst);
882 		dc->res_pool->dccg->funcs->set_dpstreamclk(
883 				dc->res_pool->dccg,
884 				REFCLK,
885 				pipe_ctx->stream_res.tg->inst);
886 	}
887 }
888 
889 void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link)
890 {
891 	const struct dc *dc = link->dc;
892 	struct dc_state *state = dc->current_state;
893 	uint8_t i;
894 
895 	for (i = 0; i < MAX_PIPES; i++) {
896 		if (state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc &&
897 				state->res_ctx.pipe_ctx[i].stream &&
898 				state->res_ctx.pipe_ctx[i].stream->link == link &&
899 				!state->res_ctx.pipe_ctx[i].stream->dpms_off) {
900 			setup_dp_hpo_stream(&state->res_ctx.pipe_ctx[i], false);
901 		}
902 	}
903 }
904 
905 #undef DC_LOGGER
906 #endif
907