| .. | .. |
|---|
| 42 | 42 | int mpcc_id) |
|---|
| 43 | 43 | { |
|---|
| 44 | 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 | + } |
|---|
| 45 | 52 | |
|---|
| 46 | 53 | /* mpc color is 12 bit. tg_color is 10 bit */ |
|---|
| 47 | 54 | /* todo: might want to use 16 bit to represent color and have each |
|---|
| 48 | 55 | * hw block translate to correct color depth. |
|---|
| 49 | 56 | */ |
|---|
| 50 | | - uint32_t bg_r_cr = bg_color->color_r_cr << 2; |
|---|
| 51 | | - uint32_t bg_g_y = bg_color->color_g_y << 2; |
|---|
| 52 | | - uint32_t bg_b_cb = bg_color->color_b_cb << 2; |
|---|
| 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; |
|---|
| 53 | 60 | |
|---|
| 54 | | - REG_SET(MPCC_BG_R_CR[mpcc_id], 0, |
|---|
| 61 | + REG_SET(MPCC_BG_R_CR[bottommost_mpcc->mpcc_id], 0, |
|---|
| 55 | 62 | MPCC_BG_R_CR, bg_r_cr); |
|---|
| 56 | | - REG_SET(MPCC_BG_G_Y[mpcc_id], 0, |
|---|
| 63 | + REG_SET(MPCC_BG_G_Y[bottommost_mpcc->mpcc_id], 0, |
|---|
| 57 | 64 | MPCC_BG_G_Y, bg_g_y); |
|---|
| 58 | | - REG_SET(MPCC_BG_B_CB[mpcc_id], 0, |
|---|
| 65 | + REG_SET(MPCC_BG_B_CB[bottommost_mpcc->mpcc_id], 0, |
|---|
| 59 | 66 | MPCC_BG_B_CB, bg_b_cb); |
|---|
| 60 | 67 | } |
|---|
| 61 | 68 | |
|---|
| .. | .. |
|---|
| 118 | 125 | while (tmp_mpcc != NULL) { |
|---|
| 119 | 126 | if (tmp_mpcc->dpp_id == dpp_id) |
|---|
| 120 | 127 | return tmp_mpcc; |
|---|
| 128 | + |
|---|
| 129 | + /* avoid circular linked list */ |
|---|
| 130 | + ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot); |
|---|
| 131 | + if (tmp_mpcc == tmp_mpcc->mpcc_bot) |
|---|
| 132 | + break; |
|---|
| 133 | + |
|---|
| 121 | 134 | tmp_mpcc = tmp_mpcc->mpcc_bot; |
|---|
| 122 | 135 | } |
|---|
| 123 | 136 | return NULL; |
|---|
| .. | .. |
|---|
| 193 | 206 | /* check insert_above_mpcc exist in tree->opp_list */ |
|---|
| 194 | 207 | struct mpcc *temp_mpcc = tree->opp_list; |
|---|
| 195 | 208 | |
|---|
| 196 | | - while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) |
|---|
| 197 | | - temp_mpcc = temp_mpcc->mpcc_bot; |
|---|
| 209 | + if (temp_mpcc != insert_above_mpcc) |
|---|
| 210 | + while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) |
|---|
| 211 | + temp_mpcc = temp_mpcc->mpcc_bot; |
|---|
| 198 | 212 | if (temp_mpcc == NULL) |
|---|
| 199 | 213 | return NULL; |
|---|
| 200 | 214 | } |
|---|
| .. | .. |
|---|
| 211 | 225 | } else { |
|---|
| 212 | 226 | new_mpcc->mpcc_bot = NULL; |
|---|
| 213 | 227 | REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); |
|---|
| 214 | | - REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); |
|---|
| 228 | + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_ONLY); |
|---|
| 215 | 229 | } |
|---|
| 216 | 230 | REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); |
|---|
| 217 | 231 | REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); |
|---|
| 232 | + |
|---|
| 233 | + /* Configure VUPDATE lock set for this MPCC to map to the OPP */ |
|---|
| 234 | + REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, tree->opp_id); |
|---|
| 218 | 235 | |
|---|
| 219 | 236 | /* update mpc tree mux setting */ |
|---|
| 220 | 237 | if (tree->opp_list == insert_above_mpcc) { |
|---|
| .. | .. |
|---|
| 311 | 328 | REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); |
|---|
| 312 | 329 | REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); |
|---|
| 313 | 330 | REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); |
|---|
| 331 | + REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); |
|---|
| 314 | 332 | |
|---|
| 315 | 333 | /* mark this mpcc as not in use */ |
|---|
| 316 | 334 | mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); |
|---|
| .. | .. |
|---|
| 321 | 339 | REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); |
|---|
| 322 | 340 | REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); |
|---|
| 323 | 341 | REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); |
|---|
| 342 | + REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); |
|---|
| 324 | 343 | } |
|---|
| 325 | 344 | } |
|---|
| 326 | 345 | |
|---|
| .. | .. |
|---|
| 354 | 373 | REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); |
|---|
| 355 | 374 | REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); |
|---|
| 356 | 375 | REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); |
|---|
| 376 | + REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); |
|---|
| 357 | 377 | |
|---|
| 358 | 378 | mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); |
|---|
| 359 | 379 | } |
|---|
| .. | .. |
|---|
| 363 | 383 | REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); |
|---|
| 364 | 384 | } |
|---|
| 365 | 385 | } |
|---|
| 386 | + |
|---|
| 387 | +void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id) |
|---|
| 388 | +{ |
|---|
| 389 | + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); |
|---|
| 390 | + int opp_id; |
|---|
| 391 | + |
|---|
| 392 | + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); |
|---|
| 393 | + |
|---|
| 394 | + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); |
|---|
| 395 | + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); |
|---|
| 396 | + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); |
|---|
| 397 | + REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf); |
|---|
| 398 | + |
|---|
| 399 | + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); |
|---|
| 400 | + |
|---|
| 401 | + if (opp_id < MAX_OPP && REG(MUX[opp_id])) |
|---|
| 402 | + REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); |
|---|
| 403 | +} |
|---|
| 404 | + |
|---|
| 366 | 405 | |
|---|
| 367 | 406 | void mpc1_init_mpcc_list_from_hw( |
|---|
| 368 | 407 | struct mpc *mpc, |
|---|
| .. | .. |
|---|
| 428 | 467 | MPCC_BUSY, &s->busy); |
|---|
| 429 | 468 | } |
|---|
| 430 | 469 | |
|---|
| 470 | +void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock) |
|---|
| 471 | +{ |
|---|
| 472 | + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); |
|---|
| 473 | + |
|---|
| 474 | + REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0); |
|---|
| 475 | +} |
|---|
| 476 | + |
|---|
| 431 | 477 | static const struct mpc_funcs dcn10_mpc_funcs = { |
|---|
| 432 | 478 | .read_mpcc_state = mpc1_read_mpcc_state, |
|---|
| 433 | 479 | .insert_plane = mpc1_insert_plane, |
|---|
| 434 | 480 | .remove_mpcc = mpc1_remove_mpcc, |
|---|
| 435 | 481 | .mpc_init = mpc1_mpc_init, |
|---|
| 482 | + .mpc_init_single_inst = mpc1_mpc_init_single_inst, |
|---|
| 436 | 483 | .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, |
|---|
| 437 | 484 | .wait_for_idle = mpc1_assert_idle_mpcc, |
|---|
| 438 | 485 | .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, |
|---|
| 439 | 486 | .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, |
|---|
| 440 | 487 | .update_blending = mpc1_update_blending, |
|---|
| 488 | + .cursor_lock = mpc1_cursor_lock, |
|---|
| 489 | + .set_denorm = NULL, |
|---|
| 490 | + .set_denorm_clamp = NULL, |
|---|
| 491 | + .set_output_csc = NULL, |
|---|
| 492 | + .set_output_gamma = NULL, |
|---|
| 441 | 493 | }; |
|---|
| 442 | 494 | |
|---|
| 443 | 495 | void dcn10_mpc_construct(struct dcn10_mpc *mpc10, |
|---|