summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
diff options
context:
space:
mode:
authorAlvin Lee <Alvin.Lee2@amd.com>2022-05-02 15:04:31 -0400
committerAlex Deucher <alexander.deucher@amd.com>2022-07-05 16:10:38 -0400
commit85f4bc0c333ceed24cbc9f69a2a77fab1ae3d4d1 (patch)
treebf72bbc683ca2ac64dd033a1e6306599c1d13b20 /drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
parente72f03f4bdc4f3a251343cf343bce28c28cbac2a (diff)
downloadlinux-85f4bc0c333ceed24cbc9f69a2a77fab1ae3d4d1.tar.bz2
drm/amd/display: Add SubVP required code
This commit enables the SubVP feature. To achieve that, we need to: - Don't force p-state disallow on SubVP (can't block dummy p-state) - Send calculated watermark to DMCUB for SubVP - Adjust CAB mode message to PMFW - Add a proper locking sequence for SubVP - Various fixes to SubVP static analysis and determining SubVP config - Currently SubVP not supported with pipe split so merge all pipes before setting up SubVp Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c73
1 files changed, 69 insertions, 4 deletions
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 790aa2b3952c..2fd19f8a9811 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -47,7 +47,10 @@
#include "clk_mgr.h"
#include "dsc.h"
#include "dcn20/dcn20_optc.h"
+#include "dmub_subvp_state.h"
+#include "dce/dmub_hw_lock_mgr.h"
#include "dc_link_dp.h"
+#include "dmub/inc/dmub_subvp_state.h"
#define DC_LOGGER_INIT(logger)
@@ -405,6 +408,65 @@ void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context)
*/
}
+/* Sub-Viewport DMUB lock needs to be acquired by driver whenever SubVP is active and:
+ * 1. Any full update for any SubVP main pipe
+ * 2. Any immediate flip for any SubVP pipe
+ * 3. Any flip for DRR pipe
+ * 4. If SubVP was previously in use (i.e. in old context)
+ */
+void dcn32_subvp_pipe_control_lock(struct dc *dc,
+ struct dc_state *context,
+ bool lock,
+ bool should_lock_all_pipes,
+ struct pipe_ctx *top_pipe_to_program,
+ bool subvp_prev_use)
+{
+ unsigned int i = 0;
+ bool subvp_immediate_flip = false;
+ bool subvp_in_use = false;
+ bool drr_pipe = false;
+ struct pipe_ctx *pipe, *old_pipe;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+ old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+ subvp_in_use = true;
+ break;
+ }
+ }
+
+ if (top_pipe_to_program && top_pipe_to_program->stream && top_pipe_to_program->plane_state) {
+ if (top_pipe_to_program->stream->mall_stream_config.type == SUBVP_MAIN &&
+ top_pipe_to_program->plane_state->flip_immediate)
+ subvp_immediate_flip = true;
+ else if (top_pipe_to_program->stream->mall_stream_config.type == SUBVP_NONE &&
+ top_pipe_to_program->stream->ignore_msa_timing_param)
+ drr_pipe = true;
+ }
+
+ if ((subvp_in_use && (should_lock_all_pipes || subvp_immediate_flip || drr_pipe)) || (!subvp_in_use && subvp_prev_use)) {
+ union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+
+ if (!lock) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+ if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN &&
+ should_lock_all_pipes)
+ pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK);
+ }
+ }
+
+ hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+ hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+ hw_lock_cmd.bits.lock = lock;
+ hw_lock_cmd.bits.should_release = !lock;
+ dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+ }
+}
+
+
static bool dcn32_set_mpc_shaper_3dlut(
struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream)
{
@@ -500,7 +562,11 @@ void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context)
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+ // For SubVP + DRR, also force disallow on the DRR pipe
+ // (We will force allow in the DMUB sequence -- some DRR timings by default won't allow P-State so we have
+ // to force once the vblank is stretched).
+ if (pipe->stream && pipe->plane_state && (pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
+ (pipe->stream->mall_stream_config.type == SUBVP_NONE && pipe->stream->ignore_msa_timing_param))) {
struct hubp *hubp = pipe->plane_res.hubp;
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
@@ -544,9 +610,8 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context)
{
int i;
struct dce_hwseq *hws = dc->hwseq;
- // Update force P-state for each pipe accordingly
- if (hws && hws->funcs.subvp_update_force_pstate)
- hws->funcs.subvp_update_force_pstate(dc, context);
+
+ // Don't force p-state disallow -- can't block dummy p-state
// Update MALL_SEL register for each pipe
if (hws && hws->funcs.update_mall_sel)