summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/link/link_dpms.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c99
1 files changed, 61 insertions, 38 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index b53ad18dbfbc..c4e03482ba9a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -817,17 +817,17 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
- dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst);
+ dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+ dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
- odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
- odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);
+ odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+ odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
dsc_cfg.pic_width *= opp_cnt;
@@ -838,10 +838,11 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) {
DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
dsc_optc_config_log(dsc, &dsc_optc_cfg);
- pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
- optc_dsc_mode,
- dsc_optc_cfg.bytes_per_pixel,
- dsc_optc_cfg.slice_width);
+ if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)
+ pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
+ optc_dsc_mode,
+ dsc_optc_cfg.bytes_per_pixel,
+ dsc_optc_cfg.slice_width);
/* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
}
@@ -868,22 +869,42 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
NULL,
true);
else {
- pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
- pipe_ctx->stream_res.stream_enc,
- OPTC_DSC_DISABLED, 0, 0);
+ if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)
+ pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
+ pipe_ctx->stream_res.stream_enc,
+ OPTC_DSC_DISABLED, 0, 0);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc, false, NULL, true);
}
}
/* disable DSC block */
- if (dccg->funcs->set_ref_dscclk)
- dccg->funcs->set_ref_dscclk(dccg, pipe_ctx->stream_res.dsc->inst);
- pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
- for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ for (odm_pipe = pipe_ctx; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ odm_pipe->stream_res.dsc->funcs->dsc_disconnect(odm_pipe->stream_res.dsc);
+ /*
+ * TODO - dsc_disconnect is a double buffered register.
+ * by the time we call dsc_disable, dsc may still remain
+ * connected to OPP. In this case OPTC will no longer
+ * get correct pixel data because DSCC is off. However
+ * we also can't wait for the disconnect pending
+ * complete, because this function can be called
+ * with/without OTG master lock acquired. When the lock
+ * is acquired we will never get pending complete until
+ * we release the lock later. So there is no easy way to
+ * solve this problem especially when the lock is
+ * acquired. DSC is a front end hw block it should be
+ * programmed as part of front end sequence, where the
+ * commit sequence without lock and update sequence
+ * with lock are completely separated. However because
+ * we are programming dsc as part of back end link
+ * programming sequence, we don't know if front end OPTC
+ * master lock is acquired. The back end should be
+ * agnostic to front end lock. DSC programming shouldn't
+ * belong to this sequence.
+ */
+ odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);
- odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
}
}
}
@@ -1158,12 +1179,13 @@ static bool poll_for_allocation_change_trigger(struct dc_link *link)
int i;
const int act_retries = 30;
enum act_return_status result = ACT_FAILED;
+ enum dc_connection_type display_connected = (link->type != dc_connection_none);
union payload_table_update_status update_status = {0};
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
union lane_align_status_updated lane_status_updated;
DC_LOGGER_INIT(link->ctx->logger);
- if (link->aux_access_disabled)
+ if (!display_connected || link->aux_access_disabled)
return true;
for (i = 0; i < act_retries; i++) {
get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
@@ -1512,6 +1534,7 @@ static bool write_128b_132b_sst_payload_allocation_table(
union payload_table_update_status update_status = { 0 };
const uint32_t max_retries = 30;
uint32_t retries = 0;
+ enum dc_connection_type display_connected = (link->type != dc_connection_none);
DC_LOGGER_INIT(link->ctx->logger);
if (allocate) {
@@ -1529,7 +1552,7 @@ static bool write_128b_132b_sst_payload_allocation_table(
proposed_table->stream_allocations[0].slot_count = req_slot_count;
proposed_table->stream_allocations[0].vcp_id = vc_id;
- if (link->aux_access_disabled)
+ if (!display_connected || link->aux_access_disabled)
return true;
/// Write DPCD 2C0 = 1 to start updating
@@ -1897,7 +1920,9 @@ static void disable_link(struct dc_link *link,
{
if (dc_is_dp_signal(signal)) {
disable_link_dp(link, link_res, signal);
- } else if (signal != SIGNAL_TYPE_VIRTUAL) {
+ } else if (signal == SIGNAL_TYPE_VIRTUAL) {
+ link->dc->hwss.disable_link_output(link, link_res, SIGNAL_TYPE_DISPLAY_PORT);
+ } else {
link->dc->hwss.disable_link_output(link, link_res, signal);
}
@@ -1964,7 +1989,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
/* We need to enable stream encoder for TMDS first to apply 1/4 TMDS
* character clock in case that beyond 340MHz.
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal))
link_hwss->setup_stream_encoder(pipe_ctx);
dc->hwss.enable_tmds_link_output(
@@ -2144,6 +2169,18 @@ static enum dc_status enable_link_dp_mst(
return enable_link_dp(state, pipe_ctx);
}
+static enum dc_status enable_link_virtual(struct pipe_ctx *pipe_ctx)
+{
+ struct dc_link *link = pipe_ctx->stream->link;
+
+ link->dc->hwss.enable_dp_link_output(link,
+ &pipe_ctx->link_res,
+ SIGNAL_TYPE_DISPLAY_PORT,
+ pipe_ctx->clock_source->id,
+ &pipe_ctx->link_config.dp_link_settings);
+ return DC_OK;
+}
+
static enum dc_status enable_link(
struct dc_state *state,
struct pipe_ctx *pipe_ctx)
@@ -2183,7 +2220,7 @@ static enum dc_status enable_link(
status = DC_OK;
break;
case SIGNAL_TYPE_VIRTUAL:
- status = DC_OK;
+ status = enable_link_virtual(pipe_ctx);
break;
default:
break;
@@ -2313,8 +2350,6 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_audio_stream(pipe_ctx);
- edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);
-
update_psp_stream_config(pipe_ctx, true);
dc->hwss.blank_stream(pipe_ctx);
@@ -2323,7 +2358,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx);
- else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&
dp_is_128b_132b_signal(pipe_ctx))
update_sst_payload(pipe_ctx, false);
@@ -2368,6 +2403,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
}
+ edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal))
@@ -2428,17 +2464,10 @@ void link_set_dpms_on(
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
&& !dp_is_128b_132b_signal(pipe_ctx)) {
- struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
-
if (link_enc)
link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal);
-
- if (stream_enc && stream_enc->funcs->dig_stream_enable)
- stream_enc->funcs->dig_stream_enable(
- stream_enc,
- pipe_ctx->stream->signal, 1);
}
pipe_ctx->stream->link->link_state_valid = true;
@@ -2538,18 +2567,12 @@ void link_set_dpms_on(
*/
if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
dp_is_128b_132b_signal(pipe_ctx))) {
- struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
if (link_enc)
link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal);
- if (stream_enc && stream_enc->funcs->dig_stream_enable)
- stream_enc->funcs->dig_stream_enable(
- stream_enc,
- pipe_ctx->stream->signal, 1);
-
}
dc->hwss.enable_stream(pipe_ctx);
@@ -2568,7 +2591,7 @@ void link_set_dpms_on(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
allocate_mst_payload(pipe_ctx);
- else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&
dp_is_128b_132b_signal(pipe_ctx))
update_sst_payload(pipe_ctx, true);