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);
}
}
} 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);
}
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);
+ }
+ }
}
}
}
+ 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(
pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
pipe_ctx->stream_res.tg, event_triggers, 2);
- if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
+ if (!dc_is_virtual_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);
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;
if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) {
struct dtbclk_dto_params dto_params = {0};
-
- dc->res_pool->dccg->funcs->set_audio_dtbclk_dto(
- dc->res_pool->dccg, &dto_params);
-
- pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
+ dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);
+
+ 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,
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,
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;
}
}
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");
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;
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);
}
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) {
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,
{
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(
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;
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)
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,
.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,
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);
}
}
{
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(
.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,
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)) {
.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,
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)) {
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);
}
#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 = {
.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,
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);
}
}
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,
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];
}
}
+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)
memset(update_state, 0, sizeof(struct pg_block_update));
+ for (ui = 0; ui < dc->res_pool->hpo_frl_stream_enc_count; ui++) {
+ if (context->res_ctx.is_hpo_frl_stream_enc_acquired[ui] &&
+ dc->res_pool->hpo_frl_stream_enc[ui]) {
+ hpo_frl_stream_enc_acquired = true;
+ break;
+ }
+ }
+
for (ui = 0; ui < dc->res_pool->hpo_dp_stream_enc_count; ui++) {
if (context->res_ctx.is_hpo_dp_stream_enc_acquired[ui] &&
dc->res_pool->hpo_dp_stream_enc[ui]) {
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)
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 (ui = 0; ui < dc->res_pool->hpo_frl_stream_enc_count; ui++) {
+ if (context->res_ctx.is_hpo_frl_stream_enc_acquired[ui] &&
+ dc->res_pool->hpo_frl_stream_enc[ui]) {
+ hpo_frl_stream_enc_acquired = true;
+ break;
+ }
+ }
+
for (ui = 0; ui < dc->res_pool->hpo_dp_stream_enc_count; ui++) {
if (context->res_ctx.is_hpo_dp_stream_enc_acquired[ui] &&
dc->res_pool->hpo_dp_stream_enc[ui]) {
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 < (unsigned int)dc->res_pool->res_cap->num_dsc; i++) {
if (update_state->pg_pipe_res_update[PG_DSC][i]) {
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 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);
.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,
//.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,
.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,
//.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,
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;
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);
}
}
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,
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);
}
.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,
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]) {
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;
}
}
+ 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(
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;
unsigned int i = 0;
int j = 0;
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]) {
}
}
- 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;
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 < (unsigned int)dc->res_pool->res_cap->num_dsc; i++) {
if (update_state->pg_pipe_res_update[PG_DSC][i]) {
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)
.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,
.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,
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;
};
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;
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;
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;
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,
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,
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);
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);
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);
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);
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,