This patch adds HW Sequencer support for FRL programming, which ties the HW programming for the different blocks together for FRL.
Signed-off-by: Harry Wentland <[email protected]> --- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 99 +++++++++++++++++-- .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 37 +++++++ .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 19 +++- .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 49 ++++++++- .../amd/display/dc/hwss/dcn30/dcn30_hwseq.h | 16 +++ .../amd/display/dc/hwss/dcn30/dcn30_init.c | 1 + .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 13 ++- .../amd/display/dc/hwss/dcn31/dcn31_init.c | 1 + .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn314/dcn314_init.c | 1 + .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 13 ++- .../amd/display/dc/hwss/dcn32/dcn32_init.c | 3 + .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 42 ++++++++ .../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 + .../amd/display/dc/hwss/dcn35/dcn35_init.c | 2 + .../amd/display/dc/hwss/dcn351/dcn351_init.c | 2 + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 13 +++ .../amd/display/dc/hwss/dcn401/dcn401_init.c | 1 + .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 38 ++++++- .../amd/display/dc/hwss/dcn42/dcn42_init.c | 2 + .../drm/amd/display/dc/hwss/hw_sequencer.h | 32 ++++++ .../display/dc/hwss/hw_sequencer_private.h | 3 + 22 files changed, 373 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 7af239524d71..236ea3f7b36a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -1192,6 +1192,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc); } + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_res.hpo_frl_stream_enc); if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.hpo_dp_stream_enc); @@ -1216,6 +1219,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) } } } else if (dccg && dccg->funcs->disable_symclk_se) { + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_FRL) dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); } @@ -1287,6 +1291,18 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) link->dc->link_srv->edp_receiver_ready_T9(link); } + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_blank(pipe_ctx->stream_res.hpo_frl_stream_enc); + + /* Set HDMISTREAMCLK source to REFCLK */ + if (link->dc->res_pool->dccg && + link->dc->res_pool->dccg->funcs->set_hdmistreamclk) { + link->dc->res_pool->dccg->funcs->set_hdmistreamclk( + link->dc->res_pool->dccg, + REFCLK, + pipe_ctx->stream_res.tg->inst); + } + } } @@ -1476,9 +1492,32 @@ void build_audio_output( } } + if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_FRL) { + switch (pipe_ctx->stream->link->frl_link_settings.frl_link_rate) { + case HDMI_FRL_LINK_RATE_3GBPS: + audio_output->crtc_info.frl_character_clock_kHz = 166667; + break; + case HDMI_FRL_LINK_RATE_6GBPS: + case HDMI_FRL_LINK_RATE_6GBPS_4LANE: + audio_output->crtc_info.frl_character_clock_kHz = 333333; + break; + case HDMI_FRL_LINK_RATE_8GBPS: + audio_output->crtc_info.frl_character_clock_kHz = 444444; + break; + case HDMI_FRL_LINK_RATE_10GBPS: + audio_output->crtc_info.frl_character_clock_kHz = 555555; + break; + case HDMI_FRL_LINK_RATE_12GBPS: + default: + audio_output->crtc_info.frl_character_clock_kHz = 666667; + break; + } + } else + audio_output->crtc_info.frl_character_clock_kHz = 0; if (state->clk_mgr && (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_FRL || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) { audio_output->pll_info.audio_dto_source_clock_in_khz = state->clk_mgr->funcs->get_dp_ref_clk_frequency( @@ -1724,7 +1763,8 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.tg, event_triggers, 2); if (!dc_is_virtual_signal(pipe_ctx->stream->signal) && - !dc_is_rgb_signal(pipe_ctx->stream->signal)) + !dc_is_rgb_signal(pipe_ctx->stream->signal) && + !dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst); @@ -2476,7 +2516,8 @@ static void dce110_setup_audio_dto( if (pipe_ctx->top_pipe) continue; - if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A && + pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_FRL) continue; if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; @@ -2485,15 +2526,27 @@ static void dce110_setup_audio_dto( if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) { struct dtbclk_dto_params dto_params = {0}; + dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); - dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( - dc->res_pool->dccg, &dto_params); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_FRL) { + /* For DCN3.1, audio to HPO FRL encoder is using audio DTBCLK DTO */ + /* set audio DTBCLK DTO to 24MHz */ + dto_params.req_audio_dtbclk_khz = 24000; + dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( + dc->res_pool->dccg, + &dto_params); + } else { + /* Audio DTBCLK params default to disabled */ + dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( + dc->res_pool->dccg, + &dto_params); - pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); + } } else pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, @@ -2523,11 +2576,37 @@ static void dce110_setup_audio_dto( build_audio_output(context, pipe_ctx, &audio_output); - pipe_ctx->stream_res.audio->funcs->wall_dto_setup( - pipe_ctx->stream_res.audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); + /* Audio to HPO DP encoder is using audio DTBCLK DTO */ + if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) { + struct dtbclk_dto_params dto_params = {0}; + dto_params.ref_dtbclk_khz = + dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); + + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { + /* set audio DTBCLK DTO to 24MHz */ + dto_params.req_audio_dtbclk_khz = 24000; + dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( + dc->res_pool->dccg, + &dto_params); + } else { + /* Audio DTBCLK params default to disabled */ + dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( + dc->res_pool->dccg, + &dto_params); + + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + } + } else { + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + } break; } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 566edc05b99d..a2fc6846564b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -752,6 +752,43 @@ void dcn10_log_hw_state(struct dc *dc, log_mpc_crc(dc, log_ctx); + for (i = 0; i < pool->hpo_frl_stream_enc_count; i++) { + struct hpo_frl_stream_encoder_state hpo_se_state = {0}; + struct hpo_frl_link_enc_state hpo_le_state = {0}; + struct hpo_frl_stream_encoder *hpo_frl_stream_enc = pool->hpo_frl_stream_enc[i]; + struct hpo_frl_link_encoder *hpo_frl_link_enc = dc->links[i]->hpo_frl_link_enc; + bool printed_header = false; + + hpo_frl_stream_enc->funcs->read_state(hpo_frl_stream_enc, &hpo_se_state); + if (hpo_se_state.stream_enc_enabled) + hpo_frl_link_enc->funcs->read_state(hpo_frl_link_enc, &hpo_le_state); + + /* Only print if HPO link is enabled */ + if ((hpo_se_state.stream_enc_enabled == 0) + || (hpo_le_state.link_enc_enabled == 0)) + continue; + if (!printed_header) { + DTN_INFO("\n"); + DTN_INFO("HPO: OTG Inst Link Pixel Format Depth ODM Segments Lanes Borrow h_active h_blank\n"); + printed_header = true; + } + + DTN_INFO("[%d]: %10d %6s %10s %5d %5d %5d %6s %5d %5d\n", + hpo_frl_stream_enc->id - ENGINE_ID_HPO_0, + hpo_se_state.otg_inst, + hpo_le_state.link_active ? "Active" : "Training", + (hpo_se_state.pixel_format == PIXEL_ENCODING_YCBCR420) ? "4:2:0" : + ((hpo_se_state.pixel_format == PIXEL_ENCODING_YCBCR422) ? "4:2:2" : "4:4:4"), + hpo_se_state.color_depth, + hpo_se_state.num_odm_segments, + hpo_le_state.lane_count, + (hpo_se_state.borrow_mode == 0) ? "NONE" : + ((hpo_se_state.borrow_mode == 1) ? "ACTIVE" : "BLANK"), + hpo_se_state.h_active, + hpo_se_state.h_blank); + } + DTN_INFO("\n"); + { if (pool->hpo_dp_stream_enc_count > 0) { DTN_INFO("DP HPO S_ENC: Enabled OTG Format Depth Vid SDP Compressed Link\n"); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index c2ea0106fdec..8b382b4e10f1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -917,6 +917,11 @@ enum dc_status dcn20_enable_stream_timing( pipe_ctx->stream->signal, true); + /* Must use manual div mode for FRL */ + if (pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode) { + bool manual_mode = dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) || !is_h_timing_divisible_by_2(stream) || dc_is_virtual_signal(pipe_ctx->stream->signal); + pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode(pipe_ctx->stream_res.tg, manual_mode); + } rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1; flow_control.flow_ctrl_mode = 0; flow_control.flow_ctrl_cnt0 = 0x80; @@ -2785,6 +2790,16 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); } + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { + if (params.opp_cnt == 4) + params.timing.pix_clk_100hz /= 4; + else if (is_two_pixels_per_container || params.opp_cnt > 1) + params.timing.pix_clk_100hz /= 2; + if (link->link_status.link_active && link->frl_link_settings.frl_link_rate != 0) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_unblank( + pipe_ctx->stream_res.hpo_frl_stream_enc, + pipe_ctx->stream_res.tg->inst); + } if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { hws->funcs.edp_backlight_control(link, true); } @@ -3052,7 +3067,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); } } else { - if (dccg->funcs->enable_symclk_se && link_enc) { + if (dccg->funcs->enable_symclk_se + && link_enc + && pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_FRL) { if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->cur_link_settings.link_rate == LINK_RATE_UNKNOWN && !link->link_status.link_active) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index 2705c58a9150..cfca7af6cd1f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -836,6 +836,10 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) if (pipe_ctx == NULL) return; + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.hpo_frl_stream_enc != NULL) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->set_avmute( + pipe_ctx->stream_res.hpo_frl_stream_enc, + enable); if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) { pipe_ctx->stream_res.stream_enc->funcs->set_avmute( pipe_ctx->stream_res.stream_enc, @@ -856,22 +860,29 @@ void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx) { bool is_hdmi_tmds; bool is_dp; + bool is_hdmi_frl; ASSERT(pipe_ctx->stream); - if (pipe_ctx->stream_res.stream_enc == NULL) + if (pipe_ctx->stream_res.stream_enc == NULL && + pipe_ctx->stream_res.hpo_frl_stream_enc == NULL) return; /* this is not root pipe */ is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); - if (!is_hdmi_tmds && !is_dp) + is_hdmi_frl = dc_is_hdmi_frl_signal(pipe_ctx->stream->signal); + if (!is_hdmi_tmds && !is_dp && !is_hdmi_frl) return; if (is_hdmi_tmds) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); + else if (is_hdmi_frl) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_res.hpo_frl_stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); else { if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num) pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num( @@ -890,6 +901,7 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) struct hubp *hubp = pipe_ctx->plane_res.hubp; bool enable = false; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + struct hpo_frl_stream_encoder *hpo_enc = pipe_ctx->stream_res.hpo_frl_stream_enc; enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal) ? dmdata_dp : dmdata_hdmi; @@ -903,11 +915,44 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) if (!hubp) return; + if (dc_is_hdmi_frl_signal(stream->signal)) { + ASSERT(mode == dmdata_hdmi); + + if (!hpo_enc || !hpo_enc->funcs->set_dynamic_metadata) + return; + + hpo_enc->funcs->set_dynamic_metadata(hpo_enc, enable, + hubp->inst, dmdata_hdmi); + } else { if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata) return; stream_enc->funcs->set_dynamic_metadata(stream_enc, enable, hubp->inst, mode); + } +} +enum dc_status dcn30_setup_hdmi_frl_link( + struct dc_link *link, + int hpo_inst, + enum clock_source_id frl_phy_clock_source_id) +{ + (void)hpo_inst; + enum dc_status status = DC_OK; + struct dc *dc = link->ctx->dc; + + if ((!link->link_enc) || + (!link->hpo_frl_link_enc) || + (!dc->res_pool->dccg->funcs->enable_hdmicharclk)) + return DC_ERROR_UNEXPECTED; + + //Enable phy output for FRL case + link->hpo_frl_link_enc->funcs->enable_frl_phy_output( + link->hpo_frl_link_enc, + link->link_enc, + frl_phy_clock_source_id, + link->frl_link_settings.frl_link_rate); + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + return status; } bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h index 40afbbfb5b9c..2306354e90af 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h @@ -72,6 +72,22 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx); void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx); +enum dc_status dcn30_setup_hdmi_frl_link( + struct dc_link *link, + int hpo_inst, + enum clock_source_id frl_phy_clock_source_id); +void dcn30_hw_set_fva_vrr_adj(struct dc *dc, struct pipe_ctx **pipe_ctx, int num_pipes, + struct fva_adj *fva_adj, + struct dc_crtc_timing_adjust *vrr_adj); + +int dcn30_hw_get_max_fva_factor(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct dc_crtc_timing *timing, + unsigned int max_pixel_clock); + +void dcn30_hw_set_vstartup_dsc_frl(struct dc *dc, + struct pipe_ctx *pipe_ctx); + bool dcn30_does_plane_fit_in_mall(struct dc *dc, unsigned int pitch, unsigned int height, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c index 5cbae0cdda96..26c7386a8a36 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c @@ -105,6 +105,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .enable_tmds_link_output = dce110_enable_tmds_link_output, .enable_dp_link_output = dce110_enable_dp_link_output, .disable_link_output = dce110_disable_link_output, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .update_visual_confirm_color = dcn10_update_visual_confirm_color, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index b4afb2bc4493..fd8311ad4fa6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -104,6 +104,8 @@ static void enable_memory_low_power(struct dc *dc) dc->res_pool->stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->stream_enc[i]->vpg); for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) dc->res_pool->hpo_dp_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_dp_stream_enc[i]->vpg); + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) + dc->res_pool->hpo_frl_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_frl_stream_enc[i]->vpg); } } @@ -377,22 +379,29 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) { bool is_hdmi_tmds; bool is_dp; + bool is_hdmi_frl; ASSERT(pipe_ctx->stream); - if (pipe_ctx->stream_res.stream_enc == NULL) + if (pipe_ctx->stream_res.stream_enc == NULL && + pipe_ctx->stream_res.hpo_frl_stream_enc == NULL) return; /* this is not root pipe */ is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); - if (!is_hdmi_tmds && !is_dp) + is_hdmi_frl = dc_is_hdmi_frl_signal(pipe_ctx->stream->signal); + if (!is_hdmi_tmds && !is_dp && !is_hdmi_frl) return; if (is_hdmi_tmds) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); + else if (is_hdmi_frl) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_res.hpo_frl_stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); else if (pipe_ctx->stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { if (pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->update_dp_info_packets_sdp_line_num) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->update_dp_info_packets_sdp_line_num( diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c index e56b9a46aecf..23b30d6f3956 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c @@ -98,6 +98,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c index 1e856ee508f1..1ee862972584 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c @@ -335,7 +335,8 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); - if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) || + stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c index 9900c87b4567..98771fc443c7 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c @@ -100,6 +100,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 7dbaaf9403f2..34f9b3624011 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -1205,7 +1205,8 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); - if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) || + stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) { @@ -1351,6 +1352,16 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); } + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { + if (params.opp_cnt == 4) + params.timing.pix_clk_100hz /= 4; + else if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || params.opp_cnt > 1) + params.timing.pix_clk_100hz /= 2; + if (link->link_status.link_active && link->frl_link_settings.frl_link_rate != 0) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_unblank( + pipe_ctx->stream_res.hpo_frl_stream_enc, + pipe_ctx->stream_res.tg->inst); + } if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) hws->funcs.edp_backlight_control(link, true); } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c index 849dae18b738..0b3e8512ebf1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c @@ -31,6 +31,7 @@ #include "dcn31/dcn31_hwseq.h" #include "dcn32/dcn32_hwseq.h" #include "dcn401/dcn401_hwseq.h" +#include "dml/dcn32/dcn32_fpu.h" #include "dcn32_init.h" static const struct hw_sequencer_funcs dcn32_funcs = { @@ -96,6 +97,8 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, + .get_max_dispclk_mhz = dcn32_get_max_dispclk_mhz, .apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations, .does_plane_fit_in_mall = NULL, .set_backlight_level = dcn31_set_backlight_level, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 894d48fcd7f8..6de4cd32bdad 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -110,6 +110,8 @@ static void enable_memory_low_power(struct dc *dc) for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) dc->res_pool->hpo_dp_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_dp_stream_enc[i]->vpg); #endif + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) + dc->res_pool->hpo_frl_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_frl_stream_enc[i]->vpg); } } @@ -439,6 +441,9 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * opp_cnt = get_odm_config(pipe_ctx, opp_inst); + if (!(pipe_ctx->stream_res.hpo_frl_stream_enc && + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_fifo_odm_enabled && + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_fifo_odm_enabled(pipe_ctx->stream_res.hpo_frl_stream_enc))) { if (opp_cnt > 1) pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg, @@ -463,6 +468,7 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * odm_pipe->stream_res.opp, true); } + } if (pipe_ctx->stream_res.dsc) { struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; @@ -501,6 +507,17 @@ void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hp } } +void dcn35_hdmistream_root_clock_control(struct dce_hwseq *hws, bool clock_on) +{ + if (!hws->ctx->dc->debug.root_clock_optimization.bits.hdmistream) + return; + + if (hws->ctx->dc->res_pool->dccg->funcs->set_hdmistreamclk_root_clock_gating) { + hws->ctx->dc->res_pool->dccg->funcs->set_hdmistreamclk_root_clock_gating( + hws->ctx->dc->res_pool->dccg, clock_on); + } +} + void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on) { if (!hws->ctx->dc->debug.root_clock_optimization.bits.physymclk) @@ -928,6 +945,14 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, memset(update_state, 0, sizeof(struct pg_block_update)); + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_frl_stream_enc_acquired[i] && + dc->res_pool->hpo_frl_stream_enc[i]) { + hpo_frl_stream_enc_acquired = true; + break; + } + } + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && dc->res_pool->hpo_dp_stream_enc[i]) { @@ -983,6 +1008,9 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false; } + if (hpo_frl_stream_enc_acquired) + update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = false; + for (i = 0; i < dc->link_count; i++) { update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true; if (dc->links[i]->type != dc_connection_none) @@ -1104,6 +1132,14 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, if (dc->links[i]->type != dc_connection_none) update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true; + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_frl_stream_enc_acquired[i] && + dc->res_pool->hpo_frl_stream_enc[i]) { + hpo_frl_stream_enc_acquired = true; + break; + } + } + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && dc->res_pool->hpo_dp_stream_enc[i]) { @@ -1320,6 +1356,9 @@ void dcn35_root_clock_control(struct dc *dc, if (dc->hwseq->funcs.physymclk_root_clock_control) dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + if (update_state->pg_pipe_res_update[PG_HDMISTREAM][0]) + if (dc->hwseq->funcs.hdmistream_root_clock_control) + dc->hwseq->funcs.hdmistream_root_clock_control(dc->hwseq, power_on); } for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { if (update_state->pg_pipe_res_update[PG_DSC][i]) { @@ -1350,6 +1389,9 @@ void dcn35_root_clock_control(struct dc *dc, if (dc->hwseq->funcs.physymclk_root_clock_control) dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + if (update_state->pg_pipe_res_update[PG_HDMISTREAM][0]) + if (dc->hwseq->funcs.hdmistream_root_clock_control) + dc->hwseq->funcs.hdmistream_root_clock_control(dc->hwseq, power_on); } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index e3459546a908..235ebf00bd1f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -39,6 +39,8 @@ void dcn35_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hpo_inst, bool clock_on); +void dcn35_hdmistream_root_clock_control(struct dce_hwseq *hws, bool clock_on); + void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 6ac8ad97cf13..fc18d2207711 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -107,6 +107,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .set_backlight_level = dcn31_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, @@ -158,6 +159,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { //.hubp_pg_control = dcn35_hubp_pg_control, .dpp_root_clock_control = dcn35_dpp_root_clock_control, .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, + .hdmistream_root_clock_control = dcn35_hdmistream_root_clock_control, .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index 04c260015eec..19ec5b4edfdc 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -100,6 +100,7 @@ static const struct hw_sequencer_funcs dcn351_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .set_backlight_level = dcn31_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, @@ -147,6 +148,7 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { //.hubp_pg_control = dcn35_hubp_pg_control, .dpp_root_clock_control = dcn35_dpp_root_clock_control, .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, + .hdmistream_root_clock_control = dcn35_hdmistream_root_clock_control, .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 9c505a8a773c..a0be7e15b9ca 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -638,6 +638,9 @@ static void enable_stream_timing_calc( stream->link->phy_state.symclk_state = SYMCLK_ON_TX_ON; } + if (pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode) { + *manual_mode = !is_h_timing_divisible_by_2(stream); + } params->vertical_total_min = stream->adjust.v_total_min; params->vertical_total_max = stream->adjust.v_total_max; params->vertical_total_mid = stream->adjust.v_total_mid; @@ -695,6 +698,8 @@ enum dc_status dcn401_enable_stream_timing( if (dc->res_pool->dccg->funcs->set_dtbclk_p_src) { if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, DPREFCLK, pipe_ctx->stream_res.tg->inst); + } else if (dc_is_hdmi_frl_signal(stream->signal)) { + dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, DTBCLK0, pipe_ctx->stream_res.tg->inst); } } @@ -733,6 +738,8 @@ enum dc_status dcn401_enable_stream_timing( pipe_ctx->stream->signal, true); + if (pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode) + pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode(pipe_ctx->stream_res.tg, manual_mode); for (i = 0; i < opp_cnt; i++) { opp_heads[i]->stream_res.opp->funcs->opp_pipe_clock_control( opp_heads[i]->stream_res.opp, @@ -1691,6 +1698,12 @@ void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx, pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); } + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { + if (link->link_status.link_active && link->frl_link_settings.frl_link_rate != 0) + pipe_ctx->stream_res.hpo_frl_stream_enc->funcs->hdmi_frl_unblank( + pipe_ctx->stream_res.hpo_frl_stream_enc, + pipe_ctx->stream_res.tg->inst); + } if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) hws->funcs.edp_backlight_control(link, true); } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c index 5d0dfb36f3e1..d24a352937b4 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c @@ -84,6 +84,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .apply_idle_power_optimizations = dcn401_apply_idle_power_optimizations, .does_plane_fit_in_mall = NULL, .set_backlight_level = dcn31_set_backlight_level, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c index 46f2f9833d9e..31dca33fdf8f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c @@ -546,6 +546,14 @@ void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, update_state->pg_res_update[PG_DIO] = true; + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_frl_stream_enc_acquired[i] && + dc->res_pool->hpo_frl_stream_enc[i]) { + hpo_frl_stream_enc_acquired = true; + break; + } + } + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && dc->res_pool->hpo_dp_stream_enc[i]) { @@ -591,11 +599,14 @@ void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, if (pipe_ctx->link_res.dio_link_enc) { update_state->pg_res_update[PG_DIO] = false; } - if (pipe_ctx->link_res.hpo_dp_link_enc) { + if (pipe_ctx->link_res.hpo_dp_link_enc + || pipe_ctx->link_res.hpo_frl_link_enc) { update_state->pg_res_update[PG_HPO] = false; } } + if (hpo_frl_stream_enc_acquired) + update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = false; for (i = 0; i < dc->link_count; i++) { update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true; @@ -615,6 +626,12 @@ void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, } } + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) { + if (dc->current_state->res_ctx.is_hpo_frl_stream_enc_acquired[i]) { + update_state->pg_res_update[PG_HPO] = false; + break; + } + } } void dcn42_prepare_bandwidth( @@ -662,6 +679,7 @@ void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context) void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, struct pg_block_update *update_state) { + bool hpo_frl_stream_enc_acquired = false; bool hpo_dp_stream_enc_acquired = false; int i = 0, j = 0; @@ -747,6 +765,14 @@ void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, break; } } + for (i = 0; i < dc->res_pool->hpo_frl_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_frl_stream_enc_acquired[i] && + dc->res_pool->hpo_frl_stream_enc[i]) { + hpo_frl_stream_enc_acquired = true; + break; + } + } + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && dc->res_pool->hpo_dp_stream_enc[i]) { @@ -755,9 +781,11 @@ void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, } } - if (hpo_dp_stream_enc_acquired) + if (hpo_frl_stream_enc_acquired || hpo_dp_stream_enc_acquired) update_state->pg_res_update[PG_HPO] = true; + if (hpo_frl_stream_enc_acquired) + update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true; if (count_active_streams(dc) > 0) { update_state->pg_res_update[PG_DCCG] = true; update_state->pg_res_update[PG_DCIO] = true; @@ -967,6 +995,9 @@ void dcn42_root_clock_control(struct dc *dc, if (dc->hwseq->funcs.physymclk_root_clock_control) dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + if (update_state->pg_pipe_res_update[PG_HDMISTREAM][0]) + if (dc->hwseq->funcs.hdmistream_root_clock_control) + dc->hwseq->funcs.hdmistream_root_clock_control(dc->hwseq, power_on); } for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { if (update_state->pg_pipe_res_update[PG_DSC][i]) { @@ -997,6 +1028,9 @@ void dcn42_root_clock_control(struct dc *dc, if (dc->hwseq->funcs.physymclk_root_clock_control) dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + if (update_state->pg_pipe_res_update[PG_HDMISTREAM][0]) + if (dc->hwseq->funcs.hdmistream_root_clock_control) + dc->hwseq->funcs.hdmistream_root_clock_control(dc->hwseq, power_on); } } void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c index b324a2195e8a..49c13611a518 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c @@ -85,6 +85,7 @@ static const struct hw_sequencer_funcs dcn42_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .setup_hdmi_frl_link = dcn30_setup_hdmi_frl_link, .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, .does_plane_fit_in_mall = NULL, .set_backlight_level = dcn31_set_backlight_level, @@ -159,6 +160,7 @@ static const struct hwseq_private_funcs dcn42_private_funcs = { .program_cm_hist = dcn42_program_cm_hist, .dpp_root_clock_control = dcn35_dpp_root_clock_control, .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, + .hdmistream_root_clock_control = dcn35_hdmistream_root_clock_control, .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio, .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index 7f0743de1b14..7e65ccd11386 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -806,6 +806,10 @@ struct stream_enc_update_hdmi_info_packets_params { struct pipe_ctx *pipe_ctx; }; +struct hpo_frl_stream_enc_update_hdmi_info_packets_params { + struct pipe_ctx *pipe_ctx; +}; + struct hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num_params { struct pipe_ctx *pipe_ctx; }; @@ -847,6 +851,12 @@ struct stream_enc_dp_set_dsc_pps_info_packet_params { bool pps_sdp_stream; }; +struct hpo_frl_stream_enc_set_dsc_config_params { + struct hpo_frl_stream_encoder *hpo_frl_stream_enc; + const struct dc_crtc_timing *timing; + uint8_t *dsc_packed_pps; +}; + struct dp_trace_source_sequence_params { struct dc_link *link; enum dpcd_source_sequence source; @@ -1028,6 +1038,7 @@ union block_sequence_params { struct update_cursor_offload_pipe_params update_cursor_offload_pipe_params; struct commit_cursor_offload_update_params commit_cursor_offload_update_params; struct stream_enc_update_hdmi_info_packets_params stream_enc_update_hdmi_info_packets_params; + struct hpo_frl_stream_enc_update_hdmi_info_packets_params hpo_frl_stream_enc_update_hdmi_info_packets_params; struct hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num_params hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num_params; struct hpo_dp_stream_enc_update_dp_info_packets_params hpo_dp_stream_enc_update_dp_info_packets_params; struct stream_enc_update_dp_info_packets_sdp_line_num_params stream_enc_update_dp_info_packets_sdp_line_num_params; @@ -1036,6 +1047,7 @@ union block_sequence_params { struct stream_enc_dp_set_dsc_config_params stream_enc_dp_set_dsc_config_params; struct hpo_dp_stream_enc_dp_set_dsc_pps_info_packet_params hpo_dp_stream_enc_dp_set_dsc_pps_info_packet_params; struct stream_enc_dp_set_dsc_pps_info_packet_params stream_enc_dp_set_dsc_pps_info_packet_params; + struct hpo_frl_stream_enc_set_dsc_config_params hpo_frl_stream_enc_set_dsc_config_params; struct dp_trace_source_sequence_params dp_trace_source_sequence_params; struct set_dmdata_attributes_params set_dmdata_attributes_params; struct link_increase_mst_payload_params link_increase_mst_payload_params; @@ -1179,6 +1191,7 @@ enum block_sequence_func { HUBP_SET_BLANK, PHANTOM_HUBP_POST_ENABLE, STREAM_ENC_UPDATE_HDMI_INFO_PACKETS, + HPO_FRL_STREAM_ENC_UPDATE_HDMI_INFO_PACKETS, HPO_DP_STREAM_ENC_UPDATE_DP_INFO_PACKETS_SDP_LINE_NUM, HPO_DP_STREAM_ENC_UPDATE_DP_INFO_PACKETS, STREAM_ENC_UPDATE_DP_INFO_PACKETS_SDP_LINE_NUM, @@ -1187,6 +1200,7 @@ enum block_sequence_func { STREAM_ENC_DP_SET_DSC_CONFIG, HPO_DP_STREAM_ENC_DP_SET_DSC_PPS_INFO_PACKET, STREAM_ENC_DP_SET_DSC_PPS_INFO_PACKET, + HPO_FRL_STREAM_ENC_SET_DSC_CONFIG, LINK_INCREASE_MST_PAYLOAD, LINK_REDUCE_MST_PAYLOAD, DP_TRACE_SOURCE_SEQUENCE, @@ -1415,6 +1429,14 @@ struct hw_sequencer_funcs { void (*get_dcc_en_bits)(struct dc *dc, int *dcc_en_bits); + enum dc_status (*setup_hdmi_frl_link)( + struct dc_link *link, + int hpo_inst, + enum clock_source_id frl_phy_clock_source_id); + + unsigned int (*get_max_dispclk_mhz)(struct dc *dc, + struct dc_state *context); + /* Idle Optimization Related */ bool (*apply_idle_power_optimizations)(struct dc *dc, bool enable); @@ -1672,6 +1694,8 @@ void hwss_dsc_set_config_simple(union block_sequence_params *params); void hwss_stream_enc_update_hdmi_info_packets(union block_sequence_params *params); +void hwss_hpo_frl_stream_enc_update_hdmi_info_packets(union block_sequence_params *params); + void hwss_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(union block_sequence_params *params); void hwss_hpo_dp_stream_enc_update_dp_info_packets(union block_sequence_params *params); @@ -2367,6 +2391,9 @@ void hwss_add_commit_cursor_offload_update(struct block_sequence_state *seq_stat void hwss_add_stream_enc_update_hdmi_info_packets(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx); +void hwss_add_hpo_frl_stream_enc_update_hdmi_info_packets(struct block_sequence_state *seq_state, + struct pipe_ctx *pipe_ctx); + void hwss_add_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx); @@ -2400,6 +2427,11 @@ void hwss_add_stream_enc_dp_set_dsc_pps_info_packet(struct block_sequence_state uint8_t *dsc_packed_pps, bool pps_sdp_stream); +void hwss_add_hpo_frl_stream_enc_set_dsc_config(struct block_sequence_state *seq_state, + struct hpo_frl_stream_encoder *hpo_frl_stream_enc, + const struct dc_crtc_timing *timing, + uint8_t *dsc_packed_pps); + void hwss_add_setup_periodic_interrupt(struct block_sequence_state *seq_state, struct dc *dc, struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h index 8e3f54fb53fd..63c6c841c681 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h @@ -140,6 +140,9 @@ struct hwseq_private_funcs { struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on); + void (*hdmistream_root_clock_control)( + struct dce_hwseq *hws, + bool clock_on); void (*physymclk_root_clock_control)( struct dce_hwseq *hws, unsigned int phy_inst, -- 2.54.0
