LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn20 - dcn20_mpc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 236 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 18 0.0 %

          Line data    Source code
       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 "dcn20_mpc.h"
      27             : 
      28             : #include "reg_helper.h"
      29             : #include "dc.h"
      30             : #include "mem_input.h"
      31             : #include "dcn10/dcn10_cm_common.h"
      32             : 
      33             : #define REG(reg)\
      34             :         mpc20->mpc_regs->reg
      35             : 
      36             : #define IND_REG(index) \
      37             :         (index)
      38             : 
      39             : #define CTX \
      40             :         mpc20->base.ctx
      41             : 
      42             : #undef FN
      43             : #define FN(reg_name, field_name) \
      44             :         mpc20->mpc_shift->field_name, mpc20->mpc_mask->field_name
      45             : 
      46             : #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
      47             : 
      48           0 : void mpc2_update_blending(
      49             :         struct mpc *mpc,
      50             :         struct mpcc_blnd_cfg *blnd_cfg,
      51             :         int mpcc_id)
      52             : {
      53           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
      54             : 
      55           0 :         struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id);
      56             : 
      57           0 :         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);
      65             : 
      66           0 :         REG_SET(MPCC_TOP_GAIN[mpcc_id], 0, MPCC_TOP_GAIN, blnd_cfg->top_gain);
      67           0 :         REG_SET(MPCC_BOT_GAIN_INSIDE[mpcc_id], 0, MPCC_BOT_GAIN_INSIDE, blnd_cfg->bottom_inside_gain);
      68           0 :         REG_SET(MPCC_BOT_GAIN_OUTSIDE[mpcc_id], 0, MPCC_BOT_GAIN_OUTSIDE, blnd_cfg->bottom_outside_gain);
      69             : 
      70           0 :         mpcc->blnd_cfg = *blnd_cfg;
      71           0 : }
      72             : 
      73           0 : void mpc2_set_denorm(
      74             :                 struct mpc *mpc,
      75             :                 int opp_id,
      76             :                 enum dc_color_depth output_depth)
      77             : {
      78           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
      79           0 :         int denorm_mode = 0;
      80             : 
      81             :         switch (output_depth) {
      82             :         case COLOR_DEPTH_666:
      83             :                 denorm_mode = 1;
      84             :                 break;
      85             :         case COLOR_DEPTH_888:
      86             :                 denorm_mode = 2;
      87             :                 break;
      88             :         case COLOR_DEPTH_999:
      89             :                 denorm_mode = 3;
      90             :                 break;
      91             :         case COLOR_DEPTH_101010:
      92             :                 denorm_mode = 4;
      93             :                 break;
      94             :         case COLOR_DEPTH_111111:
      95             :                 denorm_mode = 5;
      96             :                 break;
      97             :         case COLOR_DEPTH_121212:
      98             :                 denorm_mode = 6;
      99             :                 break;
     100             :         case COLOR_DEPTH_141414:
     101             :         case COLOR_DEPTH_161616:
     102             :         default:
     103             :                 /* not valid used case! */
     104             :                 break;
     105             :         }
     106             : 
     107           0 :         REG_UPDATE(DENORM_CONTROL[opp_id],
     108             :                         MPC_OUT_DENORM_MODE, denorm_mode);
     109           0 : }
     110             : 
     111           0 : void mpc2_set_denorm_clamp(
     112             :                 struct mpc *mpc,
     113             :                 int opp_id,
     114             :                 struct mpc_denorm_clamp denorm_clamp)
     115             : {
     116           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     117             : 
     118           0 :         REG_UPDATE_2(DENORM_CONTROL[opp_id],
     119             :                         MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr,
     120             :                         MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr);
     121           0 :         REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id],
     122             :                         MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y,
     123             :                         MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y);
     124           0 :         REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id],
     125             :                         MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb,
     126             :                         MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb);
     127           0 : }
     128             : 
     129             : 
     130             : 
     131           0 : void mpc2_set_output_csc(
     132             :                 struct mpc *mpc,
     133             :                 int opp_id,
     134             :                 const uint16_t *regval,
     135             :                 enum mpc_output_csc_mode ocsc_mode)
     136             : {
     137             :         uint32_t cur_mode;
     138           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     139             :         struct color_matrices_reg ocsc_regs;
     140             : 
     141           0 :         if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) {
     142           0 :                 REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
     143           0 :                 return;
     144             :         }
     145             : 
     146           0 :         if (regval == NULL) {
     147           0 :                 BREAK_TO_DEBUGGER();
     148           0 :                 return;
     149             :         }
     150             : 
     151             :         /* determine which CSC coefficients (A or B) we are using
     152             :          * currently.  select the alternate set to double buffer
     153             :          * the CSC update so CSC is updated on frame boundary
     154             :          */
     155           0 :         IX_REG_GET(MPC_OCSC_TEST_DEBUG_INDEX, MPC_OCSC_TEST_DEBUG_DATA,
     156             :                                                 MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX,
     157             :                                                 MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE, &cur_mode);
     158             : 
     159           0 :         if (cur_mode != MPC_OUTPUT_CSC_COEF_A)
     160             :                 ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
     161             :         else
     162           0 :                 ocsc_mode = MPC_OUTPUT_CSC_COEF_B;
     163             : 
     164           0 :         ocsc_regs.shifts.csc_c11 = mpc20->mpc_shift->MPC_OCSC_C11_A;
     165           0 :         ocsc_regs.masks.csc_c11  = mpc20->mpc_mask->MPC_OCSC_C11_A;
     166           0 :         ocsc_regs.shifts.csc_c12 = mpc20->mpc_shift->MPC_OCSC_C12_A;
     167           0 :         ocsc_regs.masks.csc_c12 = mpc20->mpc_mask->MPC_OCSC_C12_A;
     168             : 
     169           0 :         if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
     170           0 :                 ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
     171           0 :                 ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
     172             :         } else {
     173           0 :                 ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
     174           0 :                 ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
     175             :         }
     176             : 
     177           0 :         cm_helper_program_color_matrices(
     178             :                         mpc20->base.ctx,
     179             :                         regval,
     180             :                         &ocsc_regs);
     181             : 
     182           0 :         REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
     183             : }
     184             : 
     185           0 : void mpc2_set_ocsc_default(
     186             :                 struct mpc *mpc,
     187             :                 int opp_id,
     188             :                 enum dc_color_space color_space,
     189             :                 enum mpc_output_csc_mode ocsc_mode)
     190             : {
     191             :         uint32_t cur_mode;
     192           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     193             :         uint32_t arr_size;
     194             :         struct color_matrices_reg ocsc_regs;
     195           0 :         const uint16_t *regval = NULL;
     196             : 
     197           0 :         if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) {
     198           0 :                 REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
     199           0 :                 return;
     200             :         }
     201             : 
     202           0 :         regval = find_color_matrix(color_space, &arr_size);
     203             : 
     204           0 :         if (regval == NULL) {
     205           0 :                 BREAK_TO_DEBUGGER();
     206           0 :                 return;
     207             :         }
     208             : 
     209             :         /* determine which CSC coefficients (A or B) we are using
     210             :          * currently.  select the alternate set to double buffer
     211             :          * the CSC update so CSC is updated on frame boundary
     212             :          */
     213           0 :         IX_REG_GET(MPC_OCSC_TEST_DEBUG_INDEX, MPC_OCSC_TEST_DEBUG_DATA,
     214             :                                                 MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX,
     215             :                                                 MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE, &cur_mode);
     216             : 
     217           0 :         if (cur_mode != MPC_OUTPUT_CSC_COEF_A)
     218             :                 ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
     219             :         else
     220           0 :                 ocsc_mode = MPC_OUTPUT_CSC_COEF_B;
     221             : 
     222           0 :         ocsc_regs.shifts.csc_c11 = mpc20->mpc_shift->MPC_OCSC_C11_A;
     223           0 :         ocsc_regs.masks.csc_c11  = mpc20->mpc_mask->MPC_OCSC_C11_A;
     224           0 :         ocsc_regs.shifts.csc_c12 = mpc20->mpc_shift->MPC_OCSC_C12_A;
     225           0 :         ocsc_regs.masks.csc_c12 = mpc20->mpc_mask->MPC_OCSC_C12_A;
     226             : 
     227             : 
     228           0 :         if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
     229           0 :                 ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
     230           0 :                 ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
     231             :         } else {
     232           0 :                 ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
     233           0 :                 ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
     234             :         }
     235             : 
     236           0 :         cm_helper_program_color_matrices(
     237             :                         mpc20->base.ctx,
     238             :                         regval,
     239             :                         &ocsc_regs);
     240             : 
     241           0 :         REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
     242             : }
     243             : 
     244           0 : static void mpc2_ogam_get_reg_field(
     245             :                 struct mpc *mpc,
     246             :                 struct xfer_func_reg *reg)
     247             : {
     248           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     249             : 
     250           0 :         reg->shifts.exp_region0_lut_offset = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
     251           0 :         reg->masks.exp_region0_lut_offset = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
     252           0 :         reg->shifts.exp_region0_num_segments = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
     253           0 :         reg->masks.exp_region0_num_segments = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
     254           0 :         reg->shifts.exp_region1_lut_offset = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
     255           0 :         reg->masks.exp_region1_lut_offset = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
     256           0 :         reg->shifts.exp_region1_num_segments = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
     257           0 :         reg->masks.exp_region1_num_segments = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
     258           0 :         reg->shifts.field_region_end = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B;
     259           0 :         reg->masks.field_region_end = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B;
     260           0 :         reg->shifts.field_region_end_slope = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
     261           0 :         reg->masks.field_region_end_slope = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
     262           0 :         reg->shifts.field_region_end_base = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
     263           0 :         reg->masks.field_region_end_base = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
     264           0 :         reg->shifts.field_region_linear_slope = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
     265           0 :         reg->masks.field_region_linear_slope = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
     266           0 :         reg->shifts.exp_region_start = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B;
     267           0 :         reg->masks.exp_region_start = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B;
     268           0 :         reg->shifts.exp_resion_start_segment = mpc20->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
     269           0 :         reg->masks.exp_resion_start_segment = mpc20->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
     270           0 : }
     271             : 
     272           0 : void mpc20_power_on_ogam_lut(
     273             :                 struct mpc *mpc, int mpcc_id,
     274             :                 bool power_on)
     275             : {
     276           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     277             : 
     278           0 :         REG_SET(MPCC_MEM_PWR_CTRL[mpcc_id], 0,
     279             :                         MPCC_OGAM_MEM_PWR_DIS, power_on == true ? 1:0);
     280             : 
     281           0 : }
     282             : 
     283           0 : static void mpc20_configure_ogam_lut(
     284             :                 struct mpc *mpc, int mpcc_id,
     285             :                 bool is_ram_a)
     286             : {
     287           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     288             : 
     289           0 :         REG_UPDATE_2(MPCC_OGAM_LUT_RAM_CONTROL[mpcc_id],
     290             :                         MPCC_OGAM_LUT_WRITE_EN_MASK, 7,
     291             :                         MPCC_OGAM_LUT_RAM_SEL, is_ram_a == true ? 0:1);
     292             : 
     293           0 :         REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
     294           0 : }
     295             : 
     296           0 : static enum dc_lut_mode mpc20_get_ogam_current(struct mpc *mpc, int mpcc_id)
     297             : {
     298             :         enum dc_lut_mode mode;
     299             :         uint32_t state_mode;
     300           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     301             : 
     302           0 :         REG_GET(MPCC_OGAM_LUT_RAM_CONTROL[mpcc_id], MPCC_OGAM_CONFIG_STATUS, &state_mode);
     303             : 
     304           0 :         switch (state_mode) {
     305             :         case 0:
     306             :                 mode = LUT_BYPASS;
     307             :                 break;
     308             :         case 1:
     309           0 :                 mode = LUT_RAM_A;
     310           0 :                 break;
     311             :         case 2:
     312           0 :                 mode = LUT_RAM_B;
     313           0 :                 break;
     314             :         default:
     315             :                 mode = LUT_BYPASS;
     316             :                 break;
     317             :         }
     318             : 
     319           0 :         return mode;
     320             : }
     321             : 
     322           0 : static void mpc2_program_lutb(struct mpc *mpc, int mpcc_id,
     323             :                         const struct pwl_params *params)
     324             : {
     325           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     326             :         struct xfer_func_reg gam_regs;
     327             : 
     328           0 :         mpc2_ogam_get_reg_field(mpc, &gam_regs);
     329             : 
     330           0 :         gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]);
     331           0 :         gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]);
     332           0 :         gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]);
     333           0 :         gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_SLOPE_CNTL_B[mpcc_id]);
     334           0 :         gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_SLOPE_CNTL_G[mpcc_id]);
     335           0 :         gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_SLOPE_CNTL_R[mpcc_id]);
     336           0 :         gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]);
     337           0 :         gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]);
     338           0 :         gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]);
     339           0 :         gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]);
     340           0 :         gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]);
     341           0 :         gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]);
     342           0 :         gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]);
     343           0 :         gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]);
     344             : 
     345           0 :         cm_helper_program_xfer_func(mpc20->base.ctx, params, &gam_regs);
     346             : 
     347           0 : }
     348             : 
     349           0 : static void mpc2_program_luta(struct mpc *mpc, int mpcc_id,
     350             :                 const struct pwl_params *params)
     351             : {
     352           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     353             :         struct xfer_func_reg gam_regs;
     354             : 
     355           0 :         mpc2_ogam_get_reg_field(mpc, &gam_regs);
     356             : 
     357           0 :         gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]);
     358           0 :         gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]);
     359           0 :         gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]);
     360           0 :         gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_SLOPE_CNTL_B[mpcc_id]);
     361           0 :         gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_SLOPE_CNTL_G[mpcc_id]);
     362           0 :         gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_SLOPE_CNTL_R[mpcc_id]);
     363           0 :         gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]);
     364           0 :         gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]);
     365           0 :         gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]);
     366           0 :         gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]);
     367           0 :         gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]);
     368           0 :         gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]);
     369           0 :         gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]);
     370           0 :         gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]);
     371             : 
     372           0 :         cm_helper_program_xfer_func(mpc20->base.ctx, params, &gam_regs);
     373             : 
     374           0 : }
     375             : 
     376           0 : static void mpc20_program_ogam_pwl(
     377             :                 struct mpc *mpc, int mpcc_id,
     378             :                 const struct pwl_result_data *rgb,
     379             :                 uint32_t num)
     380             : {
     381             :         uint32_t i;
     382           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     383             : 
     384           0 :         PERF_TRACE();
     385           0 :         REG_SEQ_START();
     386             : 
     387           0 :         for (i = 0 ; i < num; i++) {
     388           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
     389           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg);
     390           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg);
     391             : 
     392           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0,
     393             :                                 MPCC_OGAM_LUT_DATA, rgb[i].delta_red_reg);
     394           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0,
     395             :                                 MPCC_OGAM_LUT_DATA, rgb[i].delta_green_reg);
     396           0 :                 REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0,
     397             :                                 MPCC_OGAM_LUT_DATA, rgb[i].delta_blue_reg);
     398             : 
     399             :         }
     400             : 
     401           0 : }
     402             : 
     403           0 : static void apply_DEDCN20_305_wa(struct mpc *mpc, int mpcc_id,
     404             :                                  enum dc_lut_mode current_mode,
     405             :                                  enum dc_lut_mode next_mode)
     406             : {
     407           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     408             : 
     409           0 :         if (mpc->ctx->dc->debug.cm_in_bypass) {
     410           0 :                 REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
     411           0 :                 return;
     412             :         }
     413             : 
     414           0 :         if (mpc->ctx->dc->work_arounds.dedcn20_305_wa == false) {
     415             :                 /*hw fixed in new review*/
     416             :                 return;
     417             :         }
     418           0 :         if (current_mode == LUT_BYPASS)
     419             :                 /*this will only work if OTG is locked.
     420             :                  *if we were to support OTG unlock case,
     421             :                  *the workaround will be more complex
     422             :                  */
     423           0 :                 REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE,
     424             :                         next_mode == LUT_RAM_A ? 1:2);
     425             : }
     426             : 
     427           0 : void mpc2_set_output_gamma(
     428             :                 struct mpc *mpc,
     429             :                 int mpcc_id,
     430             :                 const struct pwl_params *params)
     431             : {
     432             :         enum dc_lut_mode current_mode;
     433             :         enum dc_lut_mode next_mode;
     434           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     435             : 
     436           0 :         if (mpc->ctx->dc->debug.cm_in_bypass) {
     437           0 :                 REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
     438           0 :                 return;
     439             :         }
     440             : 
     441           0 :         if (params == NULL) {
     442           0 :                 REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
     443           0 :                 return;
     444             :         }
     445             : 
     446           0 :         current_mode = mpc20_get_ogam_current(mpc, mpcc_id);
     447           0 :         if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
     448             :                 next_mode = LUT_RAM_B;
     449             :         else
     450           0 :                 next_mode = LUT_RAM_A;
     451             : 
     452           0 :         mpc20_power_on_ogam_lut(mpc, mpcc_id, true);
     453           0 :         mpc20_configure_ogam_lut(mpc, mpcc_id, next_mode == LUT_RAM_A);
     454             : 
     455           0 :         if (next_mode == LUT_RAM_A)
     456           0 :                 mpc2_program_luta(mpc, mpcc_id, params);
     457             :         else
     458           0 :                 mpc2_program_lutb(mpc, mpcc_id, params);
     459             : 
     460           0 :         apply_DEDCN20_305_wa(mpc, mpcc_id, current_mode, next_mode);
     461             : 
     462           0 :         mpc20_program_ogam_pwl(
     463           0 :                         mpc, mpcc_id, params->rgb_resulted, params->hw_points_num);
     464             : 
     465           0 :         REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE,
     466             :                 next_mode == LUT_RAM_A ? 1:2);
     467             : }
     468           0 : void mpc2_assert_idle_mpcc(struct mpc *mpc, int id)
     469             : {
     470           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     471             :         unsigned int mpc_disabled;
     472             : 
     473           0 :         ASSERT(!(mpc20->mpcc_in_use_mask & 1 << id));
     474           0 :         REG_GET(MPCC_STATUS[id], MPCC_DISABLED, &mpc_disabled);
     475           0 :         if (mpc_disabled)
     476           0 :                 return;
     477             : 
     478           0 :         REG_WAIT(MPCC_STATUS[id],
     479             :                         MPCC_IDLE, 1,
     480             :                         1, 100000);
     481             : }
     482             : 
     483           0 : void mpc2_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id)
     484             : {
     485           0 :         struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
     486             :         unsigned int top_sel, mpc_busy, mpc_idle, mpc_disabled;
     487             : 
     488           0 :         REG_GET(MPCC_TOP_SEL[mpcc_id],
     489             :                         MPCC_TOP_SEL, &top_sel);
     490             : 
     491           0 :         REG_GET_3(MPCC_STATUS[mpcc_id],
     492             :                         MPCC_BUSY, &mpc_busy,
     493             :                         MPCC_IDLE, &mpc_idle,
     494             :                         MPCC_DISABLED, &mpc_disabled);
     495             : 
     496           0 :         if (top_sel == 0xf) {
     497           0 :                 ASSERT(!mpc_busy);
     498           0 :                 ASSERT(mpc_idle);
     499           0 :                 ASSERT(mpc_disabled);
     500             :         } else {
     501           0 :                 ASSERT(!mpc_disabled);
     502           0 :                 ASSERT(!mpc_idle);
     503             :         }
     504             : 
     505           0 :         REG_SEQ_SUBMIT();
     506           0 :         PERF_TRACE();
     507           0 :         REG_SEQ_WAIT_DONE();
     508           0 :         PERF_TRACE();
     509           0 : }
     510             : 
     511             : static void mpc2_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
     512             : {
     513           0 :         mpcc->mpcc_id = mpcc_inst;
     514           0 :         mpcc->dpp_id = 0xf;
     515           0 :         mpcc->mpcc_bot = NULL;
     516           0 :         mpcc->blnd_cfg.overlap_only = false;
     517           0 :         mpcc->blnd_cfg.global_alpha = 0xff;
     518           0 :         mpcc->blnd_cfg.global_gain = 0xff;
     519           0 :         mpcc->blnd_cfg.background_color_bpc = 4;
     520           0 :         mpcc->blnd_cfg.bottom_gain_mode = 0;
     521           0 :         mpcc->blnd_cfg.top_gain = 0x1f000;
     522           0 :         mpcc->blnd_cfg.bottom_inside_gain = 0x1f000;
     523           0 :         mpcc->blnd_cfg.bottom_outside_gain = 0x1f000;
     524           0 :         mpcc->sm_cfg.enable = false;
     525             : }
     526             : 
     527           0 : static struct mpcc *mpc2_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id)
     528             : {
     529           0 :         struct mpcc *tmp_mpcc = tree->opp_list;
     530             : 
     531           0 :         while (tmp_mpcc != NULL) {
     532           0 :                 if (tmp_mpcc->dpp_id == 0xf || tmp_mpcc->dpp_id == dpp_id)
     533             :                         return tmp_mpcc;
     534             : 
     535             :                 /* avoid circular linked list */
     536           0 :                 ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot);
     537           0 :                 if (tmp_mpcc == tmp_mpcc->mpcc_bot)
     538             :                         break;
     539             : 
     540             :                 tmp_mpcc = tmp_mpcc->mpcc_bot;
     541             :         }
     542             :         return NULL;
     543             : }
     544             : 
     545             : const struct mpc_funcs dcn20_mpc_funcs = {
     546             :         .read_mpcc_state = mpc1_read_mpcc_state,
     547             :         .insert_plane = mpc1_insert_plane,
     548             :         .remove_mpcc = mpc1_remove_mpcc,
     549             :         .mpc_init = mpc1_mpc_init,
     550             :         .mpc_init_single_inst = mpc1_mpc_init_single_inst,
     551             :         .update_blending = mpc2_update_blending,
     552             :         .cursor_lock = mpc1_cursor_lock,
     553             :         .get_mpcc_for_dpp = mpc2_get_mpcc_for_dpp,
     554             :         .wait_for_idle = mpc2_assert_idle_mpcc,
     555             :         .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
     556             :         .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
     557             :         .set_denorm = mpc2_set_denorm,
     558             :         .set_denorm_clamp = mpc2_set_denorm_clamp,
     559             :         .set_output_csc = mpc2_set_output_csc,
     560             :         .set_ocsc_default = mpc2_set_ocsc_default,
     561             :         .set_output_gamma = mpc2_set_output_gamma,
     562             :         .power_on_mpc_mem_pwr = mpc20_power_on_ogam_lut,
     563             :         .get_mpc_out_mux = mpc1_get_mpc_out_mux,
     564             :         .set_bg_color = mpc1_set_bg_color,
     565             : };
     566             : 
     567           0 : void dcn20_mpc_construct(struct dcn20_mpc *mpc20,
     568             :         struct dc_context *ctx,
     569             :         const struct dcn20_mpc_registers *mpc_regs,
     570             :         const struct dcn20_mpc_shift *mpc_shift,
     571             :         const struct dcn20_mpc_mask *mpc_mask,
     572             :         int num_mpcc)
     573             : {
     574             :         int i;
     575             : 
     576           0 :         mpc20->base.ctx = ctx;
     577             : 
     578           0 :         mpc20->base.funcs = &dcn20_mpc_funcs;
     579             : 
     580           0 :         mpc20->mpc_regs = mpc_regs;
     581           0 :         mpc20->mpc_shift = mpc_shift;
     582           0 :         mpc20->mpc_mask = mpc_mask;
     583             : 
     584           0 :         mpc20->mpcc_in_use_mask = 0;
     585           0 :         mpc20->num_mpcc = num_mpcc;
     586             : 
     587           0 :         for (i = 0; i < MAX_MPCC; i++)
     588           0 :                 mpc2_init_mpcc(&mpc20->base.mpcc_array[i], i);
     589           0 : }
     590             : 

Generated by: LCOV version 1.14