drm/amd/display: update mpc add/remove functions
authorEric Bernstein <eric.bernstein@amd.com>
Mon, 11 Sep 2017 20:56:51 +0000 (16:56 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 21 Oct 2017 20:40:45 +0000 (16:40 -0400)
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>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h

index e60be00..82a985a 100644 (file)
@@ -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;
 
index 082b39a..8e767c8 100644 (file)
@@ -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 = {
index 4bbcff4..2d3de5b 100644 (file)
@@ -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);
 };