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 "clk_mgr.h"
18
convert_to_count(uint8_t lttpr_repeater_count)19 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
20 {
21 switch (lttpr_repeater_count) {
22 case 0x80: // 1 lttpr repeater
23 return 1;
24 case 0x40: // 2 lttpr repeaters
25 return 2;
26 case 0x20: // 3 lttpr repeaters
27 return 3;
28 case 0x10: // 4 lttpr repeaters
29 return 4;
30 case 0x08: // 5 lttpr repeaters
31 return 5;
32 case 0x04: // 6 lttpr repeaters
33 return 6;
34 case 0x02: // 7 lttpr repeaters
35 return 7;
36 case 0x01: // 8 lttpr repeaters
37 return 8;
38 default:
39 break;
40 }
41 return 0; // invalid value
42 }
43
is_immediate_downstream(struct dc_link * link,uint32_t offset)44 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
45 {
46 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
47 }
48
core_link_read_dpcd(struct dc_link * link,uint32_t address,uint8_t * data,uint32_t size)49 enum dc_status core_link_read_dpcd(
50 struct dc_link *link,
51 uint32_t address,
52 uint8_t *data,
53 uint32_t size)
54 {
55 if (!link->aux_access_disabled &&
56 !dm_helpers_dp_read_dpcd(link->ctx,
57 link, address, data, size)) {
58 return DC_ERROR_UNEXPECTED;
59 }
60
61 return DC_OK;
62 }
63
core_link_write_dpcd(struct dc_link * link,uint32_t address,const uint8_t * data,uint32_t size)64 enum dc_status core_link_write_dpcd(
65 struct dc_link *link,
66 uint32_t address,
67 const uint8_t *data,
68 uint32_t size)
69 {
70 if (!link->aux_access_disabled &&
71 !dm_helpers_dp_write_dpcd(link->ctx,
72 link, address, data, size)) {
73 return DC_ERROR_UNEXPECTED;
74 }
75
76 return DC_OK;
77 }
78
dp_receiver_power_ctrl(struct dc_link * link,bool on)79 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
80 {
81 uint8_t state;
82
83 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
84
85 if (link->sync_lt_in_progress)
86 return;
87
88 core_link_write_dpcd(link, DP_SET_POWER, &state,
89 sizeof(state));
90 }
91
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)92 void dp_enable_link_phy(
93 struct dc_link *link,
94 enum signal_type signal,
95 enum clock_source_id clock_source,
96 const struct dc_link_settings *link_settings)
97 {
98 struct link_encoder *link_enc = link->link_enc;
99 struct dc *dc = link->ctx->dc;
100 struct dmcu *dmcu = dc->res_pool->dmcu;
101
102 struct pipe_ctx *pipes =
103 link->dc->current_state->res_ctx.pipe_ctx;
104 struct clock_source *dp_cs =
105 link->dc->res_pool->dp_clock_source;
106 unsigned int i;
107
108 if (link->connector_signal == SIGNAL_TYPE_EDP) {
109 link->dc->hwss.edp_power_control(link, true);
110 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
111 }
112
113 /* If the current pixel clock source is not DTO(happens after
114 * switching from HDMI passive dongle to DP on the same connector),
115 * switch the pixel clock source to DTO.
116 */
117 for (i = 0; i < MAX_PIPES; i++) {
118 if (pipes[i].stream != NULL &&
119 pipes[i].stream->link == link) {
120 if (pipes[i].clock_source != NULL &&
121 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
122 pipes[i].clock_source = dp_cs;
123 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
124 pipes[i].stream->timing.pix_clk_100hz;
125 pipes[i].clock_source->funcs->program_pix_clk(
126 pipes[i].clock_source,
127 &pipes[i].stream_res.pix_clk_params,
128 &pipes[i].pll_settings);
129 }
130 }
131 }
132
133 link->cur_link_settings = *link_settings;
134
135 if (dc->clk_mgr->funcs->notify_link_rate_change)
136 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
137
138 if (dmcu != NULL && dmcu->funcs->lock_phy)
139 dmcu->funcs->lock_phy(dmcu);
140
141 if (dc_is_dp_sst_signal(signal)) {
142 link_enc->funcs->enable_dp_output(
143 link_enc,
144 link_settings,
145 clock_source);
146 } else {
147 link_enc->funcs->enable_dp_mst_output(
148 link_enc,
149 link_settings,
150 clock_source);
151 }
152
153 if (dmcu != NULL && dmcu->funcs->unlock_phy)
154 dmcu->funcs->unlock_phy(dmcu);
155
156 dp_receiver_power_ctrl(link, true);
157 }
158
edp_receiver_ready_T9(struct dc_link * link)159 bool edp_receiver_ready_T9(struct dc_link *link)
160 {
161 unsigned int tries = 0;
162 unsigned char sinkstatus = 0;
163 unsigned char edpRev = 0;
164 enum dc_status result;
165
166 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
167
168 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
169 if (result == DC_OK && edpRev >= DP_EDP_12) {
170 do {
171 sinkstatus = 1;
172 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
173 if (sinkstatus == 0)
174 break;
175 if (result != DC_OK)
176 break;
177 udelay(100); //MAx T9
178 } while (++tries < 50);
179 }
180
181 if (link->local_sink &&
182 link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
183 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
184
185 return result;
186 }
edp_receiver_ready_T7(struct dc_link * link)187 bool edp_receiver_ready_T7(struct dc_link *link)
188 {
189 unsigned char sinkstatus = 0;
190 unsigned char edpRev = 0;
191 enum dc_status result;
192
193 /* use absolute time stamp to constrain max T7*/
194 unsigned long long enter_timestamp = 0;
195 unsigned long long finish_timestamp = 0;
196 unsigned long long time_taken_in_ns = 0;
197
198 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
199
200 if (result == DC_OK && edpRev >= DP_EDP_12) {
201 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
202 enter_timestamp = dm_get_timestamp(link->ctx);
203 do {
204 sinkstatus = 0;
205 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
206 if (sinkstatus == 1)
207 break;
208 if (result != DC_OK)
209 break;
210 udelay(25);
211 finish_timestamp = dm_get_timestamp(link->ctx);
212 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
213 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
214 }
215
216 if (link->local_sink &&
217 link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
218 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
219
220 return result;
221 }
222
dp_disable_link_phy(struct dc_link * link,enum signal_type signal)223 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
224 {
225 struct dc *dc = link->ctx->dc;
226 struct dmcu *dmcu = dc->res_pool->dmcu;
227
228 if (!link->wa_flags.dp_keep_receiver_powered)
229 dp_receiver_power_ctrl(link, false);
230
231 if (signal == SIGNAL_TYPE_EDP) {
232 if (link->dc->hwss.edp_backlight_control)
233 link->dc->hwss.edp_backlight_control(link, false);
234 link->link_enc->funcs->disable_output(link->link_enc, signal);
235 link->dc->hwss.edp_power_control(link, false);
236 } else {
237 if (dmcu != NULL && dmcu->funcs->lock_phy)
238 dmcu->funcs->lock_phy(dmcu);
239
240 link->link_enc->funcs->disable_output(link->link_enc, signal);
241
242 if (dmcu != NULL && dmcu->funcs->unlock_phy)
243 dmcu->funcs->unlock_phy(dmcu);
244 }
245
246 /* Clear current link setting.*/
247 memset(&link->cur_link_settings, 0,
248 sizeof(link->cur_link_settings));
249
250 if (dc->clk_mgr->funcs->notify_link_rate_change)
251 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
252 }
253
dp_disable_link_phy_mst(struct dc_link * link,enum signal_type signal)254 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
255 {
256 /* MST disable link only when no stream use the link */
257 if (link->mst_stream_alloc_table.stream_count > 0)
258 return;
259
260 dp_disable_link_phy(link, signal);
261
262 /* set the sink to SST mode after disabling the link */
263 dp_enable_mst_on_sink(link, false);
264 }
265
dp_set_hw_training_pattern(struct dc_link * link,enum dc_dp_training_pattern pattern,uint32_t offset)266 bool dp_set_hw_training_pattern(
267 struct dc_link *link,
268 enum dc_dp_training_pattern pattern,
269 uint32_t offset)
270 {
271 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
272
273 switch (pattern) {
274 case DP_TRAINING_PATTERN_SEQUENCE_1:
275 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
276 break;
277 case DP_TRAINING_PATTERN_SEQUENCE_2:
278 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
279 break;
280 case DP_TRAINING_PATTERN_SEQUENCE_3:
281 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
282 break;
283 case DP_TRAINING_PATTERN_SEQUENCE_4:
284 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
285 break;
286 default:
287 break;
288 }
289
290 dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
291
292 return true;
293 }
294
dp_set_hw_lane_settings(struct dc_link * link,const struct link_training_settings * link_settings,uint32_t offset)295 void dp_set_hw_lane_settings(
296 struct dc_link *link,
297 const struct link_training_settings *link_settings,
298 uint32_t offset)
299 {
300 struct link_encoder *encoder = link->link_enc;
301
302 if (link->lttpr_non_transparent_mode && !is_immediate_downstream(link, offset))
303 return;
304
305 /* call Encoder to set lane settings */
306 encoder->funcs->dp_set_lane_settings(encoder, link_settings);
307 }
308
dp_set_hw_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,uint8_t * custom_pattern,uint32_t custom_pattern_size)309 void dp_set_hw_test_pattern(
310 struct dc_link *link,
311 enum dp_test_pattern test_pattern,
312 uint8_t *custom_pattern,
313 uint32_t custom_pattern_size)
314 {
315 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
316 struct link_encoder *encoder = link->link_enc;
317
318 pattern_param.dp_phy_pattern = test_pattern;
319 pattern_param.custom_pattern = custom_pattern;
320 pattern_param.custom_pattern_size = custom_pattern_size;
321 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
322
323 encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
324 }
325
dp_retrain_link_dp_test(struct dc_link * link,struct dc_link_settings * link_setting,bool skip_video_pattern)326 void dp_retrain_link_dp_test(struct dc_link *link,
327 struct dc_link_settings *link_setting,
328 bool skip_video_pattern)
329 {
330 struct pipe_ctx *pipes =
331 &link->dc->current_state->res_ctx.pipe_ctx[0];
332 unsigned int i;
333
334 for (i = 0; i < MAX_PIPES; i++) {
335 if (pipes[i].stream != NULL &&
336 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
337 pipes[i].stream->link != NULL &&
338 pipes[i].stream_res.stream_enc != NULL &&
339 pipes[i].stream->link == link) {
340 udelay(100);
341
342 pipes[i].stream_res.stream_enc->funcs->dp_blank(
343 pipes[i].stream_res.stream_enc);
344
345 /* disable any test pattern that might be active */
346 dp_set_hw_test_pattern(link,
347 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
348
349 dp_receiver_power_ctrl(link, false);
350
351 link->dc->hwss.disable_stream(&pipes[i]);
352 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
353 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
354
355 link->link_enc->funcs->disable_output(
356 link->link_enc,
357 SIGNAL_TYPE_DISPLAY_PORT);
358
359 /* Clear current link setting. */
360 memset(&link->cur_link_settings, 0,
361 sizeof(link->cur_link_settings));
362
363 perform_link_training_with_retries(
364 link_setting,
365 skip_video_pattern,
366 LINK_TRAINING_ATTEMPTS,
367 &pipes[i],
368 SIGNAL_TYPE_DISPLAY_PORT);
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 static 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 if (dp_set_dsc_on_rx(pipe_ctx, true)) {
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