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        /* Configure VUPDATE lock set for this MPCC to map to the OPP */
 227        REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id);
 228
 229        /* update mpc tree mux setting */
 230        if (tree->opp_list == insert_above_mpcc) {
 231                /* insert the toppest mpcc */
 232                tree->opp_list = new_mpcc;
 233                REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, mpcc_id);
 234        } else {
 235                /* find insert position */
 236                struct mpcc *temp_mpcc = tree->opp_list;
 237
 238                while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc)
 239                        temp_mpcc = temp_mpcc->mpcc_bot;
 240                if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) {
 241                        REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id);
 242                        temp_mpcc->mpcc_bot = new_mpcc;
 243                        if (!insert_above_mpcc)
 244                                REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
 245                                                MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING);
 246                }
 247        }
 248
 249        /* update the blending configuration */
 250        mpc->funcs->update_blending(mpc, blnd_cfg, mpcc_id);
 251
 252        /* update the stereo mix settings, if provided */
 253        if (sm_cfg != NULL) {
 254                new_mpcc->sm_cfg = *sm_cfg;
 255                mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id);
 256        }
 257
 258        /* mark this mpcc as in use */
 259        mpc10->mpcc_in_use_mask |= 1 << mpcc_id;
 260
 261        return new_mpcc;
 262}
 263
 264/*
 265 * Remove a specified MPCC from the MPC tree.
 266 *
 267 * Parameters:
 268 * [in/out] mpc         - MPC context.
 269 * [in/out] tree        - MPC tree structure that plane will be removed from.
 270 * [in/out] mpcc        - MPCC to be removed from tree.
 271 *
 272 * Return:  void
 273 */
 274void mpc1_remove_mpcc(
 275        struct mpc *mpc,
 276        struct mpc_tree *tree,
 277        struct mpcc *mpcc_to_remove)
 278{
 279        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 280        bool found = false;
 281        int mpcc_id = mpcc_to_remove->mpcc_id;
 282
 283        if (tree->opp_list == mpcc_to_remove) {
 284                found = true;
 285                /* remove MPCC from top of tree */
 286                if (mpcc_to_remove->mpcc_bot) {
 287                        /* set the next MPCC in list to be the top MPCC */
 288                        tree->opp_list = mpcc_to_remove->mpcc_bot;
 289                        REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id);
 290                } else {
 291                        /* there are no other MPCC is list */
 292                        tree->opp_list = NULL;
 293                        REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf);
 294                }
 295        } else {
 296                /* find mpcc to remove MPCC list */
 297                struct mpcc *temp_mpcc = tree->opp_list;
 298
 299                while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove)
 300                        temp_mpcc = temp_mpcc->mpcc_bot;
 301
 302                if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) {
 303                        found = true;
 304                        temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot;
 305                        if (mpcc_to_remove->mpcc_bot) {
 306                                /* remove MPCC in middle of list */
 307                                REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
 308                                                MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id);
 309                        } else {
 310                                /* remove MPCC from bottom of list */
 311                                REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
 312                                                MPCC_BOT_SEL, 0xf);
 313                                REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
 314                                                MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH);
 315                        }
 316                }
 317        }
 318
 319        if (found) {
 320                /* turn off MPCC mux registers */
 321                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 322                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 323                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 324                REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 325
 326                /* mark this mpcc as not in use */
 327                mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
 328                mpcc_to_remove->dpp_id = 0xf;
 329                mpcc_to_remove->mpcc_bot = NULL;
 330        } else {
 331                /* In case of resume from S3/S4, remove mpcc from bios left over */
 332                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 333                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 334                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 335                REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 336        }
 337}
 338
 339static void mpc1_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
 340{
 341        mpcc->mpcc_id = mpcc_inst;
 342        mpcc->dpp_id = 0xf;
 343        mpcc->mpcc_bot = NULL;
 344        mpcc->blnd_cfg.overlap_only = false;
 345        mpcc->blnd_cfg.global_alpha = 0xff;
 346        mpcc->blnd_cfg.global_gain = 0xff;
 347        mpcc->sm_cfg.enable = false;
 348}
 349
 350/*
 351 * Reset the MPCC HW status by disconnecting all muxes.
 352 *
 353 * Parameters:
 354 * [in/out] mpc         - MPC context.
 355 *
 356 * Return:  void
 357 */
 358void mpc1_mpc_init(struct mpc *mpc)
 359{
 360        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 361        int mpcc_id;
 362        int opp_id;
 363
 364        mpc10->mpcc_in_use_mask = 0;
 365        for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) {
 366                REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 367                REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 368                REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 369                REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 370
 371                mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
 372        }
 373
 374        for (opp_id = 0; opp_id < MAX_OPP; opp_id++) {
 375                if (REG(MUX[opp_id]))
 376                        REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf);
 377        }
 378}
 379
 380void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
 381{
 382        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 383        int opp_id;
 384
 385        REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id);
 386
 387        REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
 388        REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
 389        REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
 390        REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);
 391
 392        mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id);
 393
 394        if (opp_id < MAX_OPP && REG(MUX[opp_id]))
 395                REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf);
 396}
 397
 398
 399void mpc1_init_mpcc_list_from_hw(
 400        struct mpc *mpc,
 401        struct mpc_tree *tree)
 402{
 403        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 404        unsigned int opp_id;
 405        unsigned int top_sel;
 406        unsigned int bot_sel;
 407        unsigned int out_mux;
 408        struct mpcc *mpcc;
 409        int mpcc_id;
 410        int bot_mpcc_id;
 411
 412        REG_GET(MUX[tree->opp_id], MPC_OUT_MUX, &out_mux);
 413
 414        if (out_mux != 0xf) {
 415                for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) {
 416                        REG_GET(MPCC_OPP_ID[mpcc_id],  MPCC_OPP_ID,  &opp_id);
 417                        REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel);
 418                        REG_GET(MPCC_BOT_SEL[mpcc_id],  MPCC_BOT_SEL, &bot_sel);
 419
 420                        if (bot_sel == mpcc_id)
 421                                bot_sel = 0xf;
 422
 423                        if ((opp_id == tree->opp_id) && (top_sel != 0xf)) {
 424                                mpcc = mpc1_get_mpcc(mpc, mpcc_id);
 425                                mpcc->dpp_id = top_sel;
 426                                mpc10->mpcc_in_use_mask |= 1 << mpcc_id;
 427
 428                                if (out_mux == mpcc_id)
 429                                        tree->opp_list = mpcc;
 430                                if (bot_sel != 0xf && bot_sel < mpc10->num_mpcc) {
 431                                        bot_mpcc_id = bot_sel;
 432                                        REG_GET(MPCC_OPP_ID[bot_mpcc_id],  MPCC_OPP_ID,  &opp_id);
 433                                        REG_GET(MPCC_TOP_SEL[bot_mpcc_id], MPCC_TOP_SEL, &top_sel);
 434                                        if ((opp_id == tree->opp_id) && (top_sel != 0xf)) {
 435                                                struct mpcc *mpcc_bottom = mpc1_get_mpcc(mpc, bot_mpcc_id);
 436
 437                                                mpcc->mpcc_bot = mpcc_bottom;
 438                                        }
 439                                }
 440                        }
 441                }
 442        }
 443}
 444
 445void mpc1_read_mpcc_state(
 446                struct mpc *mpc,
 447                int mpcc_inst,
 448                struct mpcc_state *s)
 449{
 450        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 451
 452        REG_GET(MPCC_OPP_ID[mpcc_inst], MPCC_OPP_ID, &s->opp_id);
 453        REG_GET(MPCC_TOP_SEL[mpcc_inst], MPCC_TOP_SEL, &s->dpp_id);
 454        REG_GET(MPCC_BOT_SEL[mpcc_inst], MPCC_BOT_SEL, &s->bot_mpcc_id);
 455        REG_GET_4(MPCC_CONTROL[mpcc_inst], MPCC_MODE, &s->mode,
 456                        MPCC_ALPHA_BLND_MODE, &s->alpha_mode,
 457                        MPCC_ALPHA_MULTIPLIED_MODE, &s->pre_multiplied_alpha,
 458                        MPCC_BLND_ACTIVE_OVERLAP_ONLY, &s->overlap_only);
 459        REG_GET_2(MPCC_STATUS[mpcc_inst], MPCC_IDLE, &s->idle,
 460                        MPCC_BUSY, &s->busy);
 461}
 462
 463void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock)
 464{
 465        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
 466
 467        REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0);
 468}
 469
 470static const struct mpc_funcs dcn10_mpc_funcs = {
 471        .read_mpcc_state = mpc1_read_mpcc_state,
 472        .insert_plane = mpc1_insert_plane,
 473        .remove_mpcc = mpc1_remove_mpcc,
 474        .mpc_init = mpc1_mpc_init,
 475        .mpc_init_single_inst = mpc1_mpc_init_single_inst,
 476        .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
 477        .wait_for_idle = mpc1_assert_idle_mpcc,
 478        .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect,
 479        .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
 480        .update_blending = mpc1_update_blending,
 481        .cursor_lock = mpc1_cursor_lock,
 482        .set_denorm = NULL,
 483        .set_denorm_clamp = NULL,
 484        .set_output_csc = NULL,
 485        .set_output_gamma = NULL,
 486};
 487
 488void dcn10_mpc_construct(struct dcn10_mpc *mpc10,
 489        struct dc_context *ctx,
 490        const struct dcn_mpc_registers *mpc_regs,
 491        const struct dcn_mpc_shift *mpc_shift,
 492        const struct dcn_mpc_mask *mpc_mask,
 493        int num_mpcc)
 494{
 495        int i;
 496
 497        mpc10->base.ctx = ctx;
 498
 499        mpc10->base.funcs = &dcn10_mpc_funcs;
 500
 501        mpc10->mpc_regs = mpc_regs;
 502        mpc10->mpc_shift = mpc_shift;
 503        mpc10->mpc_mask = mpc_mask;
 504
 505        mpc10->mpcc_in_use_mask = 0;
 506        mpc10->num_mpcc = num_mpcc;
 507
 508        for (i = 0; i < MAX_MPCC; i++)
 509                mpc1_init_mpcc(&mpc10->base.mpcc_array[i], i);
 510}
 511
 512