1 /* Copyright 2015 Advanced Micro Devices, Inc. */
4 #include "dm_services.h"
6 #include "inc/core_types.h"
7 #include "include/ddc_service_types.h"
8 #include "include/i2caux_interface.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"
17 #include "link_enc_cfg.h"
20 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
22 switch (lttpr_repeater_count) {
23 case 0x80: // 1 lttpr repeater
25 case 0x40: // 2 lttpr repeaters
27 case 0x20: // 3 lttpr repeaters
29 case 0x10: // 4 lttpr repeaters
31 case 0x08: // 5 lttpr repeaters
33 case 0x04: // 6 lttpr repeaters
35 case 0x02: // 7 lttpr repeaters
37 case 0x01: // 8 lttpr repeaters
42 return 0; // invalid value
45 static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
47 return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
50 enum dc_status core_link_read_dpcd(
56 if (!link->aux_access_disabled &&
57 !dm_helpers_dp_read_dpcd(link->ctx,
58 link, address, data, size)) {
59 return DC_ERROR_UNEXPECTED;
65 enum dc_status core_link_write_dpcd(
71 if (!link->aux_access_disabled &&
72 !dm_helpers_dp_write_dpcd(link->ctx,
73 link, address, data, size)) {
74 return DC_ERROR_UNEXPECTED;
80 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
84 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
86 if (link->sync_lt_in_progress)
89 core_link_write_dpcd(link, DP_SET_POWER, &state,
93 void dp_enable_link_phy(
95 enum signal_type signal,
96 enum clock_source_id clock_source,
97 const struct dc_link_settings *link_settings)
99 struct link_encoder *link_enc;
100 struct dc *dc = link->ctx->dc;
101 struct dmcu *dmcu = dc->res_pool->dmcu;
103 struct pipe_ctx *pipes =
104 link->dc->current_state->res_ctx.pipe_ctx;
105 struct clock_source *dp_cs =
106 link->dc->res_pool->dp_clock_source;
109 /* Link should always be assigned encoder when en-/disabling. */
110 if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
111 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
113 link_enc = link->link_enc;
116 if (link->connector_signal == SIGNAL_TYPE_EDP) {
117 link->dc->hwss.edp_power_control(link, true);
118 link->dc->hwss.edp_wait_for_hpd_ready(link, true);
121 /* If the current pixel clock source is not DTO(happens after
122 * switching from HDMI passive dongle to DP on the same connector),
123 * switch the pixel clock source to DTO.
125 for (i = 0; i < MAX_PIPES; i++) {
126 if (pipes[i].stream != NULL &&
127 pipes[i].stream->link == link) {
128 if (pipes[i].clock_source != NULL &&
129 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
130 pipes[i].clock_source = dp_cs;
131 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
132 pipes[i].stream->timing.pix_clk_100hz;
133 pipes[i].clock_source->funcs->program_pix_clk(
134 pipes[i].clock_source,
135 &pipes[i].stream_res.pix_clk_params,
136 &pipes[i].pll_settings);
141 link->cur_link_settings = *link_settings;
143 if (dc->clk_mgr->funcs->notify_link_rate_change)
144 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
146 if (dmcu != NULL && dmcu->funcs->lock_phy)
147 dmcu->funcs->lock_phy(dmcu);
149 if (dc_is_dp_sst_signal(signal)) {
150 link_enc->funcs->enable_dp_output(
155 link_enc->funcs->enable_dp_mst_output(
161 if (dmcu != NULL && dmcu->funcs->unlock_phy)
162 dmcu->funcs->unlock_phy(dmcu);
164 dp_receiver_power_ctrl(link, true);
167 void edp_add_delay_for_T9(struct dc_link *link)
169 if (link->local_sink &&
170 link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
171 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
174 bool edp_receiver_ready_T9(struct dc_link *link)
176 unsigned int tries = 0;
177 unsigned char sinkstatus = 0;
178 unsigned char edpRev = 0;
179 enum dc_status result;
181 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
183 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
184 if (result == DC_OK && edpRev >= DP_EDP_12) {
187 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
192 udelay(100); //MAx T9
193 } while (++tries < 50);
198 bool edp_receiver_ready_T7(struct dc_link *link)
200 unsigned char sinkstatus = 0;
201 unsigned char edpRev = 0;
202 enum dc_status result;
204 /* use absolute time stamp to constrain max T7*/
205 unsigned long long enter_timestamp = 0;
206 unsigned long long finish_timestamp = 0;
207 unsigned long long time_taken_in_ns = 0;
209 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
211 if (result == DC_OK && edpRev >= DP_EDP_12) {
212 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
213 enter_timestamp = dm_get_timestamp(link->ctx);
216 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
222 finish_timestamp = dm_get_timestamp(link->ctx);
223 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
224 } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
227 if (link->local_sink &&
228 link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
229 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
234 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
236 struct dc *dc = link->ctx->dc;
237 struct dmcu *dmcu = dc->res_pool->dmcu;
238 struct link_encoder *link_enc;
240 /* Link should always be assigned encoder when en-/disabling. */
241 if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
242 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
244 link_enc = link->link_enc;
247 if (!link->wa_flags.dp_keep_receiver_powered)
248 dp_receiver_power_ctrl(link, false);
250 if (signal == SIGNAL_TYPE_EDP) {
251 if (link->dc->hwss.edp_backlight_control)
252 link->dc->hwss.edp_backlight_control(link, false);
253 link_enc->funcs->disable_output(link_enc, signal);
254 link->dc->hwss.edp_power_control(link, false);
256 if (dmcu != NULL && dmcu->funcs->lock_phy)
257 dmcu->funcs->lock_phy(dmcu);
259 link_enc->funcs->disable_output(link_enc, signal);
261 if (dmcu != NULL && dmcu->funcs->unlock_phy)
262 dmcu->funcs->unlock_phy(dmcu);
265 /* Clear current link setting.*/
266 memset(&link->cur_link_settings, 0,
267 sizeof(link->cur_link_settings));
269 if (dc->clk_mgr->funcs->notify_link_rate_change)
270 dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
273 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
275 /* MST disable link only when no stream use the link */
276 if (link->mst_stream_alloc_table.stream_count > 0)
279 dp_disable_link_phy(link, signal);
281 /* set the sink to SST mode after disabling the link */
282 dp_enable_mst_on_sink(link, false);
285 bool dp_set_hw_training_pattern(
286 struct dc_link *link,
287 enum dc_dp_training_pattern pattern,
290 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
293 case DP_TRAINING_PATTERN_SEQUENCE_1:
294 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
296 case DP_TRAINING_PATTERN_SEQUENCE_2:
297 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
299 case DP_TRAINING_PATTERN_SEQUENCE_3:
300 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
302 case DP_TRAINING_PATTERN_SEQUENCE_4:
303 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
309 dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
314 void dp_set_hw_lane_settings(
315 struct dc_link *link,
316 const struct link_training_settings *link_settings,
319 struct link_encoder *encoder = link->link_enc;
321 if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
324 /* call Encoder to set lane settings */
325 encoder->funcs->dp_set_lane_settings(encoder, link_settings);
328 void dp_set_hw_test_pattern(
329 struct dc_link *link,
330 enum dp_test_pattern test_pattern,
331 uint8_t *custom_pattern,
332 uint32_t custom_pattern_size)
334 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
335 struct link_encoder *encoder = link->link_enc;
337 pattern_param.dp_phy_pattern = test_pattern;
338 pattern_param.custom_pattern = custom_pattern;
339 pattern_param.custom_pattern_size = custom_pattern_size;
340 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
342 encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
345 void dp_retrain_link_dp_test(struct dc_link *link,
346 struct dc_link_settings *link_setting,
347 bool skip_video_pattern)
349 struct pipe_ctx *pipes =
350 &link->dc->current_state->res_ctx.pipe_ctx[0];
353 for (i = 0; i < MAX_PIPES; i++) {
354 if (pipes[i].stream != NULL &&
355 !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
356 pipes[i].stream->link != NULL &&
357 pipes[i].stream_res.stream_enc != NULL &&
358 pipes[i].stream->link == link) {
361 pipes[i].stream_res.stream_enc->funcs->dp_blank(
362 pipes[i].stream_res.stream_enc);
364 /* disable any test pattern that might be active */
365 dp_set_hw_test_pattern(link,
366 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
368 dp_receiver_power_ctrl(link, false);
370 link->dc->hwss.disable_stream(&pipes[i]);
371 if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
372 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
374 link->link_enc->funcs->disable_output(
376 SIGNAL_TYPE_DISPLAY_PORT);
378 /* Clear current link setting. */
379 memset(&link->cur_link_settings, 0,
380 sizeof(link->cur_link_settings));
382 perform_link_training_with_retries(
385 LINK_TRAINING_ATTEMPTS,
387 SIGNAL_TYPE_DISPLAY_PORT);
389 link->dc->hwss.enable_stream(&pipes[i]);
391 link->dc->hwss.unblank_stream(&pipes[i],
394 if (pipes[i].stream_res.audio) {
395 /* notify audio driver for
396 * audio modes of monitor */
397 pipes[i].stream_res.audio->funcs->az_enable(
398 pipes[i].stream_res.audio);
401 /* TODO: audio should be per stream rather than
403 pipes[i].stream_res.stream_enc->funcs->
405 pipes[i].stream_res.stream_enc, false);
413 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
414 struct dsc_optc_config *config)
416 uint32_t precision = 1 << 28;
417 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
418 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
419 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
421 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
422 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
423 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
425 ll_bytes_per_pix_fraq *= 10000000;
426 ll_bytes_per_pix_fraq /= precision;
428 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
429 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
430 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
431 DC_LOG_DSC("\tslice_width %d", config->slice_width);
434 bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
436 struct dc *dc = pipe_ctx->stream->ctx->dc;
437 struct dc_stream_state *stream = pipe_ctx->stream;
440 if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
443 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
447 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
448 * i.e. after dp_enable_dsc_on_rx() had been called
450 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
452 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
453 struct dc *dc = pipe_ctx->stream->ctx->dc;
454 struct dc_stream_state *stream = pipe_ctx->stream;
455 struct pipe_ctx *odm_pipe;
458 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
462 struct dsc_config dsc_cfg;
463 struct dsc_optc_config dsc_optc_cfg;
464 enum optc_dsc_mode optc_dsc_mode;
466 /* Enable DSC hw block */
467 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
468 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
469 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
470 dsc_cfg.color_depth = stream->timing.display_color_depth;
471 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
472 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
473 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
474 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
476 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
477 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
478 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
479 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
481 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
482 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
484 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
485 dsc_cfg.pic_width *= opp_cnt;
487 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
489 /* Enable DSC in encoder */
490 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
491 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
492 dsc_optc_config_log(dsc, &dsc_optc_cfg);
493 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
495 dsc_optc_cfg.bytes_per_pixel,
496 dsc_optc_cfg.slice_width);
498 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
501 /* Enable DSC in OPTC */
502 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
503 dsc_optc_config_log(dsc, &dsc_optc_cfg);
504 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
506 dsc_optc_cfg.bytes_per_pixel,
507 dsc_optc_cfg.slice_width);
509 /* disable DSC in OPTC */
510 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
511 pipe_ctx->stream_res.tg,
512 OPTC_DSC_DISABLED, 0, 0);
514 /* disable DSC in stream encoder */
515 if (dc_is_dp_signal(stream->signal)) {
517 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
518 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
519 pipe_ctx->stream_res.stream_enc,
520 OPTC_DSC_DISABLED, 0, 0);
521 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
522 pipe_ctx->stream_res.stream_enc, false, NULL);
526 /* disable DSC block */
527 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
528 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
529 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
533 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
535 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
538 if (!pipe_ctx->stream->timing.flags.DSC)
545 dp_set_dsc_on_stream(pipe_ctx, true);
549 dp_set_dsc_on_rx(pipe_ctx, false);
550 dp_set_dsc_on_stream(pipe_ctx, false);
557 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
559 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
560 struct dc_stream_state *stream = pipe_ctx->stream;
562 if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
566 struct dsc_config dsc_cfg;
567 uint8_t dsc_packed_pps[128];
569 memset(&dsc_cfg, 0, sizeof(dsc_cfg));
570 memset(dsc_packed_pps, 0, 128);
572 /* Enable DSC hw block */
573 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
574 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
575 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
576 dsc_cfg.color_depth = stream->timing.display_color_depth;
577 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
578 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
581 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
582 if (dc_is_dp_signal(stream->signal)) {
583 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
584 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
585 pipe_ctx->stream_res.stream_enc,
590 /* disable DSC PPS in stream encoder */
591 if (dc_is_dp_signal(stream->signal)) {
592 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
593 pipe_ctx->stream_res.stream_enc, false, NULL);
601 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
603 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
605 if (!pipe_ctx->stream->timing.flags.DSC)
610 dp_set_dsc_on_stream(pipe_ctx, true);
611 dp_set_dsc_pps_sdp(pipe_ctx, true);