diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 156 |
1 files changed, 88 insertions, 68 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0cb8d1f934d1..1c218c526650 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -33,6 +33,7 @@ #include "resource.h" +#include "gpio_service_interface.h" #include "clk_mgr.h" #include "clock_source.h" #include "dc_bios_types.h" @@ -53,11 +54,10 @@ #include "link_enc_cfg.h" #include "dc_link.h" -#include "dc_link_ddc.h" +#include "link.h" #include "dm_helpers.h" #include "mem_input.h" -#include "dc_link_dp.h" #include "dc_dmub_srv.h" #include "dsc.h" @@ -68,8 +68,6 @@ #include "dmub/dmub_srv.h" -#include "i2caux_interface.h" - #include "dce/dmub_psr.h" #include "dce/dmub_hw_lock_mgr.h" @@ -382,16 +380,18 @@ static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) } /** - * dc_stream_adjust_vmin_vmax: + * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR + * @dc: dc reference + * @stream: Initial dc stream state + * @adjust: Updated parameters for vertical_total_min and vertical_total_max * * Looks up the pipe context of dc_stream_state and updates the * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh * Rate, which is a power-saving feature that targets reducing panel * refresh rate while the screen is static * - * @dc: dc reference - * @stream: Initial dc stream state - * @adjust: Updated parameters for vertical_total_min and vertical_total_max + * Return: %true if the pipe context is found and adjusted; + * %false if the pipe context is not found. */ bool dc_stream_adjust_vmin_vmax(struct dc *dc, struct dc_stream_state *stream, @@ -419,14 +419,17 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, } /** - * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal + * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of + * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) * * @dc: [in] dc reference * @stream: [in] Initial dc stream state - * @adjust: [in] Updated parameters for vertical_total_min and + * @refresh_rate: [in] new refresh_rate * - * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used - * by DRR (Dynamic Refresh Rate) + * Return: %true if the pipe context is found and there is an associated + * timing_generator for the DC; + * %false if the pipe context is not found or there is no + * timing_generator for the DC. */ bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, struct dc_stream_state *stream, @@ -518,14 +521,15 @@ dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu, } bool -dc_stream_forward_crc_window(struct dc *dc, - struct rect *rect, struct dc_stream_state *stream, bool is_stop) +dc_stream_forward_crc_window(struct dc_stream_state *stream, + struct rect *rect, bool is_stop) { struct dmcu *dmcu; struct dc_dmub_srv *dmub_srv; struct otg_phy_mux mux_mapping; struct pipe_ctx *pipe; int i; + struct dc *dc = stream->ctx->dc; for (i = 0; i < MAX_PIPES; i++) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; @@ -566,7 +570,10 @@ dc_stream_forward_crc_window(struct dc *dc, * once. * * By default, only CRC0 is configured, and the entire frame is used to - * calculate the crc. + * calculate the CRC. + * + * Return: %false if the stream is not found or CRC capture is not supported; + * %true if the stream has been configured. */ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, struct crc_params *crc_window, bool enable, bool continuous) @@ -635,7 +642,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, * dc_stream_configure_crc needs to be called beforehand to enable CRCs. * * Return: - * false if stream is not found, or if CRCs are not enabled. + * %false if stream is not found, or if CRCs are not enabled. */ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) @@ -862,6 +869,7 @@ static bool dc_construct_ctx(struct dc *dc, dc_ctx->perf_trace = dc_perf_trace_create(); if (!dc_ctx->perf_trace) { + kfree(dc_ctx); ASSERT_CRITICAL(false); return false; } @@ -1191,7 +1199,7 @@ static void disable_vbios_mode_if_required( pipe->stream_res.pix_clk_params.requested_pix_clk_100hz; if (pix_clk_100hz != requested_pix_clk_100hz) { - core_link_disable_stream(pipe); + link_set_dpms_off(pipe); pipe->stream->dpms_off = false; } } @@ -1299,7 +1307,7 @@ static void detect_edp_presence(struct dc *dc) if (dc->config.edp_not_connected) { edp_link->edp_sink_present = false; } else { - dc_link_detect_sink(edp_link, &type); + dc_link_detect_connection_type(edp_link, &type); edp_link->edp_sink_present = (type != dc_connection_none); } } @@ -1650,7 +1658,7 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } - if (is_edp_ilr_optimization_required(link, crtc_timing)) { + if (link_is_edp_ilr_optimization_required(link, crtc_timing)) { DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); return false; } @@ -1740,6 +1748,8 @@ void dc_z10_save_init(struct dc *dc) * * Applies given context to the hardware and copy it into current context. * It's up to the user to release the src context afterwards. + * + * Return: an enum dc_status result code for the operation */ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { @@ -2007,8 +2017,9 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) return result == DC_OK; } - if (!streams_changed(dc, context->streams, context->stream_count)) + if (!streams_changed(dc, context->streams, context->stream_count)) { return DC_OK; + } DC_LOG_DC("%s: %d streams\n", __func__, context->stream_count); @@ -2948,6 +2959,9 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->vsp_infopacket) stream->vsp_infopacket = *update->vsp_infopacket; + if (update->adaptive_sync_infopacket) + stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket; + if (update->dither_option) stream->dither_option = *update->dither_option; @@ -3153,12 +3167,13 @@ static void commit_planes_do_stream_update(struct dc *dc, stream_update->vsc_infopacket || stream_update->vsp_infopacket || stream_update->hfvsif_infopacket || + stream_update->adaptive_sync_infopacket || stream_update->vtem_infopacket) { resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + link_dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); } if (stream_update->hdr_static_metadata && @@ -3194,14 +3209,14 @@ static void commit_planes_do_stream_update(struct dc *dc, continue; if (stream_update->dsc_config) - dp_update_dsc_config(pipe_ctx); + link_update_dsc_config(pipe_ctx); if (stream_update->mst_bw_update) { if (stream_update->mst_bw_update->is_increase) - dc_link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); - else - dc_link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); - } + link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); + else + link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); + } if (stream_update->pending_test_pattern) { dc_link_dp_set_test_pattern(stream->link, @@ -3214,7 +3229,7 @@ static void commit_planes_do_stream_update(struct dc *dc, if (stream_update->dpms_off) { if (*stream_update->dpms_off) { - core_link_disable_stream(pipe_ctx); + link_set_dpms_off(pipe_ctx); /* for dpms, keep acquired resources*/ if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); @@ -3224,7 +3239,7 @@ static void commit_planes_do_stream_update(struct dc *dc, } else { if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, dc->current_state); - core_link_enable_stream(dc->current_state, pipe_ctx); + link_set_dpms_on(dc->current_state, pipe_ctx); } } @@ -3325,6 +3340,7 @@ static void commit_planes_for_stream(struct dc *dc, struct pipe_ctx *top_pipe_to_program = NULL; bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); bool subvp_prev_use = false; + bool subvp_curr_use = false; // Once we apply the new subvp context to hardware it won't be in the // dc->current_state anymore, so we have to cache it before we apply @@ -3334,6 +3350,21 @@ static void commit_planes_for_stream(struct dc *dc, dc_z10_restore(dc); + if (update_type == UPDATE_TYPE_FULL) { + /* wait for all double-buffer activity to clear on all pipes */ + int pipe_idx; + + for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + if (!pipe_ctx->stream) + continue; + + if (pipe_ctx->stream_res.tg->funcs->wait_drr_doublebuffer_pending_clear) + pipe_ctx->stream_res.tg->funcs->wait_drr_doublebuffer_pending_clear(pipe_ctx->stream_res.tg); + } + } + if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) { /* Optimize seamless boot flag keeps clocks and watermarks high until * first flip. After first flip, optimization is required to lower @@ -3381,6 +3412,15 @@ static void commit_planes_for_stream(struct dc *dc, break; } + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + subvp_curr_use = true; + break; + } + } + if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { struct pipe_ctx *mpcc_pipe; struct pipe_ctx *odm_pipe; @@ -3652,42 +3692,22 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program->stream_res.tg); } - /* For phantom pipe OTG enable, it has to be done after any previous pipe - * that was in use has already been programmed at gotten its double buffer - * update for "disable". - */ - if (update_type != UPDATE_TYPE_FAST) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - - /* If an active, non-phantom pipe is being transitioned into a phantom - * pipe, wait for the double buffer update to complete first before we do - * ANY phantom pipe programming. - */ - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM && - old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { - old_pipe->stream_res.tg->funcs->wait_for_state( - old_pipe->stream_res.tg, - CRTC_STATE_VBLANK); - old_pipe->stream_res.tg->funcs->wait_for_state( - old_pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - } + if (subvp_curr_use) { + /* If enabling subvp or transitioning from subvp->subvp, enable the + * phantom streams before we program front end for the phantom pipes. + */ + if (update_type != UPDATE_TYPE_FAST) { + if (dc->hwss.enable_phantom_streams) + dc->hwss.enable_phantom_streams(dc, context); } - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; + } - if ((new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) || - subvp_prev_use) { - // If old context or new context has phantom pipes, apply - // the phantom timings now. We can't change the phantom - // pipe configuration safely without driver acquiring - // the DMCUB lock first. - dc->hwss.apply_ctx_to_hw(dc, context); - break; - } - } + if (subvp_prev_use && !subvp_curr_use) { + /* If disabling subvp, disable phantom streams after front end + * programming has completed (we turn on phantom OTG in order + * to complete the plane disable for phantom pipes). + */ + dc->hwss.apply_ctx_to_hw(dc, context); } if (update_type != UPDATE_TYPE_FAST) @@ -4285,7 +4305,7 @@ void dc_resume(struct dc *dc) uint32_t i; for (i = 0; i < dc->link_count; i++) - core_link_resume(dc->links[i]); + link_resume(dc->links[i]); } bool dc_is_dmcu_initialized(struct dc *dc) @@ -4704,7 +4724,7 @@ bool dc_enable_dmub_notifications(struct dc *dc) /** * dc_enable_dmub_outbox - Enables DMUB unsolicited notification * - * dc: [in] dc structure + * @dc: [in] dc structure * * Enables DMUB unsolicited notifications to x86 via outbox. */ @@ -4905,8 +4925,8 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, /** * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption * - * @dc [in]: dc structure - * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable + * @dc: [in] dc structure + * @hpd_int_enable: [in] 1 for hpd int enable, 0 to disable * * Submits dpia hpd int enable command to dmub via inbox message */ @@ -4987,7 +5007,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo } /** - * dc_extended_blank_supported 0 Decide whether extended blank is supported + * dc_extended_blank_supported - Decide whether extended blank is supported * * @dc: [in] Current DC state * @@ -4996,7 +5016,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo * ability to enter z9/z10. * * Return: - * Indicate whether extended blank is supported (true or false) + * Indicate whether extended blank is supported (%true or %false) */ bool dc_extended_blank_supported(struct dc *dc) { |