1 /* 2 * Copyright 2020 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 "fixed31_32.h" 28 #include "resource.h" 29 #include "basics/conversion.h" 30 #include "dwb.h" 31 #include "dcn30_dwb.h" 32 #include "dcn30_cm_common.h" 33 #include "dcn10/dcn10_cm_common.h" 34 35 36 #define REG(reg)\ 37 dwbc30->dwbc_regs->reg 38 39 #define CTX \ 40 dwbc30->base.ctx 41 42 #undef FN 43 #define FN(reg_name, field_name) \ 44 dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name 45 46 #define TO_DCN30_DWBC(dwbc_base) \ 47 container_of(dwbc_base, struct dcn30_dwbc, base) 48 49 static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30, 50 struct dcn3_xfer_func_reg *reg) 51 { 52 reg->shifts.exp_region0_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; 53 reg->masks.exp_region0_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; 54 reg->shifts.exp_region0_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; 55 reg->masks.exp_region0_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; 56 reg->shifts.exp_region1_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; 57 reg->masks.exp_region1_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; 58 reg->shifts.exp_region1_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; 59 reg->masks.exp_region1_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; 60 61 reg->shifts.field_region_end = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_B; 62 reg->masks.field_region_end = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_B; 63 reg->shifts.field_region_end_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B; 64 reg->masks.field_region_end_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B; 65 reg->shifts.field_region_end_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B; 66 reg->masks.field_region_end_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B; 67 reg->shifts.field_region_linear_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B; 68 reg->masks.field_region_linear_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B; 69 reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B; 70 reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B; 71 reg->shifts.exp_region_start = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_B; 72 reg->masks.exp_region_start = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_B; 73 reg->shifts.exp_resion_start_segment = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; 74 reg->masks.exp_resion_start_segment = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; 75 } 76 77 /*program dwb ogam RAM A*/ 78 static void dwb3_program_ogam_luta_settings( 79 struct dcn30_dwbc *dwbc30, 80 const struct pwl_params *params) 81 { 82 struct dcn3_xfer_func_reg gam_regs; 83 84 dwb3_get_reg_field_ogam(dwbc30, &gam_regs); 85 86 gam_regs.start_cntl_b = REG(DWB_OGAM_RAMA_START_CNTL_B); 87 gam_regs.start_cntl_g = REG(DWB_OGAM_RAMA_START_CNTL_G); 88 gam_regs.start_cntl_r = REG(DWB_OGAM_RAMA_START_CNTL_R); 89 gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMA_START_BASE_CNTL_B); 90 gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMA_START_BASE_CNTL_G); 91 gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMA_START_BASE_CNTL_R); 92 gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_B); 93 gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_G); 94 gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_R); 95 gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMA_END_CNTL1_B); 96 gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMA_END_CNTL2_B); 97 gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMA_END_CNTL1_G); 98 gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMA_END_CNTL2_G); 99 gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMA_END_CNTL1_R); 100 gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMA_END_CNTL2_R); 101 gam_regs.offset_b = REG(DWB_OGAM_RAMA_OFFSET_B); 102 gam_regs.offset_g = REG(DWB_OGAM_RAMA_OFFSET_G); 103 gam_regs.offset_r = REG(DWB_OGAM_RAMA_OFFSET_R); 104 gam_regs.region_start = REG(DWB_OGAM_RAMA_REGION_0_1); 105 gam_regs.region_end = REG(DWB_OGAM_RAMA_REGION_32_33); 106 /*todo*/ 107 cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs); 108 } 109 110 /*program dwb ogam RAM B*/ 111 static void dwb3_program_ogam_lutb_settings( 112 struct dcn30_dwbc *dwbc30, 113 const struct pwl_params *params) 114 { 115 struct dcn3_xfer_func_reg gam_regs; 116 117 dwb3_get_reg_field_ogam(dwbc30, &gam_regs); 118 119 gam_regs.start_cntl_b = REG(DWB_OGAM_RAMB_START_CNTL_B); 120 gam_regs.start_cntl_g = REG(DWB_OGAM_RAMB_START_CNTL_G); 121 gam_regs.start_cntl_r = REG(DWB_OGAM_RAMB_START_CNTL_R); 122 gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMB_START_BASE_CNTL_B); 123 gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMB_START_BASE_CNTL_G); 124 gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMB_START_BASE_CNTL_R); 125 gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_B); 126 gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_G); 127 gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_R); 128 gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMB_END_CNTL1_B); 129 gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMB_END_CNTL2_B); 130 gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMB_END_CNTL1_G); 131 gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMB_END_CNTL2_G); 132 gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMB_END_CNTL1_R); 133 gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMB_END_CNTL2_R); 134 gam_regs.offset_b = REG(DWB_OGAM_RAMB_OFFSET_B); 135 gam_regs.offset_g = REG(DWB_OGAM_RAMB_OFFSET_G); 136 gam_regs.offset_r = REG(DWB_OGAM_RAMB_OFFSET_R); 137 gam_regs.region_start = REG(DWB_OGAM_RAMB_REGION_0_1); 138 gam_regs.region_end = REG(DWB_OGAM_RAMB_REGION_32_33); 139 140 cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs); 141 } 142 143 static enum dc_lut_mode dwb3_get_ogam_current( 144 struct dcn30_dwbc *dwbc30) 145 { 146 enum dc_lut_mode mode; 147 uint32_t state_mode; 148 uint32_t ram_select; 149 150 REG_GET(DWB_OGAM_CONTROL, 151 DWB_OGAM_MODE, &state_mode); 152 REG_GET(DWB_OGAM_CONTROL, 153 DWB_OGAM_SELECT, &ram_select); 154 155 if (state_mode == 0) { 156 mode = LUT_BYPASS; 157 } else if (state_mode == 2) { 158 if (ram_select == 0) 159 mode = LUT_RAM_A; 160 else 161 mode = LUT_RAM_B; 162 } else { 163 // Reserved value 164 mode = LUT_BYPASS; 165 BREAK_TO_DEBUGGER(); 166 return mode; 167 } 168 return mode; 169 } 170 171 static void dwb3_configure_ogam_lut( 172 struct dcn30_dwbc *dwbc30, 173 bool is_ram_a) 174 { 175 REG_UPDATE(DWB_OGAM_LUT_CONTROL, 176 DWB_OGAM_LUT_READ_COLOR_SEL, 7); 177 REG_UPDATE(DWB_OGAM_CONTROL, 178 DWB_OGAM_SELECT, is_ram_a == true ? 0 : 1); 179 REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0); 180 } 181 182 static void dwb3_program_ogam_pwl(struct dcn30_dwbc *dwbc30, 183 const struct pwl_result_data *rgb, 184 uint32_t num) 185 { 186 uint32_t i; 187 188 // triple base implementation 189 for (i = 0; i < num/2; i++) { 190 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].red_reg); 191 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].green_reg); 192 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].blue_reg); 193 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].red_reg); 194 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].green_reg); 195 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].blue_reg); 196 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].red_reg); 197 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].green_reg); 198 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].blue_reg); 199 } 200 } 201 202 static bool dwb3_program_ogam_lut( 203 struct dcn30_dwbc *dwbc30, 204 const struct pwl_params *params) 205 { 206 enum dc_lut_mode current_mode; 207 enum dc_lut_mode next_mode; 208 209 if (params == NULL) { 210 REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 0); 211 return false; 212 } 213 214 current_mode = dwb3_get_ogam_current(dwbc30); 215 if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) 216 next_mode = LUT_RAM_B; 217 else 218 next_mode = LUT_RAM_A; 219 220 dwb3_configure_ogam_lut(dwbc30, next_mode == LUT_RAM_A); 221 222 if (next_mode == LUT_RAM_A) 223 dwb3_program_ogam_luta_settings(dwbc30, params); 224 else 225 dwb3_program_ogam_lutb_settings(dwbc30, params); 226 227 dwb3_program_ogam_pwl( 228 dwbc30, params->rgb_resulted, params->hw_points_num); 229 230 REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2); 231 REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1); 232 233 return true; 234 } 235 236 bool dwb3_ogam_set_input_transfer_func( 237 struct dwbc *dwbc, 238 const struct dc_transfer_func *in_transfer_func_dwb_ogam) 239 { 240 struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); 241 bool result = false; 242 struct pwl_params *dwb_ogam_lut = NULL; 243 244 if (in_transfer_func_dwb_ogam == NULL) 245 return result; 246 247 dwb_ogam_lut = kzalloc(sizeof(*dwb_ogam_lut), GFP_KERNEL); 248 249 if (dwb_ogam_lut) { 250 cm_helper_translate_curve_to_hw_format( 251 in_transfer_func_dwb_ogam, 252 dwb_ogam_lut, false); 253 254 result = dwb3_program_ogam_lut( 255 dwbc30, 256 dwb_ogam_lut); 257 kfree(dwb_ogam_lut); 258 dwb_ogam_lut = NULL; 259 } 260 261 return result; 262 } 263 264 static void dwb3_program_gamut_remap( 265 struct dwbc *dwbc, 266 const uint16_t *regval, 267 enum cm_gamut_coef_format coef_format, 268 enum cm_gamut_remap_select select) 269 { 270 struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); 271 272 struct color_matrices_reg gam_regs; 273 274 REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format); 275 276 if (regval == NULL || select == CM_GAMUT_REMAP_MODE_BYPASS) { 277 REG_SET(DWB_GAMUT_REMAP_MODE, 0, 278 DWB_GAMUT_REMAP_MODE, 0); 279 return; 280 } 281 282 switch (select) { 283 case CM_GAMUT_REMAP_MODE_RAMA_COEFF: 284 gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPA_C11_C12); 285 gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPA_C33_C34); 286 287 cm_helper_program_color_matrices( 288 dwbc30->base.ctx, 289 regval, 290 &gam_regs); 291 break; 292 case CM_GAMUT_REMAP_MODE_RAMB_COEFF: 293 gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPB_C11_C12); 294 gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPB_C33_C34); 295 296 cm_helper_program_color_matrices( 297 dwbc30->base.ctx, 298 regval, 299 &gam_regs); 300 break; 301 case CM_GAMUT_REMAP_MODE_RESERVED: 302 /* should never happen, bug */ 303 BREAK_TO_DEBUGGER(); 304 return; 305 default: 306 break; 307 } 308 309 REG_SET(DWB_GAMUT_REMAP_MODE, 0, 310 DWB_GAMUT_REMAP_MODE, select); 311 312 } 313 314 void dwb3_set_gamut_remap( 315 struct dwbc *dwbc, 316 const struct dc_dwb_params *params) 317 { 318 struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); 319 struct cm_grph_csc_adjustment adjust = params->csc_params; 320 int i = 0; 321 322 if (adjust.gamut_adjust_type != CM_GAMUT_ADJUST_TYPE_SW) { 323 /* Bypass if type is bypass or hw */ 324 dwb3_program_gamut_remap(dwbc, NULL, adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_BYPASS); 325 } else { 326 struct fixed31_32 arr_matrix[12]; 327 uint16_t arr_reg_val[12]; 328 unsigned int current_mode; 329 330 for (i = 0; i < 12; i++) 331 arr_matrix[i] = adjust.temperature_matrix[i]; 332 333 convert_float_matrix(arr_reg_val, arr_matrix, 12); 334 335 REG_GET(DWB_GAMUT_REMAP_MODE, DWB_GAMUT_REMAP_MODE_CURRENT, ¤t_mode); 336 337 if (current_mode == CM_GAMUT_REMAP_MODE_RAMA_COEFF) { 338 dwb3_program_gamut_remap(dwbc, arr_reg_val, 339 adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMB_COEFF); 340 } else { 341 dwb3_program_gamut_remap(dwbc, arr_reg_val, 342 adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMA_COEFF); 343 } 344 } 345 } 346 347 void dwb3_program_hdr_mult( 348 struct dwbc *dwbc, 349 const struct dc_dwb_params *params) 350 { 351 struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); 352 353 REG_UPDATE(DWB_HDR_MULT_COEF, DWB_HDR_MULT_COEF, params->hdr_mult); 354 } 355