linux/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "reg_helper.h"
  27#include "dcn10_mpc.h"
  28
  29#define REG(reg)\
  30        mpc10->mpc_regs->reg
  31
  32#define CTX \
  33        mpc10->base.ctx
  34
  35#undef FN
  36#define FN(reg_name, field_name) \
  37        mpc10->mpc_shift->field_name, mpc10->mpc_mask->field_name
  38
  39
  40void mpc1_set_bg_color(struct mpc *mpc,
  41                struct tg_color *bg_color,
  42                int mpcc_id)
  43{
  44        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
  45        struct mpcc *bottommost_mpcc = mpc1_get_mpcc(mpc, mpcc_id);
  46        uint32_t bg_r_cr, bg_g_y, bg_b_cb;
  47
  48        /* find bottommost mpcc. */
  49        while (bottommost_mpcc->mpcc_bot) {
  50                bottommost_mpcc = bottommost_mpcc->mpcc_bot;
  51        }
  52
  53        /* mpc color is 12 bit.  tg_color is 10 bit */
  54        /* todo: might want to use 16 bit to represent color and have each
  55         * hw block translate to correct color depth.
  56         */
  57        bg_r_cr = bg_color->color_r_cr << 2;
  58        bg_g_y = bg_color->color_g_y << 2;
  59        bg_b_cb = bg_color->color_b_cb << 2;
  60
  61        REG_SET(MPCC_BG_R_CR[bottommost_mpcc->mpcc_id], 0,
  62                        MPCC_BG_R_CR, bg_r_cr);
  63        REG_SET(MPCC_BG_G_Y[bottommost_mpcc->mpcc_id], 0,
  64                        MPCC_BG_G_Y, bg_g_y);
  65        REG_SET(MPCC_BG_B_CB[bottommost_mpcc->mpcc_id], 0,
  66                        MPCC_BG_B_CB, bg_b_cb);
  67}
  68
  69static void mpc1_update_blending(
  70        struct mpc *mpc,
  71        struct mpcc_blnd_cfg *blnd_cfg,
  72        int mpcc_id)
  73{
  74        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
  75        struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id);
  76
  77        REG_UPDATE_5(MPCC_CONTROL[mpcc_id],
  78                        MPCC_ALPHA_BLND_MODE,           blnd_cfg->alpha_mode,
  79                        MPCC_ALPHA_MULTIPLIED_MODE,     blnd_cfg->pre_multiplied_alpha,
  80                        MPCC_BLND_ACTIVE_OVERLAP_ONLY,  blnd_cfg->overlap_only,
  81                        MPCC_GLOBAL_ALPHA,              blnd_cfg->global_alpha,
  82                        MPCC_GLOBAL_GAIN,               blnd_cfg->global_gain);
  83
  84        mpc1_set_bg_color(mpc, &blnd_cfg->black_color, mpcc_id);
  85        mpcc->blnd_cfg = *blnd_cfg;
  86}
  87
  88void mpc1_update_stereo_mix(
  89        struct mpc *mpc,
  90        struct mpcc_sm_cfg *sm_cfg,
  91        int mpcc_id)
  92{
  93        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
  94
  95        REG_UPDATE_6(MPCC_SM_CONTROL[mpcc_id],
  96                        MPCC_SM_EN,                     sm_cfg->enable,
  97                        MPCC_SM_MODE,                   sm_cfg->sm_mode,
  98                        MPCC_SM_FRAME_ALT,              sm_cfg->frame_alt,
  99                        MPCC_SM_FIELD_ALT,              sm_cfg->field_alt,
 100                        MPCC_SM_FORCE_NEXT_FRAME_POL,   sm_cfg->force_next_frame_porlarity,
 101                        MPCC_SM_FORCE_NEXT_TOP_POL,     sm_cfg->force_next_field_polarity);
 102}
 103void mpc1_assert_idle_mpcc(struct mpc *mpc, int id)
 104{
 105        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 106
 107        ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id));
 108        REG_WAIT(MPCC_STATUS[id],
 109                        MPCC_IDLE, 1,
 110                        1, 100000);
 111}
 112
 113struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id)
 114{
 115        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 116
 117        ASSERT(mpcc_id < mpc10->num_mpcc);
 118        return &(mpc->mpcc_array[mpcc_id]);
 119}
 120
 121struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id)
 122{
 123        struct mpcc *tmp_mpcc = tree->opp_list;
 124
 125        while (tmp_mpcc != NULL) {
 126                if (tmp_mpcc->dpp_id == dpp_id)
 127                        return tmp_mpcc;
 128                tmp_mpcc = tmp_mpcc->mpcc_bot;
 129        }
 130        return NULL;
 131}
 132
 133bool mpc1_is_mpcc_idle(struct mpc *mpc, int mpcc_id)
 134{
 135        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 136        unsigned int top_sel;
 137        unsigned int opp_id;
 138        unsigned int idle;
 139
 140        REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel);
 141        REG_GET(MPCC_OPP_ID[mpcc_id],  MPCC_OPP_ID, &opp_id);
 142        REG_GET(MPCC_STATUS[mpcc_id],  MPCC_IDLE,   &idle);
 143        if (top_sel == 0xf && opp_id == 0xf && idle)
 144                return true;
 145        else
 146                return false;
 147}
 148
 149void mpc1_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id)
 150{
 151        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 152        unsigned int top_sel, mpc_busy, mpc_idle;
 153
 154        REG_GET(MPCC_TOP_SEL[mpcc_id],
 155                        MPCC_TOP_SEL, &top_sel);
 156
 157        if (top_sel == 0xf) {
 158                REG_GET_2(MPCC_STATUS[mpcc_id],
 159                                MPCC_BUSY, &mpc_busy,
 160                                MPCC_IDLE, &mpc_idle);
 161
 162                ASSERT(mpc_busy == 0);
 163                ASSERT(mpc_idle == 1);
 164        }
 165}
 166
 167/*
 168 * Insert DPP into MPC tree based on specified blending position.
 169 * Only used for planes that are part of blending chain for OPP output
 170 *
 171 * Parameters:
 172 * [in/out] mpc         - MPC context.
 173 * [in/out] tree        - MPC tree structure that plane will be added to.
 174 * [in] blnd_cfg        - MPCC blending configuration for the new blending layer.
 175 * [in] sm_cfg          - MPCC stereo mix configuration for the new blending layer.
 176 *                        stereo mix must disable for the very bottom layer of the tree config.
 177 * [in] insert_above_mpcc - Insert new plane above this MPCC.  If NULL, insert as bottom plane.
 178 * [in] dpp_id          - DPP instance for the plane to be added.
 179 * [in] mpcc_id         - The MPCC physical instance to use for blending.
 180 *
 181 * Return:  struct mpcc* - MPCC that was added.
 182 */
 183struct mpcc *mpc1_insert_plane(
 184        struct mpc *mpc,
 185        struct mpc_tree *tree,
 186        struct mpcc_blnd_cfg *blnd_cfg,
 187        struct mpcc_sm_cfg *sm_cfg,
 188        struct mpcc *insert_above_mpcc,
 189        int dpp_id,
 190        int mpcc_id)
 191{
 192        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 193        struct mpcc *new_mpcc = NULL;
 194
 195        /* sanity check parameters */
 196        ASSERT(mpcc_id < mpc10->num_mpcc);
 197        ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id));
 198
 199        if (insert_above_mpcc) {
 200                /* check insert_above_mpcc exist in tree->opp_list */
 201                struct mpcc *temp_mpcc = tree->opp_list;
 202
 203                while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc)
 204                        temp_mpcc = temp_mpcc->mpcc_bot;
 205                if (temp_mpcc == NULL)
 206                        return NULL;
 207        }
 208
 209        /* Get and update MPCC struct parameters */
 210        new_mpcc = mpc1_get_mpcc(mpc, mpcc_id);
 211        new_mpcc->dpp_id = dpp_id;
 212
 213        /* program mux and MPCC_MODE */
 214        if (insert_above_mpcc) {
 215                new_mpcc->mpcc_bot = insert_above_mpcc;
 216                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, insert_above_mpcc->mpcc_id);
 217                REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING);
 218        } else {
 219                new_mpcc->mpcc_bot = NULL;
 220                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 221                REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_ONLY);
 222        }
 223        REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id);
 224        REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id);
 225
 226        /* update mpc tree mux setting */
 227        if (tree->opp_list == insert_above_mpcc) {
 228                /* insert the toppest mpcc */
 229                tree->opp_list = new_mpcc;
 230                REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, mpcc_id);
 231        } else {
 232                /* find insert position */
 233                struct mpcc *temp_mpcc = tree->opp_list;
 234
 235                while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc)
 236                        temp_mpcc = temp_mpcc->mpcc_bot;
 237                if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) {
 238                        REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id);
 239                        temp_mpcc->mpcc_bot = new_mpcc;
 240                        if (!insert_above_mpcc)
 241                                REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
 242                                                MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING);
 243                }
 244        }
 245
 246        /* update the blending configuration */
 247        mpc->funcs->update_blending(mpc, blnd_cfg, mpcc_id);
 248
 249        /* update the stereo mix settings, if provided */
 250        if (sm_cfg != NULL) {
 251                new_mpcc->sm_cfg = *sm_cfg;
 252                mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id);
 253        }
 254
 255        /* mark this mpcc as in use */
 256        mpc10->mpcc_in_use_mask |= 1 << mpcc_id;
 257
 258        return new_mpcc;
 259}
 260
 261/*
 262 * Remove a specified MPCC from the MPC tree.
 263 *
 264 * Parameters:
 265 * [in/out] mpc         - MPC context.
 266 * [in/out] tree        - MPC tree structure that plane will be removed from.
 267 * [in/out] mpcc        - MPCC to be removed from tree.
 268 *
 269 * Return:  void
 270 */
 271void mpc1_remove_mpcc(
 272        struct mpc *mpc,
 273        struct mpc_tree *tree,
 274        struct mpcc *mpcc_to_remove)
 275{
 276        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 277        bool found = false;
 278        int mpcc_id = mpcc_to_remove->mpcc_id;
 279
 280        if (tree->opp_list == mpcc_to_remove) {
 281                found = true;
 282                /* remove MPCC from top of tree */
 283                if (mpcc_to_remove->mpcc_bot) {
 284                        /* set the next MPCC in list to be the top MPCC */
 285                        tree->opp_list = mpcc_to_remove->mpcc_bot;
 286                        REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id);
 287                } else {
 288                        /* there are no other MPCC is list */
 289                        tree->opp_list = NULL;
 290                        REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf);
 291                }
 292        } else {
 293                /* find mpcc to remove MPCC list */
 294                struct mpcc *temp_mpcc = tree->opp_list;
 295
 296                while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove)
 297                        temp_mpcc = temp_mpcc->mpcc_bot;
 298
 299                if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) {
 300                        found = true;
 301                        temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot;
 302                        if (mpcc_to_remove->mpcc_bot) {
 303                                /* remove MPCC in middle of list */
 304                                REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
 305                                                MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id);
 306                        } else {
 307                                /* remove MPCC from bottom of list */
 308                                REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
 309                                                MPCC_BOT_SEL, 0xf);
 310                                REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
 311                                                MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH);
 312                        }
 313                }
 314        }
 315
 316        if (found) {
 317                /* turn off MPCC mux registers */
 318                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 319                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 320                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 321
 322                /* mark this mpcc as not in use */
 323                mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
 324                mpcc_to_remove->dpp_id = 0xf;
 325                mpcc_to_remove->mpcc_bot = NULL;
 326        } else {
 327                /* In case of resume from S3/S4, remove mpcc from bios left over */
 328                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 329                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 330                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 331        }
 332}
 333
 334static void mpc1_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
 335{
 336        mpcc->mpcc_id = mpcc_inst;
 337        mpcc->dpp_id = 0xf;
 338        mpcc->mpcc_bot = NULL;
 339        mpcc->blnd_cfg.overlap_only = false;
 340        mpcc->blnd_cfg.global_alpha = 0xff;
 341        mpcc->blnd_cfg.global_gain = 0xff;
 342        mpcc->sm_cfg.enable = false;
 343}
 344
 345/*
 346 * Reset the MPCC HW status by disconnecting all muxes.
 347 *
 348 * Parameters:
 349 * [in/out] mpc         - MPC context.
 350 *
 351 * Return:  void
 352 */
 353void mpc1_mpc_init(struct mpc *mpc)
 354{
 355        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 356        int mpcc_id;
 357        int opp_id;
 358
 359        mpc10->mpcc_in_use_mask = 0;
 360        for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) {
 361                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 362                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 363                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 364
 365                mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
 366        }
 367
 368        for (opp_id = 0; opp_id < MAX_OPP; opp_id++) {
 369                if (REG(MUX[opp_id]))
 370                        REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf);
 371        }
 372}
 373
 374void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
 375{
 376        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 377        int opp_id;
 378
 379        REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id);
 380
 381        REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 382        REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 383        REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 384
 385        mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
 386
 387        if (opp_id < MAX_OPP && REG(MUX[opp_id]))
 388                REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf);
 389}
 390
 391
 392void mpc1_init_mpcc_list_from_hw(
 393        struct mpc *mpc,
 394        struct mpc_tree *tree)
 395{
 396        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 397        unsigned int opp_id;
 398        unsigned int top_sel;
 399        unsigned int bot_sel;
 400        unsigned int out_mux;
 401        struct mpcc *mpcc;
 402        int mpcc_id;
 403        int bot_mpcc_id;
 404
 405        REG_GET(MUX[tree->opp_id], MPC_OUT_MUX, &out_mux);
 406
 407        if (out_mux != 0xf) {
 408                for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) {
 409                        REG_GET(MPCC_OPP_ID[mpcc_id],  MPCC_OPP_ID,  &opp_id);
 410                        REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel);
 411                        REG_GET(MPCC_BOT_SEL[mpcc_id],  MPCC_BOT_SEL, &bot_sel);
 412
 413                        if (bot_sel == mpcc_id)
 414                                bot_sel = 0xf;
 415
 416                        if ((opp_id == tree->opp_id) && (top_sel != 0xf)) {
 417                                mpcc = mpc1_get_mpcc(mpc, mpcc_id);
 418                                mpcc->dpp_id = top_sel;
 419                                mpc10->mpcc_in_use_mask |= 1 << mpcc_id;
 420
 421                                if (out_mux == mpcc_id)
 422                                        tree->opp_list = mpcc;
 423                                if (bot_sel != 0xf && bot_sel < mpc10->num_mpcc) {
 424                                        bot_mpcc_id = bot_sel;
 425                                        REG_GET(MPCC_OPP_ID[bot_mpcc_id],  MPCC_OPP_ID,  &opp_id);
 426                                        REG_GET(MPCC_TOP_SEL[bot_mpcc_id], MPCC_TOP_SEL, &top_sel);
 427                                        if ((opp_id == tree->opp_id) && (top_sel != 0xf)) {
 428                                                struct mpcc *mpcc_bottom = mpc1_get_mpcc(mpc, bot_mpcc_id);
 429
 430                                                mpcc->mpcc_bot = mpcc_bottom;
 431                                        }
 432                                }
 433                        }
 434                }
 435        }
 436}
 437
 438void mpc1_read_mpcc_state(
 439                struct mpc *mpc,
 440                int mpcc_inst,
 441                struct mpcc_state *s)
 442{
 443        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 444
 445        REG_GET(MPCC_OPP_ID[mpcc_inst], MPCC_OPP_ID, &s->opp_id);
 446        REG_GET(MPCC_TOP_SEL[mpcc_inst], MPCC_TOP_SEL, &s->dpp_id);
 447        REG_GET(MPCC_BOT_SEL[mpcc_inst], MPCC_BOT_SEL, &s->bot_mpcc_id);
 448        REG_GET_4(MPCC_CONTROL[mpcc_inst], MPCC_MODE, &s->mode,
 449                        MPCC_ALPHA_BLND_MODE, &s->alpha_mode,
 450                        MPCC_ALPHA_MULTIPLIED_MODE, &s->pre_multiplied_alpha,
 451                        MPCC_BLND_ACTIVE_OVERLAP_ONLY, &s->overlap_only);
 452        REG_GET_2(MPCC_STATUS[mpcc_inst], MPCC_IDLE, &s->idle,
 453                        MPCC_BUSY, &s->busy);
 454}
 455
 456static const struct mpc_funcs dcn10_mpc_funcs = {
 457        .read_mpcc_state = mpc1_read_mpcc_state,
 458        .insert_plane = mpc1_insert_plane,
 459        .remove_mpcc = mpc1_remove_mpcc,
 460        .mpc_init = mpc1_mpc_init,
 461        .mpc_init_single_inst = mpc1_mpc_init_single_inst,
 462        .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
 463        .wait_for_idle = mpc1_assert_idle_mpcc,
 464        .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect,
 465        .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
 466        .update_blending = mpc1_update_blending,
 467        .set_denorm = NULL,
 468        .set_denorm_clamp = NULL,
 469        .set_output_csc = NULL,
 470        .set_output_gamma = NULL,
 471};
 472
 473void dcn10_mpc_construct(struct dcn10_mpc *mpc10,
 474        struct dc_context *ctx,
 475        const struct dcn_mpc_registers *mpc_regs,
 476        const struct dcn_mpc_shift *mpc_shift,
 477        const struct dcn_mpc_mask *mpc_mask,
 478        int num_mpcc)
 479{
 480        int i;
 481
 482        mpc10->base.ctx = ctx;
 483
 484        mpc10->base.funcs = &dcn10_mpc_funcs;
 485
 486        mpc10->mpc_regs = mpc_regs;
 487        mpc10->mpc_shift = mpc_shift;
 488        mpc10->mpc_mask = mpc_mask;
 489
 490        mpc10->mpcc_in_use_mask = 0;
 491        mpc10->num_mpcc = num_mpcc;
 492
 493        for (i = 0; i < MAX_MPCC; i++)
 494                mpc1_init_mpcc(&mpc10->base.mpcc_array[i], i);
 495}
 496
 497