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 40 void 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 bottommost_mpcc->blnd_cfg.black_color = *bg_color; 49 50 /* find bottommost mpcc. */ 51 while (bottommost_mpcc->mpcc_bot) { 52 bottommost_mpcc = bottommost_mpcc->mpcc_bot; 53 } 54 55 /* mpc color is 12 bit. tg_color is 10 bit */ 56 /* todo: might want to use 16 bit to represent color and have each 57 * hw block translate to correct color depth. 58 */ 59 bg_r_cr = bg_color->color_r_cr << 2; 60 bg_g_y = bg_color->color_g_y << 2; 61 bg_b_cb = bg_color->color_b_cb << 2; 62 63 REG_SET(MPCC_BG_R_CR[bottommost_mpcc->mpcc_id], 0, 64 MPCC_BG_R_CR, bg_r_cr); 65 REG_SET(MPCC_BG_G_Y[bottommost_mpcc->mpcc_id], 0, 66 MPCC_BG_G_Y, bg_g_y); 67 REG_SET(MPCC_BG_B_CB[bottommost_mpcc->mpcc_id], 0, 68 MPCC_BG_B_CB, bg_b_cb); 69 } 70 71 static void mpc1_update_blending( 72 struct mpc *mpc, 73 struct mpcc_blnd_cfg *blnd_cfg, 74 int mpcc_id) 75 { 76 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 77 struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id); 78 79 REG_UPDATE_5(MPCC_CONTROL[mpcc_id], 80 MPCC_ALPHA_BLND_MODE, blnd_cfg->alpha_mode, 81 MPCC_ALPHA_MULTIPLIED_MODE, blnd_cfg->pre_multiplied_alpha, 82 MPCC_BLND_ACTIVE_OVERLAP_ONLY, blnd_cfg->overlap_only, 83 MPCC_GLOBAL_ALPHA, blnd_cfg->global_alpha, 84 MPCC_GLOBAL_GAIN, blnd_cfg->global_gain); 85 86 mpcc->blnd_cfg = *blnd_cfg; 87 } 88 89 void mpc1_update_stereo_mix( 90 struct mpc *mpc, 91 struct mpcc_sm_cfg *sm_cfg, 92 int mpcc_id) 93 { 94 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 95 96 REG_UPDATE_6(MPCC_SM_CONTROL[mpcc_id], 97 MPCC_SM_EN, sm_cfg->enable, 98 MPCC_SM_MODE, sm_cfg->sm_mode, 99 MPCC_SM_FRAME_ALT, sm_cfg->frame_alt, 100 MPCC_SM_FIELD_ALT, sm_cfg->field_alt, 101 MPCC_SM_FORCE_NEXT_FRAME_POL, sm_cfg->force_next_frame_porlarity, 102 MPCC_SM_FORCE_NEXT_TOP_POL, sm_cfg->force_next_field_polarity); 103 } 104 void mpc1_assert_idle_mpcc(struct mpc *mpc, int id) 105 { 106 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 107 108 ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); 109 REG_WAIT(MPCC_STATUS[id], 110 MPCC_IDLE, 1, 111 1, 100000); 112 } 113 114 struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id) 115 { 116 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 117 118 ASSERT(mpcc_id < mpc10->num_mpcc); 119 return &(mpc->mpcc_array[mpcc_id]); 120 } 121 122 struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id) 123 { 124 struct mpcc *tmp_mpcc = tree->opp_list; 125 126 while (tmp_mpcc != NULL) { 127 if (tmp_mpcc->dpp_id == dpp_id) 128 return tmp_mpcc; 129 tmp_mpcc = tmp_mpcc->mpcc_bot; 130 } 131 return NULL; 132 } 133 134 bool mpc1_is_mpcc_idle(struct mpc *mpc, int mpcc_id) 135 { 136 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 137 unsigned int top_sel; 138 unsigned int opp_id; 139 unsigned int idle; 140 141 REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); 142 REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); 143 REG_GET(MPCC_STATUS[mpcc_id], MPCC_IDLE, &idle); 144 if (top_sel == 0xf && opp_id == 0xf && idle) 145 return true; 146 else 147 return false; 148 } 149 150 void mpc1_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id) 151 { 152 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 153 unsigned int top_sel, mpc_busy, mpc_idle; 154 155 REG_GET(MPCC_TOP_SEL[mpcc_id], 156 MPCC_TOP_SEL, &top_sel); 157 158 if (top_sel == 0xf) { 159 REG_GET_2(MPCC_STATUS[mpcc_id], 160 MPCC_BUSY, &mpc_busy, 161 MPCC_IDLE, &mpc_idle); 162 163 ASSERT(mpc_busy == 0); 164 ASSERT(mpc_idle == 1); 165 } 166 } 167 168 /* 169 * Insert DPP into MPC tree based on specified blending position. 170 * Only used for planes that are part of blending chain for OPP output 171 * 172 * Parameters: 173 * [in/out] mpc - MPC context. 174 * [in/out] tree - MPC tree structure that plane will be added to. 175 * [in] blnd_cfg - MPCC blending configuration for the new blending layer. 176 * [in] sm_cfg - MPCC stereo mix configuration for the new blending layer. 177 * stereo mix must disable for the very bottom layer of the tree config. 178 * [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane. 179 * [in] dpp_id - DPP instance for the plane to be added. 180 * [in] mpcc_id - The MPCC physical instance to use for blending. 181 * 182 * Return: struct mpcc* - MPCC that was added. 183 */ 184 struct mpcc *mpc1_insert_plane( 185 struct mpc *mpc, 186 struct mpc_tree *tree, 187 struct mpcc_blnd_cfg *blnd_cfg, 188 struct mpcc_sm_cfg *sm_cfg, 189 struct mpcc *insert_above_mpcc, 190 int dpp_id, 191 int mpcc_id) 192 { 193 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 194 struct mpcc *new_mpcc = NULL; 195 196 /* sanity check parameters */ 197 ASSERT(mpcc_id < mpc10->num_mpcc); 198 ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); 199 200 if (insert_above_mpcc) { 201 /* check insert_above_mpcc exist in tree->opp_list */ 202 struct mpcc *temp_mpcc = tree->opp_list; 203 204 while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) 205 temp_mpcc = temp_mpcc->mpcc_bot; 206 if (temp_mpcc == NULL) 207 return NULL; 208 } 209 210 /* Get and update MPCC struct parameters */ 211 new_mpcc = mpc1_get_mpcc(mpc, mpcc_id); 212 new_mpcc->dpp_id = dpp_id; 213 214 /* program mux and MPCC_MODE */ 215 if (insert_above_mpcc) { 216 new_mpcc->mpcc_bot = insert_above_mpcc; 217 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, insert_above_mpcc->mpcc_id); 218 REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); 219 } else { 220 new_mpcc->mpcc_bot = NULL; 221 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); 222 REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_ONLY); 223 } 224 REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); 225 REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); 226 227 /* Configure VUPDATE lock set for this MPCC to map to the OPP */ 228 REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id); 229 230 /* update mpc tree mux setting */ 231 if (tree->opp_list == insert_above_mpcc) { 232 /* insert the toppest mpcc */ 233 tree->opp_list = new_mpcc; 234 REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, mpcc_id); 235 } else { 236 /* find insert position */ 237 struct mpcc *temp_mpcc = tree->opp_list; 238 239 while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) 240 temp_mpcc = temp_mpcc->mpcc_bot; 241 if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) { 242 REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); 243 temp_mpcc->mpcc_bot = new_mpcc; 244 if (!insert_above_mpcc) 245 REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], 246 MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); 247 } 248 } 249 250 /* update the blending configuration */ 251 mpc->funcs->update_blending(mpc, blnd_cfg, mpcc_id); 252 253 /* update the stereo mix settings, if provided */ 254 if (sm_cfg != NULL) { 255 new_mpcc->sm_cfg = *sm_cfg; 256 mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id); 257 } 258 259 /* mark this mpcc as in use */ 260 mpc10->mpcc_in_use_mask |= 1 << mpcc_id; 261 262 return new_mpcc; 263 } 264 265 /* 266 * Remove a specified MPCC from the MPC tree. 267 * 268 * Parameters: 269 * [in/out] mpc - MPC context. 270 * [in/out] tree - MPC tree structure that plane will be removed from. 271 * [in/out] mpcc - MPCC to be removed from tree. 272 * 273 * Return: void 274 */ 275 void mpc1_remove_mpcc( 276 struct mpc *mpc, 277 struct mpc_tree *tree, 278 struct mpcc *mpcc_to_remove) 279 { 280 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 281 bool found = false; 282 int mpcc_id = mpcc_to_remove->mpcc_id; 283 284 if (tree->opp_list == mpcc_to_remove) { 285 found = true; 286 /* remove MPCC from top of tree */ 287 if (mpcc_to_remove->mpcc_bot) { 288 /* set the next MPCC in list to be the top MPCC */ 289 tree->opp_list = mpcc_to_remove->mpcc_bot; 290 REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id); 291 } else { 292 /* there are no other MPCC is list */ 293 tree->opp_list = NULL; 294 REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf); 295 } 296 } else { 297 /* find mpcc to remove MPCC list */ 298 struct mpcc *temp_mpcc = tree->opp_list; 299 300 while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove) 301 temp_mpcc = temp_mpcc->mpcc_bot; 302 303 if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) { 304 found = true; 305 temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot; 306 if (mpcc_to_remove->mpcc_bot) { 307 /* remove MPCC in middle of list */ 308 REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, 309 MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id); 310 } else { 311 /* remove MPCC from bottom of list */ 312 REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, 313 MPCC_BOT_SEL, 0xf); 314 REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], 315 MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); 316 } 317 } 318 } 319 320 if (found) { 321 /* turn off MPCC mux registers */ 322 REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); 323 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); 324 REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); 325 REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); 326 327 /* mark this mpcc as not in use */ 328 mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); 329 mpcc_to_remove->dpp_id = 0xf; 330 mpcc_to_remove->mpcc_bot = NULL; 331 } else { 332 /* In case of resume from S3/S4, remove mpcc from bios left over */ 333 REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); 334 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); 335 REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); 336 REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); 337 } 338 } 339 340 static void mpc1_init_mpcc(struct mpcc *mpcc, int mpcc_inst) 341 { 342 mpcc->mpcc_id = mpcc_inst; 343 mpcc->dpp_id = 0xf; 344 mpcc->mpcc_bot = NULL; 345 mpcc->blnd_cfg.overlap_only = false; 346 mpcc->blnd_cfg.global_alpha = 0xff; 347 mpcc->blnd_cfg.global_gain = 0xff; 348 mpcc->sm_cfg.enable = false; 349 } 350 351 /* 352 * Reset the MPCC HW status by disconnecting all muxes. 353 * 354 * Parameters: 355 * [in/out] mpc - MPC context. 356 * 357 * Return: void 358 */ 359 void mpc1_mpc_init(struct mpc *mpc) 360 { 361 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 362 int mpcc_id; 363 int opp_id; 364 365 mpc10->mpcc_in_use_mask = 0; 366 for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { 367 REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); 368 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); 369 REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); 370 REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); 371 372 mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); 373 } 374 375 for (opp_id = 0; opp_id < MAX_OPP; opp_id++) { 376 if (REG(MUX[opp_id])) 377 REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); 378 } 379 } 380 381 void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id) 382 { 383 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 384 int opp_id; 385 386 REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); 387 388 REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); 389 REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); 390 REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); 391 REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); 392 393 mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); 394 395 if (opp_id < MAX_OPP && REG(MUX[opp_id])) 396 REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); 397 } 398 399 400 void mpc1_init_mpcc_list_from_hw( 401 struct mpc *mpc, 402 struct mpc_tree *tree) 403 { 404 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 405 unsigned int opp_id; 406 unsigned int top_sel; 407 unsigned int bot_sel; 408 unsigned int out_mux; 409 struct mpcc *mpcc; 410 int mpcc_id; 411 int bot_mpcc_id; 412 413 REG_GET(MUX[tree->opp_id], MPC_OUT_MUX, &out_mux); 414 415 if (out_mux != 0xf) { 416 for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { 417 REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); 418 REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); 419 REG_GET(MPCC_BOT_SEL[mpcc_id], MPCC_BOT_SEL, &bot_sel); 420 421 if (bot_sel == mpcc_id) 422 bot_sel = 0xf; 423 424 if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { 425 mpcc = mpc1_get_mpcc(mpc, mpcc_id); 426 mpcc->dpp_id = top_sel; 427 mpc10->mpcc_in_use_mask |= 1 << mpcc_id; 428 429 if (out_mux == mpcc_id) 430 tree->opp_list = mpcc; 431 if (bot_sel != 0xf && bot_sel < mpc10->num_mpcc) { 432 bot_mpcc_id = bot_sel; 433 REG_GET(MPCC_OPP_ID[bot_mpcc_id], MPCC_OPP_ID, &opp_id); 434 REG_GET(MPCC_TOP_SEL[bot_mpcc_id], MPCC_TOP_SEL, &top_sel); 435 if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { 436 struct mpcc *mpcc_bottom = mpc1_get_mpcc(mpc, bot_mpcc_id); 437 438 mpcc->mpcc_bot = mpcc_bottom; 439 } 440 } 441 } 442 } 443 } 444 } 445 446 void mpc1_read_mpcc_state( 447 struct mpc *mpc, 448 int mpcc_inst, 449 struct mpcc_state *s) 450 { 451 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 452 453 REG_GET(MPCC_OPP_ID[mpcc_inst], MPCC_OPP_ID, &s->opp_id); 454 REG_GET(MPCC_TOP_SEL[mpcc_inst], MPCC_TOP_SEL, &s->dpp_id); 455 REG_GET(MPCC_BOT_SEL[mpcc_inst], MPCC_BOT_SEL, &s->bot_mpcc_id); 456 REG_GET_4(MPCC_CONTROL[mpcc_inst], MPCC_MODE, &s->mode, 457 MPCC_ALPHA_BLND_MODE, &s->alpha_mode, 458 MPCC_ALPHA_MULTIPLIED_MODE, &s->pre_multiplied_alpha, 459 MPCC_BLND_ACTIVE_OVERLAP_ONLY, &s->overlap_only); 460 REG_GET_2(MPCC_STATUS[mpcc_inst], MPCC_IDLE, &s->idle, 461 MPCC_BUSY, &s->busy); 462 } 463 464 void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock) 465 { 466 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 467 468 REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0); 469 } 470 471 unsigned int mpc1_get_mpc_out_mux(struct mpc *mpc, int opp_id) 472 { 473 struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); 474 uint32_t val = 0xf; 475 476 if (opp_id < MAX_OPP && REG(MUX[opp_id])) 477 REG_GET(MUX[opp_id], MPC_OUT_MUX, &val); 478 479 return val; 480 } 481 482 static const struct mpc_funcs dcn10_mpc_funcs = { 483 .read_mpcc_state = mpc1_read_mpcc_state, 484 .insert_plane = mpc1_insert_plane, 485 .remove_mpcc = mpc1_remove_mpcc, 486 .mpc_init = mpc1_mpc_init, 487 .mpc_init_single_inst = mpc1_mpc_init_single_inst, 488 .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, 489 .wait_for_idle = mpc1_assert_idle_mpcc, 490 .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, 491 .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, 492 .update_blending = mpc1_update_blending, 493 .cursor_lock = mpc1_cursor_lock, 494 .set_denorm = NULL, 495 .set_denorm_clamp = NULL, 496 .set_output_csc = NULL, 497 .set_output_gamma = NULL, 498 .get_mpc_out_mux = mpc1_get_mpc_out_mux, 499 .set_bg_color = mpc1_set_bg_color, 500 }; 501 502 void dcn10_mpc_construct(struct dcn10_mpc *mpc10, 503 struct dc_context *ctx, 504 const struct dcn_mpc_registers *mpc_regs, 505 const struct dcn_mpc_shift *mpc_shift, 506 const struct dcn_mpc_mask *mpc_mask, 507 int num_mpcc) 508 { 509 int i; 510 511 mpc10->base.ctx = ctx; 512 513 mpc10->base.funcs = &dcn10_mpc_funcs; 514 515 mpc10->mpc_regs = mpc_regs; 516 mpc10->mpc_shift = mpc_shift; 517 mpc10->mpc_mask = mpc_mask; 518 519 mpc10->mpcc_in_use_mask = 0; 520 mpc10->num_mpcc = num_mpcc; 521 522 for (i = 0; i < MAX_MPCC; i++) 523 mpc1_init_mpcc(&mpc10->base.mpcc_array[i], i); 524 } 525 526