diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn32')
11 files changed, 96 insertions, 29 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c index 3fb4bcc34353..ffbb739d85b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c @@ -42,6 +42,20 @@ #define DC_LOGGER \ dccg->ctx->logger +/* This function is a workaround for writing to OTG_PIXEL_RATE_DIV + * without the probability of causing a DIG FIFO error. + */ +static void dccg32_wait_for_dentist_change_done( + struct dccg *dccg) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + uint32_t dentist_dispclk_value = REG_READ(DENTIST_DISPCLK_CNTL); + + REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value); + REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000); +} + static void dccg32_get_pixel_rate_div( struct dccg *dccg, uint32_t otg_inst, @@ -110,21 +124,29 @@ static void dccg32_set_pixel_rate_div( REG_UPDATE_2(OTG_PIXEL_RATE_DIV, OTG0_PIXEL_RATE_DIVK1, k1, OTG0_PIXEL_RATE_DIVK2, k2); + + dccg32_wait_for_dentist_change_done(dccg); break; case 1: REG_UPDATE_2(OTG_PIXEL_RATE_DIV, OTG1_PIXEL_RATE_DIVK1, k1, OTG1_PIXEL_RATE_DIVK2, k2); + + dccg32_wait_for_dentist_change_done(dccg); break; case 2: REG_UPDATE_2(OTG_PIXEL_RATE_DIV, OTG2_PIXEL_RATE_DIVK1, k1, OTG2_PIXEL_RATE_DIVK2, k2); + + dccg32_wait_for_dentist_change_done(dccg); break; case 3: REG_UPDATE_2(OTG_PIXEL_RATE_DIV, OTG3_PIXEL_RATE_DIVK1, k1, OTG3_PIXEL_RATE_DIVK2, k2); + + dccg32_wait_for_dentist_change_done(dccg); break; default: BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h index 271c163e4844..8071ab98d708 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h @@ -111,7 +111,8 @@ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ - DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh) + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) struct dccg *dccg32_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c index c72448125976..2fef1419ae91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c @@ -274,10 +274,10 @@ static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_ dc->debug.enable_dp_dig_pixel_rate_div_policy; } -static void enc32_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param) +void enc32_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); struct dc *dc = enc->ctx->dc; @@ -286,6 +286,7 @@ static void enc32_stream_encoder_dp_unblank( uint32_t n_vid = 0x8000; uint32_t m_vid; uint32_t n_multiply = 0; + uint32_t pix_per_cycle = 0; uint64_t m_vid_l = n_vid; /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ @@ -293,6 +294,7 @@ static void enc32_stream_encoder_dp_unblank( || is_dp_dig_pixel_rate_div_policy(dc, ¶m->timing)) { /*this logic should be the same in get_pixel_clock_parameters() */ n_multiply = 1; + pix_per_cycle = 1; } /* M / N = Fstream / Flink * m_vid / n_vid = pixel rate / link rate @@ -320,6 +322,10 @@ static void enc32_stream_encoder_dp_unblank( REG_UPDATE_2(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 1, DP_VID_N_MUL, n_multiply); + + REG_UPDATE(DP_PIXEL_FORMAT, + DP_PIXEL_PER_CYCLE_PROCESSING_MODE, + pix_per_cycle); } /* make sure stream is disabled before resetting steer fifo */ @@ -434,7 +440,7 @@ static void enc32_reset_fifo(struct stream_encoder *enc, bool reset) udelay(10); } -static void enc32_enable_fifo(struct stream_encoder *enc) +void enc32_enable_fifo(struct stream_encoder *enc) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h index 875b1cd46056..1be5410cce97 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h @@ -194,4 +194,12 @@ void dcn32_dio_stream_encoder_construct( const struct dcn10_stream_encoder_shift *se_shift, const struct dcn10_stream_encoder_mask *se_mask); + +void enc32_enable_fifo(struct stream_encoder *enc); + +void enc32_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + #endif /* __DC_DIO_STREAM_ENCODER_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c index fe0cd177744c..2d604f7ee782 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c @@ -47,6 +47,15 @@ void hubp32_update_force_pstate_disallow(struct hubp *hubp, bool pstate_disallow DATA_UCLK_PSTATE_FORCE_VALUE, 0); } +void hubp32_update_force_cursor_pstate_disallow(struct hubp *hubp, bool pstate_disallow) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE_2(UCLK_PSTATE_FORCE, + CURSOR_UCLK_PSTATE_FORCE_EN, pstate_disallow, + CURSOR_UCLK_PSTATE_FORCE_VALUE, 0); +} + void hubp32_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); @@ -188,6 +197,7 @@ static struct hubp_funcs dcn32_hubp_funcs = { .hubp_set_flip_int = hubp1_set_flip_int, .hubp_in_blank = hubp1_in_blank, .hubp_update_force_pstate_disallow = hubp32_update_force_pstate_disallow, + .hubp_update_force_cursor_pstate_disallow = hubp32_update_force_cursor_pstate_disallow, .phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable, .hubp_update_mall_sel = hubp32_update_mall_sel, .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h index d5e5ed8ab869..d2acbc129609 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h @@ -46,6 +46,8 @@ void hubp32_update_force_pstate_disallow(struct hubp *hubp, bool pstate_disallow); +void hubp32_update_force_cursor_pstate_disallow(struct hubp *hubp, bool pstate_disallow); + void hubp32_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor); void hubp32_prepare_subvp_buffering(struct hubp *hubp, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index f9073b722b36..b3824287c224 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -414,7 +414,7 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc, } -static bool dcn32_set_mpc_shaper_3dlut( +bool dcn32_set_mpc_shaper_3dlut( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; @@ -571,39 +571,56 @@ bool dcn32_set_output_transfer_func(struct dc *dc, return ret; } -/* Program P-State force value according to if pipe is using SubVP or not: +/* Program P-State force value according to if pipe is using SubVP / FPO or not: * 1. Reset P-State force on all pipes first * 2. For each main pipe, force P-State disallow (P-State allow moderated by DMUB) */ -void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context) +void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context) { int i; - int num_subvp = 0; - /* Unforce p-state for each pipe + + /* Unforce p-state for each pipe if it is not FPO or SubVP. + * For FPO and SubVP, if it's already forced disallow, leave + * it as disallow. */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; struct hubp *hubp = pipe->plane_res.hubp; - if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) - hubp->funcs->hubp_update_force_pstate_disallow(hubp, false); - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) - num_subvp++; - } + if (!pipe->stream || (pipe->stream && !(pipe->stream->mall_stream_config.type == SUBVP_MAIN || + pipe->stream->fpo_in_use))) { + if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) + hubp->funcs->hubp_update_force_pstate_disallow(hubp, false); + } - if (num_subvp == 0) - return; + /* Today only FPO uses cursor P-State force. Only clear cursor P-State force + * if it's not FPO. + */ + if (!pipe->stream || (pipe->stream && !pipe->stream->fpo_in_use)) { + if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) + hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false); + } + } /* Loop through each pipe -- for each subvp main pipe force p-state allow equal to false. */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct hubp *hubp = pipe->plane_res.hubp; - if (pipe->stream && pipe->plane_state && (pipe->stream->mall_stream_config.type == SUBVP_MAIN)) { - struct hubp *hubp = pipe->plane_res.hubp; + if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { + if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) + hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); + } + if (pipe->stream && pipe->stream->fpo_in_use) { if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); + /* For now only force cursor p-state disallow for FPO + * Needs to be added for subvp once FW side gets updated + */ + if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow) + hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, true); } } } @@ -677,10 +694,6 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context) if (hws && hws->funcs.update_mall_sel) hws->funcs.update_mall_sel(dc, context); - //update subvp force pstate - if (hws && hws->funcs.subvp_update_force_pstate) - dc->hwseq->funcs.subvp_update_force_pstate(dc, context); - // Program FORCE_ONE_ROW_FOR_FRAME and CURSOR_REQ_MODE for main subvp pipes for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -902,7 +915,7 @@ void dcn32_init_hw(struct dc *dc) if (dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); - if (dc->clk_mgr->funcs->set_hard_max_memclk) + if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); if (dc->res_pool->hubbub->funcs->force_pstate_change_control) @@ -1111,7 +1124,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign *k2_div = PIXEL_RATE_DIV_BY_2; else *k2_div = PIXEL_RATE_DIV_BY_4; - } else if (dc_is_dp_signal(stream->signal)) { + } else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { if (two_pix_per_container) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_2; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h index 84c1f36c3fa6..6694c1d14aa3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h @@ -54,6 +54,9 @@ bool dcn32_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state); +bool dcn32_set_mpc_shaper_3dlut( + struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream); + bool dcn32_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream); @@ -64,7 +67,7 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context); void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context); -void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context); +void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context); void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c index dcb81662884f..8085f2acb1a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c @@ -149,7 +149,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = { .dccg_init = dcn20_dccg_init, .set_mcm_luts = dcn32_set_mcm_luts, .program_mall_pipe_config = dcn32_program_mall_pipe_config, - .subvp_update_force_pstate = dcn32_subvp_update_force_pstate, + .update_force_pstate = dcn32_update_force_pstate, .update_mall_sel = dcn32_update_mall_sel, .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, .set_pixels_per_cycle = dcn32_set_pixels_per_cycle, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 1715909b1225..502f990346b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -725,6 +725,7 @@ static const struct dc_debug_options debug_defaults_drv = { .min_prefetch_in_strobe_ns = 60000, // 60us .disable_unbounded_requesting = false, .override_dispclk_programming = true, + .disable_fpo_optimizations = false, }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index aca928edc4e3..10a3350376e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -1276,7 +1276,8 @@ double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *conte DCCG_SRII(PHASE, DTBCLK_DTO, 0), DCCG_SRII(PHASE, DTBCLK_DTO, 1), \ DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \ SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \ - SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), SR(DCCG_AUDIO_DTO_SOURCE) \ + SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), \ + SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) \ ) /* VMID */ |
