2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "dcn20_mpc.h"
28 #include "reg_helper.h"
30 #include "mem_input.h"
31 #include "dcn10/dcn10_cm_common.h"
36 #define IND_REG(index) \
43 #define FN(reg_name, field_name) \
44 mpc20->mpc_shift->field_name, mpc20->mpc_mask->field_name
46 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
48 void mpc2_update_blending(
50 struct mpcc_blnd_cfg
*blnd_cfg
,
53 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
55 struct mpcc
*mpcc
= mpc1_get_mpcc(mpc
, mpcc_id
);
57 REG_UPDATE_7(MPCC_CONTROL
[mpcc_id
],
58 MPCC_ALPHA_BLND_MODE
, blnd_cfg
->alpha_mode
,
59 MPCC_ALPHA_MULTIPLIED_MODE
, blnd_cfg
->pre_multiplied_alpha
,
60 MPCC_BLND_ACTIVE_OVERLAP_ONLY
, blnd_cfg
->overlap_only
,
61 MPCC_GLOBAL_ALPHA
, blnd_cfg
->global_alpha
,
62 MPCC_GLOBAL_GAIN
, blnd_cfg
->global_gain
,
63 MPCC_BG_BPC
, blnd_cfg
->background_color_bpc
,
64 MPCC_BOT_GAIN_MODE
, blnd_cfg
->bottom_gain_mode
);
66 REG_SET(MPCC_TOP_GAIN
[mpcc_id
], 0, MPCC_TOP_GAIN
, blnd_cfg
->top_gain
);
67 REG_SET(MPCC_BOT_GAIN_INSIDE
[mpcc_id
], 0, MPCC_BOT_GAIN_INSIDE
, blnd_cfg
->bottom_inside_gain
);
68 REG_SET(MPCC_BOT_GAIN_OUTSIDE
[mpcc_id
], 0, MPCC_BOT_GAIN_OUTSIDE
, blnd_cfg
->bottom_outside_gain
);
70 mpc1_set_bg_color(mpc
, &blnd_cfg
->black_color
, mpcc_id
);
71 mpcc
->blnd_cfg
= *blnd_cfg
;
77 enum dc_color_depth output_depth
)
79 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
82 switch (output_depth
) {
92 case COLOR_DEPTH_101010
:
95 case COLOR_DEPTH_111111
:
98 case COLOR_DEPTH_121212
:
101 case COLOR_DEPTH_141414
:
102 case COLOR_DEPTH_161616
:
104 /* not valid used case! */
108 REG_UPDATE(DENORM_CONTROL
[opp_id
],
109 MPC_OUT_DENORM_MODE
, denorm_mode
);
112 void mpc2_set_denorm_clamp(
115 struct mpc_denorm_clamp denorm_clamp
)
117 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
119 REG_UPDATE_2(DENORM_CONTROL
[opp_id
],
120 MPC_OUT_DENORM_CLAMP_MAX_R_CR
, denorm_clamp
.clamp_max_r_cr
,
121 MPC_OUT_DENORM_CLAMP_MIN_R_CR
, denorm_clamp
.clamp_min_r_cr
);
122 REG_UPDATE_2(DENORM_CLAMP_G_Y
[opp_id
],
123 MPC_OUT_DENORM_CLAMP_MAX_G_Y
, denorm_clamp
.clamp_max_g_y
,
124 MPC_OUT_DENORM_CLAMP_MIN_G_Y
, denorm_clamp
.clamp_min_g_y
);
125 REG_UPDATE_2(DENORM_CLAMP_B_CB
[opp_id
],
126 MPC_OUT_DENORM_CLAMP_MAX_B_CB
, denorm_clamp
.clamp_max_b_cb
,
127 MPC_OUT_DENORM_CLAMP_MIN_B_CB
, denorm_clamp
.clamp_min_b_cb
);
132 void mpc2_set_output_csc(
135 const uint16_t *regval
,
136 enum mpc_output_csc_mode ocsc_mode
)
139 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
140 struct color_matrices_reg ocsc_regs
;
142 if (ocsc_mode
== MPC_OUTPUT_CSC_DISABLE
) {
143 REG_SET(CSC_MODE
[opp_id
], 0, MPC_OCSC_MODE
, ocsc_mode
);
147 if (regval
== NULL
) {
152 /* determine which CSC coefficients (A or B) we are using
153 * currently. select the alternate set to double buffer
154 * the CSC update so CSC is updated on frame boundary
156 IX_REG_GET(MPC_OCSC_TEST_DEBUG_INDEX
, MPC_OCSC_TEST_DEBUG_DATA
,
157 MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX
,
158 MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE
, &cur_mode
);
160 if (cur_mode
!= MPC_OUTPUT_CSC_COEF_A
)
161 ocsc_mode
= MPC_OUTPUT_CSC_COEF_A
;
163 ocsc_mode
= MPC_OUTPUT_CSC_COEF_B
;
165 ocsc_regs
.shifts
.csc_c11
= mpc20
->mpc_shift
->MPC_OCSC_C11_A
;
166 ocsc_regs
.masks
.csc_c11
= mpc20
->mpc_mask
->MPC_OCSC_C11_A
;
167 ocsc_regs
.shifts
.csc_c12
= mpc20
->mpc_shift
->MPC_OCSC_C12_A
;
168 ocsc_regs
.masks
.csc_c12
= mpc20
->mpc_mask
->MPC_OCSC_C12_A
;
170 if (ocsc_mode
== MPC_OUTPUT_CSC_COEF_A
) {
171 ocsc_regs
.csc_c11_c12
= REG(CSC_C11_C12_A
[opp_id
]);
172 ocsc_regs
.csc_c33_c34
= REG(CSC_C33_C34_A
[opp_id
]);
174 ocsc_regs
.csc_c11_c12
= REG(CSC_C11_C12_B
[opp_id
]);
175 ocsc_regs
.csc_c33_c34
= REG(CSC_C33_C34_B
[opp_id
]);
178 cm_helper_program_color_matrices(
183 REG_SET(CSC_MODE
[opp_id
], 0, MPC_OCSC_MODE
, ocsc_mode
);
186 void mpc2_set_ocsc_default(
189 enum dc_color_space color_space
,
190 enum mpc_output_csc_mode ocsc_mode
)
193 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
195 struct color_matrices_reg ocsc_regs
;
196 const uint16_t *regval
= NULL
;
198 if (ocsc_mode
== MPC_OUTPUT_CSC_DISABLE
) {
199 REG_SET(CSC_MODE
[opp_id
], 0, MPC_OCSC_MODE
, ocsc_mode
);
203 regval
= find_color_matrix(color_space
, &arr_size
);
205 if (regval
== NULL
) {
210 /* determine which CSC coefficients (A or B) we are using
211 * currently. select the alternate set to double buffer
212 * the CSC update so CSC is updated on frame boundary
214 IX_REG_GET(MPC_OCSC_TEST_DEBUG_INDEX
, MPC_OCSC_TEST_DEBUG_DATA
,
215 MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX
,
216 MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE
, &cur_mode
);
218 if (cur_mode
!= MPC_OUTPUT_CSC_COEF_A
)
219 ocsc_mode
= MPC_OUTPUT_CSC_COEF_A
;
221 ocsc_mode
= MPC_OUTPUT_CSC_COEF_B
;
223 ocsc_regs
.shifts
.csc_c11
= mpc20
->mpc_shift
->MPC_OCSC_C11_A
;
224 ocsc_regs
.masks
.csc_c11
= mpc20
->mpc_mask
->MPC_OCSC_C11_A
;
225 ocsc_regs
.shifts
.csc_c12
= mpc20
->mpc_shift
->MPC_OCSC_C12_A
;
226 ocsc_regs
.masks
.csc_c12
= mpc20
->mpc_mask
->MPC_OCSC_C12_A
;
229 if (ocsc_mode
== MPC_OUTPUT_CSC_COEF_A
) {
230 ocsc_regs
.csc_c11_c12
= REG(CSC_C11_C12_A
[opp_id
]);
231 ocsc_regs
.csc_c33_c34
= REG(CSC_C33_C34_A
[opp_id
]);
233 ocsc_regs
.csc_c11_c12
= REG(CSC_C11_C12_B
[opp_id
]);
234 ocsc_regs
.csc_c33_c34
= REG(CSC_C33_C34_B
[opp_id
]);
237 cm_helper_program_color_matrices(
242 REG_SET(CSC_MODE
[opp_id
], 0, MPC_OCSC_MODE
, ocsc_mode
);
245 static void mpc2_ogam_get_reg_field(
247 struct xfer_func_reg
*reg
)
249 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
251 reg
->shifts
.exp_region0_lut_offset
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET
;
252 reg
->masks
.exp_region0_lut_offset
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET
;
253 reg
->shifts
.exp_region0_num_segments
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS
;
254 reg
->masks
.exp_region0_num_segments
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS
;
255 reg
->shifts
.exp_region1_lut_offset
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET
;
256 reg
->masks
.exp_region1_lut_offset
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET
;
257 reg
->shifts
.exp_region1_num_segments
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS
;
258 reg
->masks
.exp_region1_num_segments
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS
;
259 reg
->shifts
.field_region_end
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_END_B
;
260 reg
->masks
.field_region_end
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_END_B
;
261 reg
->shifts
.field_region_end_slope
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B
;
262 reg
->masks
.field_region_end_slope
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B
;
263 reg
->shifts
.field_region_end_base
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B
;
264 reg
->masks
.field_region_end_base
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B
;
265 reg
->shifts
.field_region_linear_slope
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B
;
266 reg
->masks
.field_region_linear_slope
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B
;
267 reg
->shifts
.exp_region_start
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_START_B
;
268 reg
->masks
.exp_region_start
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_START_B
;
269 reg
->shifts
.exp_resion_start_segment
= mpc20
->mpc_shift
->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B
;
270 reg
->masks
.exp_resion_start_segment
= mpc20
->mpc_mask
->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B
;
273 void mpc20_power_on_ogam_lut(
274 struct mpc
*mpc
, int mpcc_id
,
277 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
279 REG_SET(MPCC_MEM_PWR_CTRL
[mpcc_id
], 0,
280 MPCC_OGAM_MEM_PWR_DIS
, power_on
== true ? 1:0);
284 static void mpc20_configure_ogam_lut(
285 struct mpc
*mpc
, int mpcc_id
,
288 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
290 REG_UPDATE_2(MPCC_OGAM_LUT_RAM_CONTROL
[mpcc_id
],
291 MPCC_OGAM_LUT_WRITE_EN_MASK
, 7,
292 MPCC_OGAM_LUT_RAM_SEL
, is_ram_a
== true ? 0:1);
294 REG_SET(MPCC_OGAM_LUT_INDEX
[mpcc_id
], 0, MPCC_OGAM_LUT_INDEX
, 0);
297 static enum dc_lut_mode
mpc20_get_ogam_current(struct mpc
*mpc
, int mpcc_id
)
299 enum dc_lut_mode mode
;
301 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
303 REG_GET(MPCC_OGAM_LUT_RAM_CONTROL
[mpcc_id
],
304 MPCC_OGAM_CONFIG_STATUS
, &state_mode
);
306 switch (state_mode
) {
323 static void mpc2_program_lutb(struct mpc
*mpc
, int mpcc_id
,
324 const struct pwl_params
*params
)
326 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
327 struct xfer_func_reg gam_regs
;
329 mpc2_ogam_get_reg_field(mpc
, &gam_regs
);
331 gam_regs
.start_cntl_b
= REG(MPCC_OGAM_RAMB_START_CNTL_B
[mpcc_id
]);
332 gam_regs
.start_cntl_g
= REG(MPCC_OGAM_RAMB_START_CNTL_G
[mpcc_id
]);
333 gam_regs
.start_cntl_r
= REG(MPCC_OGAM_RAMB_START_CNTL_R
[mpcc_id
]);
334 gam_regs
.start_slope_cntl_b
= REG(MPCC_OGAM_RAMB_SLOPE_CNTL_B
[mpcc_id
]);
335 gam_regs
.start_slope_cntl_g
= REG(MPCC_OGAM_RAMB_SLOPE_CNTL_G
[mpcc_id
]);
336 gam_regs
.start_slope_cntl_r
= REG(MPCC_OGAM_RAMB_SLOPE_CNTL_R
[mpcc_id
]);
337 gam_regs
.start_end_cntl1_b
= REG(MPCC_OGAM_RAMB_END_CNTL1_B
[mpcc_id
]);
338 gam_regs
.start_end_cntl2_b
= REG(MPCC_OGAM_RAMB_END_CNTL2_B
[mpcc_id
]);
339 gam_regs
.start_end_cntl1_g
= REG(MPCC_OGAM_RAMB_END_CNTL1_G
[mpcc_id
]);
340 gam_regs
.start_end_cntl2_g
= REG(MPCC_OGAM_RAMB_END_CNTL2_G
[mpcc_id
]);
341 gam_regs
.start_end_cntl1_r
= REG(MPCC_OGAM_RAMB_END_CNTL1_R
[mpcc_id
]);
342 gam_regs
.start_end_cntl2_r
= REG(MPCC_OGAM_RAMB_END_CNTL2_R
[mpcc_id
]);
343 gam_regs
.region_start
= REG(MPCC_OGAM_RAMB_REGION_0_1
[mpcc_id
]);
344 gam_regs
.region_end
= REG(MPCC_OGAM_RAMB_REGION_32_33
[mpcc_id
]);
346 cm_helper_program_xfer_func(mpc20
->base
.ctx
, params
, &gam_regs
);
350 static void mpc2_program_luta(struct mpc
*mpc
, int mpcc_id
,
351 const struct pwl_params
*params
)
353 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
354 struct xfer_func_reg gam_regs
;
356 mpc2_ogam_get_reg_field(mpc
, &gam_regs
);
358 gam_regs
.start_cntl_b
= REG(MPCC_OGAM_RAMA_START_CNTL_B
[mpcc_id
]);
359 gam_regs
.start_cntl_g
= REG(MPCC_OGAM_RAMA_START_CNTL_G
[mpcc_id
]);
360 gam_regs
.start_cntl_r
= REG(MPCC_OGAM_RAMA_START_CNTL_R
[mpcc_id
]);
361 gam_regs
.start_slope_cntl_b
= REG(MPCC_OGAM_RAMA_SLOPE_CNTL_B
[mpcc_id
]);
362 gam_regs
.start_slope_cntl_g
= REG(MPCC_OGAM_RAMA_SLOPE_CNTL_G
[mpcc_id
]);
363 gam_regs
.start_slope_cntl_r
= REG(MPCC_OGAM_RAMA_SLOPE_CNTL_R
[mpcc_id
]);
364 gam_regs
.start_end_cntl1_b
= REG(MPCC_OGAM_RAMA_END_CNTL1_B
[mpcc_id
]);
365 gam_regs
.start_end_cntl2_b
= REG(MPCC_OGAM_RAMA_END_CNTL2_B
[mpcc_id
]);
366 gam_regs
.start_end_cntl1_g
= REG(MPCC_OGAM_RAMA_END_CNTL1_G
[mpcc_id
]);
367 gam_regs
.start_end_cntl2_g
= REG(MPCC_OGAM_RAMA_END_CNTL2_G
[mpcc_id
]);
368 gam_regs
.start_end_cntl1_r
= REG(MPCC_OGAM_RAMA_END_CNTL1_R
[mpcc_id
]);
369 gam_regs
.start_end_cntl2_r
= REG(MPCC_OGAM_RAMA_END_CNTL2_R
[mpcc_id
]);
370 gam_regs
.region_start
= REG(MPCC_OGAM_RAMA_REGION_0_1
[mpcc_id
]);
371 gam_regs
.region_end
= REG(MPCC_OGAM_RAMA_REGION_32_33
[mpcc_id
]);
373 cm_helper_program_xfer_func(mpc20
->base
.ctx
, params
, &gam_regs
);
377 static void mpc20_program_ogam_pwl(
378 struct mpc
*mpc
, int mpcc_id
,
379 const struct pwl_result_data
*rgb
,
383 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
388 for (i
= 0 ; i
< num
; i
++) {
389 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0, MPCC_OGAM_LUT_DATA
, rgb
[i
].red_reg
);
390 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0, MPCC_OGAM_LUT_DATA
, rgb
[i
].green_reg
);
391 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0, MPCC_OGAM_LUT_DATA
, rgb
[i
].blue_reg
);
393 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0,
394 MPCC_OGAM_LUT_DATA
, rgb
[i
].delta_red_reg
);
395 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0,
396 MPCC_OGAM_LUT_DATA
, rgb
[i
].delta_green_reg
);
397 REG_SET(MPCC_OGAM_LUT_DATA
[mpcc_id
], 0,
398 MPCC_OGAM_LUT_DATA
, rgb
[i
].delta_blue_reg
);
404 void apply_DEDCN20_305_wa(
406 int mpcc_id
, enum dc_lut_mode current_mode
,
407 enum dc_lut_mode next_mode
)
409 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
411 if (mpc
->ctx
->dc
->debug
.cm_in_bypass
) {
412 REG_SET(MPCC_OGAM_MODE
[mpcc_id
], 0, MPCC_OGAM_MODE
, 0);
416 if (mpc
->ctx
->dc
->work_arounds
.dedcn20_305_wa
== false) {
417 /*hw fixed in new review*/
420 if (current_mode
== LUT_BYPASS
)
421 /*this will only work if OTG is locked.
422 *if we were to support OTG unlock case,
423 *the workaround will be more complex
425 REG_SET(MPCC_OGAM_MODE
[mpcc_id
], 0, MPCC_OGAM_MODE
,
426 next_mode
== LUT_RAM_A
? 1:2);
429 void mpc2_set_output_gamma(
432 const struct pwl_params
*params
)
434 enum dc_lut_mode current_mode
;
435 enum dc_lut_mode next_mode
;
436 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
438 if (mpc
->ctx
->dc
->debug
.cm_in_bypass
) {
439 REG_SET(MPCC_OGAM_MODE
[mpcc_id
], 0, MPCC_OGAM_MODE
, 0);
443 if (params
== NULL
) {
444 REG_SET(MPCC_OGAM_MODE
[mpcc_id
], 0, MPCC_OGAM_MODE
, 0);
448 current_mode
= mpc20_get_ogam_current(mpc
, mpcc_id
);
449 if (current_mode
== LUT_BYPASS
|| current_mode
== LUT_RAM_A
)
450 next_mode
= LUT_RAM_B
;
452 next_mode
= LUT_RAM_A
;
454 mpc20_power_on_ogam_lut(mpc
, mpcc_id
, true);
455 mpc20_configure_ogam_lut(mpc
, mpcc_id
, next_mode
== LUT_RAM_A
? true:false);
457 if (next_mode
== LUT_RAM_A
)
458 mpc2_program_luta(mpc
, mpcc_id
, params
);
460 mpc2_program_lutb(mpc
, mpcc_id
, params
);
462 apply_DEDCN20_305_wa(mpc
, mpcc_id
, current_mode
, next_mode
);
464 mpc20_program_ogam_pwl(
465 mpc
, mpcc_id
, params
->rgb_resulted
, params
->hw_points_num
);
467 REG_SET(MPCC_OGAM_MODE
[mpcc_id
], 0, MPCC_OGAM_MODE
,
468 next_mode
== LUT_RAM_A
? 1:2);
470 void mpc2_assert_idle_mpcc(struct mpc
*mpc
, int id
)
472 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
473 unsigned int mpc_disabled
;
475 ASSERT(!(mpc20
->mpcc_in_use_mask
& 1 << id
));
476 REG_GET(MPCC_STATUS
[id
], MPCC_DISABLED
, &mpc_disabled
);
480 REG_WAIT(MPCC_STATUS
[id
],
485 void mpc2_assert_mpcc_idle_before_connect(struct mpc
*mpc
, int mpcc_id
)
487 struct dcn20_mpc
*mpc20
= TO_DCN20_MPC(mpc
);
488 unsigned int top_sel
, mpc_busy
, mpc_idle
, mpc_disabled
;
490 REG_GET(MPCC_TOP_SEL
[mpcc_id
],
491 MPCC_TOP_SEL
, &top_sel
);
493 REG_GET_3(MPCC_STATUS
[mpcc_id
],
494 MPCC_BUSY
, &mpc_busy
,
495 MPCC_IDLE
, &mpc_idle
,
496 MPCC_DISABLED
, &mpc_disabled
);
498 if (top_sel
== 0xf) {
501 ASSERT(mpc_disabled
);
503 ASSERT(!mpc_disabled
);
513 static void mpc2_init_mpcc(struct mpcc
*mpcc
, int mpcc_inst
)
515 mpcc
->mpcc_id
= mpcc_inst
;
517 mpcc
->mpcc_bot
= NULL
;
518 mpcc
->blnd_cfg
.overlap_only
= false;
519 mpcc
->blnd_cfg
.global_alpha
= 0xff;
520 mpcc
->blnd_cfg
.global_gain
= 0xff;
521 mpcc
->blnd_cfg
.background_color_bpc
= 4;
522 mpcc
->blnd_cfg
.bottom_gain_mode
= 0;
523 mpcc
->blnd_cfg
.top_gain
= 0x1f000;
524 mpcc
->blnd_cfg
.bottom_inside_gain
= 0x1f000;
525 mpcc
->blnd_cfg
.bottom_outside_gain
= 0x1f000;
526 mpcc
->sm_cfg
.enable
= false;
529 struct mpcc
*mpc2_get_mpcc_for_dpp(struct mpc_tree
*tree
, int dpp_id
)
531 struct mpcc
*tmp_mpcc
= tree
->opp_list
;
533 while (tmp_mpcc
!= NULL
) {
534 if (tmp_mpcc
->dpp_id
== 0xf || tmp_mpcc
->dpp_id
== dpp_id
)
536 tmp_mpcc
= tmp_mpcc
->mpcc_bot
;
541 const struct mpc_funcs dcn20_mpc_funcs
= {
542 .read_mpcc_state
= mpc1_read_mpcc_state
,
543 .insert_plane
= mpc1_insert_plane
,
544 .remove_mpcc
= mpc1_remove_mpcc
,
545 .mpc_init
= mpc1_mpc_init
,
546 .mpc_init_single_inst
= mpc1_mpc_init_single_inst
,
547 .update_blending
= mpc2_update_blending
,
548 .get_mpcc_for_dpp
= mpc2_get_mpcc_for_dpp
,
549 .wait_for_idle
= mpc2_assert_idle_mpcc
,
550 .assert_mpcc_idle_before_connect
= mpc2_assert_mpcc_idle_before_connect
,
551 .init_mpcc_list_from_hw
= mpc1_init_mpcc_list_from_hw
,
552 .set_denorm
= mpc2_set_denorm
,
553 .set_denorm_clamp
= mpc2_set_denorm_clamp
,
554 .set_output_csc
= mpc2_set_output_csc
,
555 .set_ocsc_default
= mpc2_set_ocsc_default
,
556 .set_output_gamma
= mpc2_set_output_gamma
,
557 .power_on_mpc_mem_pwr
= mpc20_power_on_ogam_lut
,
560 void dcn20_mpc_construct(struct dcn20_mpc
*mpc20
,
561 struct dc_context
*ctx
,
562 const struct dcn20_mpc_registers
*mpc_regs
,
563 const struct dcn20_mpc_shift
*mpc_shift
,
564 const struct dcn20_mpc_mask
*mpc_mask
,
569 mpc20
->base
.ctx
= ctx
;
571 mpc20
->base
.funcs
= &dcn20_mpc_funcs
;
573 mpc20
->mpc_regs
= mpc_regs
;
574 mpc20
->mpc_shift
= mpc_shift
;
575 mpc20
->mpc_mask
= mpc_mask
;
577 mpc20
->mpcc_in_use_mask
= 0;
578 mpc20
->num_mpcc
= num_mpcc
;
580 for (i
= 0; i
< MAX_MPCC
; i
++)
581 mpc2_init_mpcc(&mpc20
->base
.mpcc_array
[i
], i
);