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