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