aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2473-drm-amd-display-update-mpc-add-remove-functions.patch
diff options
context:
space:
mode:
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.patch347
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
+