diff options
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.c | 99 |
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); |