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"
15 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
18 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
22 enum dc_status core_link_read_dpcd(
28 if (!dm_helpers_dp_read_dpcd(link->ctx,
31 return DC_ERROR_UNEXPECTED;
36 enum dc_status core_link_write_dpcd(
42 if (!dm_helpers_dp_write_dpcd(link->ctx,
45 return DC_ERROR_UNEXPECTED;
50 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
54 state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
56 core_link_write_dpcd(link, DP_SET_POWER, &state,
60 void dp_enable_link_phy(
62 enum signal_type signal,
63 enum clock_source_id clock_source,
64 const struct dc_link_settings *link_settings)
66 struct link_encoder *link_enc = link->link_enc;
67 struct dc *core_dc = link->ctx->dc;
68 struct dmcu *dmcu = core_dc->res_pool->dmcu;
70 struct pipe_ctx *pipes =
71 link->dc->current_state->res_ctx.pipe_ctx;
72 struct clock_source *dp_cs =
73 link->dc->res_pool->dp_clock_source;
75 /* If the current pixel clock source is not DTO(happens after
76 * switching from HDMI passive dongle to DP on the same connector),
77 * switch the pixel clock source to DTO.
79 for (i = 0; i < MAX_PIPES; i++) {
80 if (pipes[i].stream != NULL &&
81 pipes[i].stream->link == link) {
82 if (pipes[i].clock_source != NULL &&
83 pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
84 pipes[i].clock_source = dp_cs;
85 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
86 pipes[i].stream->timing.pix_clk_100hz;
87 pipes[i].clock_source->funcs->program_pix_clk(
88 pipes[i].clock_source,
89 &pipes[i].stream_res.pix_clk_params,
90 &pipes[i].pll_settings);
95 if (dmcu != NULL && dmcu->funcs->lock_phy)
96 dmcu->funcs->lock_phy(dmcu);
98 if (dc_is_dp_sst_signal(signal)) {
99 link_enc->funcs->enable_dp_output(
104 link_enc->funcs->enable_dp_mst_output(
110 if (dmcu != NULL && dmcu->funcs->unlock_phy)
111 dmcu->funcs->unlock_phy(dmcu);
113 link->cur_link_settings = *link_settings;
115 dp_receiver_power_ctrl(link, true);
118 bool edp_receiver_ready_T9(struct dc_link *link)
120 unsigned int tries = 0;
121 unsigned char sinkstatus = 0;
122 unsigned char edpRev = 0;
123 enum dc_status result = DC_OK;
124 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
125 if (edpRev < DP_EDP_12)
127 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
130 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
135 udelay(100); //MAx T9
136 } while (++tries < 50);
138 if (link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
139 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
143 bool edp_receiver_ready_T7(struct dc_link *link)
145 unsigned int tries = 0;
146 unsigned char sinkstatus = 0;
147 unsigned char edpRev = 0;
148 enum dc_status result = DC_OK;
150 result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
151 if (result == DC_OK && edpRev < DP_EDP_12)
153 /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
156 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
161 udelay(25); //MAx T7 is 50ms
162 } while (++tries < 300);
164 if (link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
165 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
170 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
172 struct dc *core_dc = link->ctx->dc;
173 struct dmcu *dmcu = core_dc->res_pool->dmcu;
175 if (!link->wa_flags.dp_keep_receiver_powered)
176 dp_receiver_power_ctrl(link, false);
178 if (signal == SIGNAL_TYPE_EDP) {
179 link->link_enc->funcs->disable_output(link->link_enc, signal);
180 link->dc->hwss.edp_power_control(link, false);
182 if (dmcu != NULL && dmcu->funcs->lock_phy)
183 dmcu->funcs->lock_phy(dmcu);
185 link->link_enc->funcs->disable_output(link->link_enc, signal);
187 if (dmcu != NULL && dmcu->funcs->unlock_phy)
188 dmcu->funcs->unlock_phy(dmcu);
191 /* Clear current link setting.*/
192 memset(&link->cur_link_settings, 0,
193 sizeof(link->cur_link_settings));
196 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
198 /* MST disable link only when no stream use the link */
199 if (link->mst_stream_alloc_table.stream_count > 0)
202 dp_disable_link_phy(link, signal);
204 /* set the sink to SST mode after disabling the link */
205 dp_enable_mst_on_sink(link, false);
208 bool dp_set_hw_training_pattern(
209 struct dc_link *link,
210 enum hw_dp_training_pattern pattern)
212 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
215 case HW_DP_TRAINING_PATTERN_1:
216 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
218 case HW_DP_TRAINING_PATTERN_2:
219 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
221 case HW_DP_TRAINING_PATTERN_3:
222 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
224 case HW_DP_TRAINING_PATTERN_4:
225 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
231 dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
236 void dp_set_hw_lane_settings(
237 struct dc_link *link,
238 const struct link_training_settings *link_settings)
240 struct link_encoder *encoder = link->link_enc;
242 /* call Encoder to set lane settings */
243 encoder->funcs->dp_set_lane_settings(encoder, link_settings);
246 enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
248 /* We need to explicitly check that connector
249 * is not DP. Some Travis_VGA get reported
250 * by video bios as DP.
252 if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
254 switch (link->dpcd_caps.branch_dev_id) {
255 case DP_BRANCH_DEVICE_ID_2:
257 link->dpcd_caps.branch_dev_name,
258 DP_VGA_LVDS_CONVERTER_ID_2,
261 branch_dev_name)) == 0) {
262 return DP_PANEL_MODE_SPECIAL;
265 case DP_BRANCH_DEVICE_ID_3:
266 if (strncmp(link->dpcd_caps.branch_dev_name,
267 DP_VGA_LVDS_CONVERTER_ID_3,
270 branch_dev_name)) == 0) {
271 return DP_PANEL_MODE_SPECIAL;
279 if (link->dpcd_caps.panel_mode_edp) {
280 return DP_PANEL_MODE_EDP;
283 return DP_PANEL_MODE_DEFAULT;
286 void dp_set_hw_test_pattern(
287 struct dc_link *link,
288 enum dp_test_pattern test_pattern,
289 uint8_t *custom_pattern,
290 uint32_t custom_pattern_size)
292 struct encoder_set_dp_phy_pattern_param pattern_param = {0};
293 struct link_encoder *encoder = link->link_enc;
295 pattern_param.dp_phy_pattern = test_pattern;
296 pattern_param.custom_pattern = custom_pattern;
297 pattern_param.custom_pattern_size = custom_pattern_size;
298 pattern_param.dp_panel_mode = dp_get_panel_mode(link);
300 encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
303 void dp_retrain_link_dp_test(struct dc_link *link,
304 struct dc_link_settings *link_setting,
305 bool skip_video_pattern)
307 struct pipe_ctx *pipes =
308 &link->dc->current_state->res_ctx.pipe_ctx[0];
311 for (i = 0; i < MAX_PIPES; i++) {
312 if (pipes[i].stream != NULL &&
313 !pipes[i].top_pipe &&
314 pipes[i].stream->link != NULL &&
315 pipes[i].stream_res.stream_enc != NULL) {
318 pipes[i].stream_res.stream_enc->funcs->dp_blank(
319 pipes[i].stream_res.stream_enc);
321 /* disable any test pattern that might be active */
322 dp_set_hw_test_pattern(link,
323 DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
325 dp_receiver_power_ctrl(link, false);
327 link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE);
329 link->link_enc->funcs->disable_output(
331 SIGNAL_TYPE_DISPLAY_PORT);
333 /* Clear current link setting. */
334 memset(&link->cur_link_settings, 0,
335 sizeof(link->cur_link_settings));
337 link->link_enc->funcs->enable_dp_output(
340 pipes[i].clock_source->id);
341 link->cur_link_settings = *link_setting;
343 dp_receiver_power_ctrl(link, true);
345 perform_link_training_with_retries(
349 LINK_TRAINING_ATTEMPTS);
352 link->dc->hwss.enable_stream(&pipes[i]);
354 link->dc->hwss.unblank_stream(&pipes[i],
357 if (pipes[i].stream_res.audio) {
358 /* notify audio driver for
359 * audio modes of monitor */
360 pipes[i].stream_res.audio->funcs->az_enable(
361 pipes[i].stream_res.audio);
364 /* TODO: audio should be per stream rather than
366 pipes[i].stream_res.stream_enc->funcs->
368 pipes[i].stream_res.stream_enc, false);
374 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
377 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
378 struct dsc_optc_config *config)
380 DC_LOG_DSC("Setting optc DSC config at DSC inst %d", dsc->inst);
381 DC_LOG_DSC("\n\tbytes_per_pixel %d\n\tis_pixel_format_444 %d\n\tslice_width %d",
382 config->bytes_per_pixel,
383 config->is_pixel_format_444, config->slice_width);
386 static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
388 struct dc *core_dc = pipe_ctx->stream->ctx->dc;
389 struct dc_stream_state *stream = pipe_ctx->stream;
392 if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
395 result = dm_helpers_dp_write_dsc_enable(core_dc->ctx, stream, enable);
399 /* This has to be done after DSC was enabled on RX first, i.e. after dp_enable_dsc_on_rx() had been called
401 static void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
403 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
404 struct dc *core_dc = pipe_ctx->stream->ctx->dc;
405 struct dc_stream_state *stream = pipe_ctx->stream;
406 struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
409 /* TODO proper function */
410 struct dsc_config dsc_cfg;
411 struct dsc_optc_config dsc_optc_cfg;
412 enum optc_dsc_mode optc_dsc_mode;
413 uint8_t dsc_packed_pps[128];
415 /* Enable DSC hw block */
416 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
417 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
418 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
419 dsc_cfg.color_depth = stream->timing.display_color_depth;
420 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
422 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps[0]);
424 struct display_stream_compressor *bot_dsc = odm_pipe->stream_res.dsc;
425 uint8_t dsc_packed_pps_odm[128];
427 dsc_cfg.pic_width /= 2;
428 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % 2 == 0);
429 dsc_cfg.dc_dsc_cfg.num_slices_h /= 2;
430 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]);
431 bot_dsc->funcs->dsc_set_config(bot_dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]);
432 bot_dsc->funcs->dsc_enable(bot_dsc, odm_pipe->stream_res.opp->inst);
434 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
436 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
438 dsc_optc_config_log(dsc, &dsc_optc_cfg);
439 /* Enable DSC in encoder */
440 if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) && pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)
441 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
443 dsc_optc_cfg.bytes_per_pixel,
444 dsc_optc_cfg.slice_width,
447 /* Enable DSC in OPTC */
448 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
450 dsc_optc_cfg.bytes_per_pixel,
451 dsc_optc_cfg.slice_width);
453 /* disable DSC in OPTC */
454 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
455 pipe_ctx->stream_res.tg,
456 OPTC_DSC_DISABLED, 0, 0);
458 /* disable DSC in stream encoder */
459 if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
460 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
461 pipe_ctx->stream_res.stream_enc,
462 OPTC_DSC_DISABLED, 0, 0, NULL);
465 /* disable DSC block */
466 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
468 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
472 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
474 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
477 if (!pipe_ctx->stream->timing.flags.DSC)
483 if (dp_set_dsc_on_rx(pipe_ctx, true)) {
484 dp_set_dsc_on_stream(pipe_ctx, true);
488 dp_set_dsc_on_rx(pipe_ctx, false);
489 dp_set_dsc_on_stream(pipe_ctx, false);
496 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
498 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
500 if (!pipe_ctx->stream->timing.flags.DSC)
505 dp_set_dsc_on_stream(pipe_ctx, true);