diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch new file mode 100644 index 00000000..09fc6496 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch @@ -0,0 +1,347 @@ +From f0ecdd563a909f7ad6b349d819d7b3a7ac169dd2 Mon Sep 17 00:00:00 2001 +From: Eric Bernstein <eric.bernstein@amd.com> +Date: Mon, 11 Sep 2017 16:56:51 -0400 +Subject: [PATCH 2473/4131] drm/amd/display: update mpc add/remove functions + +Signed-off-by: Eric Bernstein <eric.bernstein@amd.com> +Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +--- + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 +- + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 173 ++++++++++++++------- + drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 10 +- + 3 files changed, 130 insertions(+), 70 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 e60be00a..82a985a 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 +@@ -881,7 +881,8 @@ static void dcn10_init_hw(struct dc *dc) + + xfm->funcs->transform_reset(xfm); + dc->res_pool->mpc->funcs->remove( +- dc->res_pool->mpc, dc->res_pool->opps[i], i); ++ dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), ++ dc->res_pool->opps[i]->inst, i); + + /* Blank controller using driver code instead of + * command table. +@@ -1079,7 +1080,8 @@ static void plane_atomic_disconnect(struct dc *dc, + if (dc->debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + +- mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); ++ mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), ++ dc->res_pool->opps[opp_id]->inst, fe_idx); + } + + /* disable HW used by plane. +@@ -2299,8 +2301,9 @@ static void update_dchubp_dpp( + plane_state->format, + EXPANSION_MODE_ZERO); + +- mpcc_cfg.mi = mi; +- mpcc_cfg.opp = pipe_ctx->stream_res.opp; ++ mpcc_cfg.dpp_id = mi->inst; ++ mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; ++ mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); + for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) + mpcc_cfg.z_index++; + if (dc->debug.surface_visual_confirm) +@@ -2317,7 +2320,8 @@ static void update_dchubp_dpp( + mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( + pipe_ctx->stream->output_color_space) + && per_pixel_alpha; +- dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); ++ mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); ++ mi->opp_id = mpcc_cfg.opp_id; + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; +@@ -2528,7 +2532,8 @@ static void dcn10_apply_ctx_for_surface( + /* reset mpc */ + dc->res_pool->mpc->funcs->remove( + dc->res_pool->mpc, +- old_pipe_ctx->stream_res.opp, ++ &(old_pipe_ctx->stream_res.opp->mpc_tree), ++ old_pipe_ctx->stream_res.opp->inst, + old_pipe_ctx->pipe_idx); + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +index 082b39a..8e767c8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +@@ -118,17 +118,19 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i + + static void mpc10_mpcc_remove( + struct mpc *mpc, +- struct output_pixel_processor *opp, ++ struct mpc_tree_cfg *tree_cfg, ++ int opp_id, + int dpp_id) + { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + +- for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) +- if (opp->mpc_tree.dpp[z_idx] == dpp_id) ++ /* find z_idx for the dpp to be removed */ ++ for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) ++ if (tree_cfg->dpp[z_idx] == dpp_id) + break; + +- if (z_idx == opp->mpc_tree.num_pipes) { ++ if (z_idx == tree_cfg->num_pipes) { + /* In case of resume from S3/S4, remove mpcc from bios left over */ + REG_SET(MPCC_OPP_ID[dpp_id], 0, + MPCC_OPP_ID, 0xf); +@@ -139,7 +141,7 @@ static void mpc10_mpcc_remove( + return; + } + +- mpcc_id = opp->mpc_tree.mpcc[z_idx]; ++ mpcc_id = tree_cfg->mpcc[z_idx]; + + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, 0xf); +@@ -149,82 +151,101 @@ static void mpc10_mpcc_remove( + MPCC_BOT_SEL, 0xf); + + if (z_idx > 0) { +- int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; ++ int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; + +- if (z_idx + 1 < opp->mpc_tree.num_pipes) ++ if (z_idx + 1 < tree_cfg->num_pipes) ++ /* mpcc to be removed is in the middle of the tree */ + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, +- MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); ++ MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); + else { ++ /* mpcc to be removed is at the bottom of the tree */ + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + MPCC_MODE, MODE_TOP_ONLY); + } +- } else if (opp->mpc_tree.num_pipes > 1) +- REG_SET(MUX[opp->inst], 0, +- MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); ++ } else if (tree_cfg->num_pipes > 1) ++ /* mpcc to be removed is at the top of the tree */ ++ REG_SET(MUX[opp_id], 0, ++ MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); + else +- REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); ++ /* mpcc to be removed is the only one in the tree */ ++ REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); + ++ /* mark this mpcc as not in use */ + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); +- opp->mpc_tree.num_pipes--; +- for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { +- opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; +- opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; ++ tree_cfg->num_pipes--; ++ for (; z_idx < tree_cfg->num_pipes; z_idx++) { ++ tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; ++ tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; + } +- opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; +- opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; ++ tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; ++ tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; + } + +-static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) ++static void mpc10_add_to_tree_cfg( ++ struct mpc *mpc, ++ struct mpcc_cfg *cfg, ++ int mpcc_id) + { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); ++ int mpcc_mode = MODE_TOP_ONLY; ++ int position = cfg->z_index; ++ struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; +- int mpcc_mode = MODE_TOP_ONLY; +- int mpcc_id, z_idx; ++ int z_idx; + +- ASSERT(cfg->z_index < mpc10->num_mpcc); ++ REG_SET(MPCC_OPP_ID[mpcc_id], 0, ++ MPCC_OPP_ID, cfg->opp_id); + +- for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) +- if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) +- break; +- if (z_idx == cfg->opp->mpc_tree.num_pipes) { +- ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); +- mpcc_id = mpc10_get_idle_mpcc_id(mpc10); +- /*todo: remove hack*/ +- mpcc_id = cfg->mi->inst; +- ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); ++ REG_SET(MPCC_TOP_SEL[mpcc_id], 0, ++ MPCC_TOP_SEL, cfg->dpp_id); + +- if (mpc->ctx->dc->debug.sanity_checks) +- mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); +- } else { +- ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); +- mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; +- mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); +- } ++ if (position == 0) { ++ /* idle dpp/mpcc is added to the top layer of tree */ + +- REG_SET(MPCC_OPP_ID[mpcc_id], 0, +- MPCC_OPP_ID, cfg->opp->inst); ++ if (tree_cfg->num_pipes > 0) { ++ /* get instance of previous top mpcc */ ++ int prev_top_mpcc_id = tree_cfg->mpcc[0]; + +- REG_SET(MPCC_TOP_SEL[mpcc_id], 0, +- MPCC_TOP_SEL, cfg->mi->inst); ++ REG_SET(MPCC_BOT_SEL[mpcc_id], 0, ++ MPCC_BOT_SEL, prev_top_mpcc_id); ++ mpcc_mode = MODE_BLEND; ++ } ++ ++ /* opp will get new output. from new added mpcc */ ++ REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); ++ ++ } else if (position == tree_cfg->num_pipes) { ++ /* idle dpp/mpcc is added to the bottom layer of tree */ + +- if (cfg->z_index > 0) { +- int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; ++ /* get instance of previous bottom mpcc, set to middle layer */ ++ int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + +- REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, ++ REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); +- REG_UPDATE(MPCC_CONTROL[top_mpcc_id], ++ REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], + MPCC_MODE, MODE_BLEND); +- } else +- REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); + +- if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { +- int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; ++ /* mpcc_id become new bottom mpcc*/ ++ REG_SET(MPCC_BOT_SEL[mpcc_id], 0, ++ MPCC_BOT_SEL, 0xf); ++ ++ } else { ++ /* idle dpp/mpcc is added to middle of tree */ ++ int above_mpcc_id = tree_cfg->mpcc[position - 1]; ++ int below_mpcc_id = tree_cfg->mpcc[position]; ++ ++ /* mpcc above new mpcc_id has new bottom mux*/ ++ REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, ++ MPCC_BOT_SEL, mpcc_id); ++ REG_UPDATE(MPCC_CONTROL[above_mpcc_id], ++ MPCC_MODE, MODE_BLEND); + ++ /* mpcc_id bottom mux is from below mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, +- MPCC_BOT_SEL, bot_mpcc_id); ++ MPCC_BOT_SEL, below_mpcc_id); + mpcc_mode = MODE_BLEND; + } + +@@ -234,18 +255,50 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + ++ /* update mpc_tree_cfg with new mpcc */ ++ for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { ++ tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; ++ tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; ++ } ++ tree_cfg->dpp[position] = cfg->dpp_id; ++ tree_cfg->mpcc[position] = mpcc_id; ++ tree_cfg->num_pipes++; ++} ++ ++static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) ++{ ++ struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); ++ int mpcc_id, z_idx; ++ ++ ASSERT(cfg->z_index < mpc10->num_mpcc); ++ ++ /* check in dpp already exists in mpc tree */ ++ for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) ++ if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) ++ break; ++ if (z_idx == cfg->tree_cfg->num_pipes) { ++ ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); ++ mpcc_id = mpc10_get_idle_mpcc_id(mpc10); ++ ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); ++ ++ if (mpc->ctx->dc->debug.sanity_checks) ++ mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); ++ } else { ++ ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); ++ mpcc_id = cfg->tree_cfg->mpcc[z_idx]; ++ mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); ++ } ++ ++ /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ ++ mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); ++ ++ /* set background color */ + mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); + ++ /* mark this mpcc as in use */ + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; +- for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { +- cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; +- cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; +- } +- cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; +- cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; +- cfg->opp->mpc_tree.num_pipes++; +- cfg->mi->opp_id = cfg->opp->inst; +- cfg->mi->mpcc_id = mpcc_id; ++ ++ return mpcc_id; + } + + const struct mpc_funcs dcn10_mpc_funcs = { +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +index 4bbcff4..2d3de5b 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +@@ -29,8 +29,9 @@ + #include "opp.h" + + struct mpcc_cfg { +- struct mem_input *mi; +- struct output_pixel_processor *opp; ++ int dpp_id; ++ int opp_id; ++ struct mpc_tree_cfg *tree_cfg; + unsigned int z_index; + + struct tg_color black_color; +@@ -44,9 +45,10 @@ struct mpc { + }; + + struct mpc_funcs { +- void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); ++ int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, +- struct output_pixel_processor *opp, ++ struct mpc_tree_cfg *tree_cfg, ++ int opp_id, + int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); + }; +-- +2.7.4 + |