diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 218 |
1 files changed, 161 insertions, 57 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 33d311cea28c..2118ea21d7e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -23,6 +23,7 @@ * */ +#include <linux/delay.h> #include "dm_services.h" #include "core_types.h" #include "resource.h" @@ -45,6 +46,12 @@ #include "dcn10_cm_common.h" #include "dc_link_dp.h" #include "dccg.h" +#include "clk_mgr.h" + + +#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT +#include "dsc.h" +#endif #define DC_LOGGER_INIT(logger) @@ -343,6 +350,62 @@ void dcn10_log_hw_state(struct dc *dc, } DTN_INFO("\n"); +#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n"); + for (i = 0; i < pool->res_cap->num_dsc; i++) { + struct display_stream_compressor *dsc = pool->dscs[i]; + struct dcn_dsc_state s = {0}; + + dsc->funcs->dsc_read_state(dsc, &s); + DTN_INFO("[%d]: %-9d %-12d %-10d\n", + dsc->inst, + s.dsc_clock_en, + s.dsc_slice_width, + s.dsc_bytes_per_pixel); + DTN_INFO("\n"); + } + DTN_INFO("\n"); + + DTN_INFO("S_ENC: DSC_MODE SEC_GSP7_LINE_NUM" + " VBID6_LINE_REFERENCE VBID6_LINE_NUM SEC_GSP7_ENABLE SEC_STREAM_ENABLE\n"); + for (i = 0; i < pool->stream_enc_count; i++) { + struct stream_encoder *enc = pool->stream_enc[i]; + struct enc_state s = {0}; + + if (enc->funcs->enc_read_state) { + enc->funcs->enc_read_state(enc, &s); + DTN_INFO("[%-3d]: %-9d %-18d %-21d %-15d %-16d %-17d\n", + enc->id, + s.dsc_mode, + s.sec_gsp_pps_line_num, + s.vbid6_line_reference, + s.vbid6_line_num, + s.sec_gsp_pps_enable, + s.sec_stream_enable); + DTN_INFO("\n"); + } + } + DTN_INFO("\n"); + + DTN_INFO("L_ENC: DPHY_FEC_EN DPHY_FEC_READY_SHADOW DPHY_FEC_ACTIVE_STATUS\n"); + for (i = 0; i < dc->link_count; i++) { + struct link_encoder *lenc = dc->links[i]->link_enc; + + struct link_enc_state s = {0}; + + if (lenc->funcs->read_state) { + lenc->funcs->read_state(lenc, &s); + DTN_INFO("[%-3d]: %-12d %-22d %-22d\n", + i, + s.dphy_fec_en, + s.dphy_fec_ready_shadow, + s.dphy_fec_active_status); + DTN_INFO("\n"); + } + } + DTN_INFO("\n"); +#endif + DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n" "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n", dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_khz, @@ -358,6 +421,23 @@ void dcn10_log_hw_state(struct dc *dc, DTN_INFO_END(); } +bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct hubp *hubp = pipe_ctx->plane_res.hubp; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + if (tg->funcs->is_optc_underflow_occurred(tg)) { + tg->funcs->clear_optc_underflow(tg); + return true; + } + + if (hubp->funcs->hubp_get_underflow_status(hubp)) { + hubp->funcs->hubp_clear_underflow(hubp); + return true; + } + return false; +} + static void enable_power_gating_plane( struct dce_hwseq *hws, bool enable) @@ -658,16 +738,15 @@ static enum dc_status dcn10_enable_stream_timing( BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } - pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - - pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; pipe_ctx->stream_res.tg->funcs->program_timing( pipe_ctx->stream_res.tg, &stream->timing, + pipe_ctx->pipe_dlg_param.vready_offset, + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width, + pipe_ctx->stream->signal, true); #if 0 /* move to after enable_crtc */ @@ -1024,7 +1103,7 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) pipe_ctx->plane_res.dpp = dpp; pipe_ctx->plane_res.mpcc_inst = dpp->inst; hubp->mpcc_id = dpp->inst; - hubp->opp_id = 0xf; + hubp->opp_id = OPP_ID_INVALID; hubp->power_gated = false; dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; @@ -1101,9 +1180,6 @@ static void dcn10_init_hw(struct dc *dc) */ struct dc_link *link = dc->links[i]; - if (link->link_enc->connector.id == CONNECTOR_ID_EDP) - dc->hwss.edp_power_control(link, true); - link->link_enc->funcs->hw_init(link->link_enc); /* Check for enabled DIG to identify enabled display */ @@ -1119,16 +1195,7 @@ static void dcn10_init_hw(struct dc *dc) * everything down. */ if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct hubp *hubp = dc->res_pool->hubps[i]; - struct dpp *dpp = dc->res_pool->dpps[i]; - - hubp->funcs->hubp_init(hubp); - dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; - plane_atomic_power_down(dc, dpp, hubp); - } - - apply_DEGVIDCN10_253_wa(dc); + dc->hwss.init_pipes(dc, dc->current_state); } for (i = 0; i < dc->res_pool->audio_count; i++) { @@ -1145,6 +1212,9 @@ static void dcn10_init_hw(struct dc *dc) if (dmcu != NULL) dmcu->funcs->dmcu_init(dmcu); + if (abm != NULL && dmcu != NULL) + abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ REG_WRITE(DIO_MEM_PWR_CTRL, 0); @@ -1159,7 +1229,7 @@ static void dcn10_init_hw(struct dc *dc) enable_power_gating_plane(dc->hwseq, true); - memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks)); + memset(&dc->clk_mgr->clks, 0, sizeof(dc->clk_mgr->clks)); } static void dcn10_reset_hw_ctx_wrap( @@ -1235,8 +1305,7 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( pipe_ctx->plane_res.hubp, &plane_state->address, - plane_state->flip_immediate, - 0); + plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1297,10 +1366,6 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, return result; } - - - - static bool dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) @@ -1756,7 +1821,7 @@ static void dcn10_program_output_csc(struct dc *dc, bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->plane_state->visible) + if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible) return true; if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) return true; @@ -1765,7 +1830,7 @@ bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->plane_state->visible) + if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1774,7 +1839,7 @@ bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->plane_state->visible) + if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1920,7 +1985,7 @@ static uint16_t fixed_point_to_int_frac( return result; } -void build_prescale_params(struct dc_bias_and_scale *bias_and_scale, +void dcn10_build_prescale_params(struct dc_bias_and_scale *bias_and_scale, const struct dc_plane_state *plane_state) { if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN @@ -1950,10 +2015,15 @@ static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state) plane_state->format, EXPANSION_MODE_ZERO, plane_state->input_csc_color_matrix, +#ifdef CONFIG_DRM_AMD_DC_DCN2_0 + plane_state->color_space, + NULL); +#else plane_state->color_space); +#endif //set scale and bias registers - build_prescale_params(&bns_params, plane_state); + dcn10_build_prescale_params(&bns_params, plane_state); if (dpp->funcs->dpp_program_bias_and_scale) dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); } @@ -2071,7 +2141,7 @@ void update_dchubp_dpp( */ if (plane_state->update_flags.bits.full_update) { bool should_divided_by_2 = context->bw_ctx.bw.dcn.clk.dppclk_khz <= - dc->res_pool->clk_mgr->clks.dispclk_khz / 2; + dc->clk_mgr->clks.dispclk_khz / 2; dpp->funcs->dpp_dppclk_control( dpp, @@ -2084,9 +2154,9 @@ void update_dchubp_dpp( dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz); else - dc->res_pool->clk_mgr->clks.dppclk_khz = should_divided_by_2 ? - dc->res_pool->clk_mgr->clks.dispclk_khz / 2 : - dc->res_pool->clk_mgr->clks.dispclk_khz; + dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ? + dc->clk_mgr->clks.dispclk_khz / 2 : + dc->clk_mgr->clks.dispclk_khz; } /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG @@ -2152,7 +2222,7 @@ void update_dchubp_dpp( pipe_ctx, pipe_ctx->stream->output_color_space, pipe_ctx->stream->csc_color_matrix.matrix, - hubp->opp_id); + pipe_ctx->stream_res.opp->inst); } if (plane_state->update_flags.bits.full_update || @@ -2279,14 +2349,15 @@ static void program_all_pipe_in_tree( if (pipe_ctx->top_pipe == NULL) { bool blank = !is_pipe_tree_visible(pipe_ctx); - pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; - pipe_ctx->stream_res.tg->funcs->program_global_sync( - pipe_ctx->stream_res.tg); + pipe_ctx->stream_res.tg, + pipe_ctx->pipe_dlg_param.vready_offset, + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); + + pipe_ctx->stream_res.tg->funcs->set_vtg_params( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); dc->hwss.blank_pixel_data(dc, pipe_ctx, blank); @@ -2331,6 +2402,7 @@ static void dcn10_apply_ctx_for_surface( { int i; struct timing_generator *tg; + uint32_t underflow_check_delay_us; bool removed_pipe[4] = { false }; bool interdependent_update = false; struct pipe_ctx *top_pipe_to_program = @@ -2345,11 +2417,22 @@ static void dcn10_apply_ctx_for_surface( interdependent_update = top_pipe_to_program->plane_state && top_pipe_to_program->plane_state->update_flags.bits.full_update; + underflow_check_delay_us = dc->debug.underflow_assert_delay_us; + + if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur) + ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program)); + if (interdependent_update) lock_all_pipes(dc, context, true); else dcn10_pipe_control_lock(dc, top_pipe_to_program, true); + if (underflow_check_delay_us != 0xFFFFFFFF) + udelay(underflow_check_delay_us); + + if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur) + ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program)); + if (num_planes == 0) { /* OTG blank before remove all front end */ dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true); @@ -2369,7 +2452,7 @@ static void dcn10_apply_ctx_for_surface( if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { if (old_pipe_ctx->stream_res.tg == tg && old_pipe_ctx->plane_res.hubp && - old_pipe_ctx->plane_res.hubp->opp_id != 0xf) + old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) dcn10_disable_plane(dc, old_pipe_ctx); } @@ -2389,6 +2472,11 @@ static void dcn10_apply_ctx_for_surface( if (num_planes > 0) program_all_pipe_in_tree(dc, top_pipe_to_program, context); +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) + /* Program secondary blending tree and writeback pipes */ + if ((stream->num_wb_info > 0) && (dc->hwss.program_all_writeback_pipes_in_tree)) + dc->hwss.program_all_writeback_pipes_in_tree(dc, stream, context); +#endif if (interdependent_update) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -2415,6 +2503,12 @@ static void dcn10_apply_ctx_for_surface( if (removed_pipe[i]) dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (removed_pipe[i]) { + dc->hwss.optimize_bandwidth(dc, context); + break; + } + if (dc->hwseq->wa.DEGVIDCN10_254) hubbub1_wm_change_req_wa(dc->res_pool->hubbub); } @@ -2448,8 +2542,8 @@ static void dcn10_prepare_bandwidth( if (context->stream_count == 0) context->bw_ctx.bw.dcn.clk.phyclk_khz = 0; - dc->res_pool->clk_mgr->funcs->update_clocks( - dc->res_pool->clk_mgr, + dc->clk_mgr->funcs->update_clocks( + dc->clk_mgr, context, false); } @@ -2480,8 +2574,8 @@ static void dcn10_optimize_bandwidth( if (context->stream_count == 0) context->bw_ctx.bw.dcn.clk.phyclk_khz = 0; - dc->res_pool->clk_mgr->funcs->update_clocks( - dc->res_pool->clk_mgr, + dc->clk_mgr->funcs->update_clocks( + dc->clk_mgr, context, true); } @@ -2504,8 +2598,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx, { int i = 0; struct drr_params params = {0}; - // DRR should set trigger event to monitor surface update event - unsigned int event_triggers = 0x80; + // DRR set trigger event mapped to OTG_TRIG_A (bit 11) for manual control flow + unsigned int event_triggers = 0x800; params.vertical_total_max = vmax; params.vertical_total_min = vmin; @@ -2644,9 +2738,6 @@ static void dcn10_wait_for_mpcc_disconnect( res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst); pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false; hubp->funcs->set_blank(hubp, true); - /*DC_LOG_ERROR(dc->ctx->logger, - "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", - i);*/ } } @@ -2790,7 +2881,6 @@ static void apply_front_porch_workaround( int get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx) { - struct timing_generator *optc = pipe_ctx->stream_res.tg; const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; struct dc_crtc_timing patched_crtc_timing; int vesa_sync_start; @@ -2813,7 +2903,7 @@ int get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx) * interlace_factor; vertical_line_start = asic_blank_end - - optc->dlg_otg_param.vstartup_start + 1; + pipe_ctx->pipe_dlg_param.vstartup_start + 1; return vertical_line_start; } @@ -2961,6 +3051,18 @@ static void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx, } } +static void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx, + const uint8_t *custom_sdp_message, + unsigned int sdp_message_size) +{ + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + pipe_ctx->stream_res.stream_enc->funcs->send_immediate_sdp_message( + pipe_ctx->stream_res.stream_enc, + custom_sdp_message, + sdp_message_size); + } +} + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .init_hw = dcn10_init_hw, @@ -2980,6 +3082,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .enable_timing_synchronization = dcn10_enable_timing_synchronization, .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, .update_info_frame = dce110_update_info_frame, + .send_immediate_sdp_message = dcn10_send_immediate_sdp_message, .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dcn10_unblank_stream, @@ -3012,7 +3115,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .disable_stream_gating = NULL, .enable_stream_gating = NULL, .setup_periodic_interrupt = dcn10_setup_periodic_interrupt, - .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt + .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt, + .did_underflow_occur = dcn10_did_underflow_occur }; |