1/*
2 * Copyright 2016 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 "dm_services.h"
27
28#include "core_types.h"
29
30#include "reg_helper.h"
31#include "dcn20_dpp.h"
32#include "basics/conversion.h"
33
34#include "dcn10/dcn10_cm_common.h"
35
36#define REG(reg)\
37 dpp->tf_regs->reg
38
39#define IND_REG(index) \
40 (index)
41
42#define CTX \
43 dpp->base.ctx
44
45#undef FN
46#define FN(reg_name, field_name) \
47 dpp->tf_shift->field_name, dpp->tf_mask->field_name
48
49
50static void dpp2_enable_cm_block(
51 struct dpp *dpp_base)
52{
53 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
54
55 unsigned int cm_bypass_mode = 0;
56 //Temp, put CM in bypass mode
57 if (dpp_base->ctx->dc->debug.cm_in_bypass)
58 cm_bypass_mode = 1;
59
60 REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode);
61}
62
63
64static bool dpp2_degamma_ram_inuse(
65 struct dpp *dpp_base,
66 bool *ram_a_inuse)
67{
68 bool ret = false;
69 uint32_t status_reg = 0;
70 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
71
72 REG_GET(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_CONFIG_STATUS,
73 &status_reg);
74
75 if (status_reg == 3) {
76 *ram_a_inuse = true;
77 ret = true;
78 } else if (status_reg == 4) {
79 *ram_a_inuse = false;
80 ret = true;
81 }
82 return ret;
83}
84
85static void dpp2_program_degamma_lut(
86 struct dpp *dpp_base,
87 const struct pwl_result_data *rgb,
88 uint32_t num,
89 bool is_ram_a)
90{
91 uint32_t i;
92
93 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
94 REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK,
95 CM_DGAM_LUT_WRITE_EN_MASK, 7);
96 REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL,
97 is_ram_a == true ? 0:1);
98
99 REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0);
100 for (i = 0 ; i < num; i++) {
101 REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg);
102 REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg);
103 REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg);
104
105 REG_SET(CM_DGAM_LUT_DATA, 0,
106 CM_DGAM_LUT_DATA, rgb[i].delta_red_reg);
107 REG_SET(CM_DGAM_LUT_DATA, 0,
108 CM_DGAM_LUT_DATA, rgb[i].delta_green_reg);
109 REG_SET(CM_DGAM_LUT_DATA, 0,
110 CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg);
111
112 }
113
114}
115
116void dpp2_set_degamma_pwl(
117 struct dpp *dpp_base,
118 const struct pwl_params *params)
119{
120 bool is_ram_a = true;
121
122 dpp1_power_on_degamma_lut(dpp_base, power_on: true);
123 dpp2_enable_cm_block(dpp_base);
124 dpp2_degamma_ram_inuse(dpp_base, ram_a_inuse: &is_ram_a);
125 if (is_ram_a == true)
126 dpp1_program_degamma_lutb_settings(dpp_base, params);
127 else
128 dpp1_program_degamma_luta_settings(dpp_base, params);
129
130 dpp2_program_degamma_lut(dpp_base, rgb: params->rgb_resulted, num: params->hw_points_num, is_ram_a: !is_ram_a);
131 dpp1_degamma_ram_select(dpp_base, use_ram_a: !is_ram_a);
132}
133
134void dpp2_set_degamma(
135 struct dpp *dpp_base,
136 enum ipp_degamma_mode mode)
137{
138 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
139 dpp2_enable_cm_block(dpp_base);
140
141 switch (mode) {
142 case IPP_DEGAMMA_MODE_BYPASS:
143 /* Setting de gamma bypass for now */
144 REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
145 break;
146 case IPP_DEGAMMA_MODE_HW_sRGB:
147 REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
148 break;
149 case IPP_DEGAMMA_MODE_HW_xvYCC:
150 REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
151 break;
152 case IPP_DEGAMMA_MODE_USER_PWL:
153 REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
154 break;
155 default:
156 BREAK_TO_DEBUGGER();
157 break;
158 }
159}
160
161static void program_gamut_remap(
162 struct dcn20_dpp *dpp,
163 const uint16_t *regval,
164 enum dcn20_gamut_remap_select select)
165{
166 uint32_t cur_select = 0;
167 struct color_matrices_reg gam_regs;
168
169 if (regval == NULL || select == DCN2_GAMUT_REMAP_BYPASS) {
170 REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
171 CM_GAMUT_REMAP_MODE, 0);
172 return;
173 }
174
175 /* determine which gamut_remap coefficients (A or B) we are using
176 * currently. select the alternate set to double buffer
177 * the update so gamut_remap is updated on frame boundary
178 */
179 IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
180 CM_TEST_DEBUG_DATA_STATUS_IDX,
181 CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE, &cur_select);
182
183 /* value stored in dbg reg will be 1 greater than mode we want */
184 if (cur_select != DCN2_GAMUT_REMAP_COEF_A)
185 select = DCN2_GAMUT_REMAP_COEF_A;
186 else
187 select = DCN2_GAMUT_REMAP_COEF_B;
188
189 gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
190 gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11;
191 gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
192 gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
193
194 if (select == DCN2_GAMUT_REMAP_COEF_A) {
195 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
196 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
197 } else {
198 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
199 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
200 }
201
202 cm_helper_program_color_matrices(
203 ctx: dpp->base.ctx,
204 regval,
205 reg: &gam_regs);
206
207 REG_SET(
208 CM_GAMUT_REMAP_CONTROL, 0,
209 CM_GAMUT_REMAP_MODE, select);
210
211}
212
213void dpp2_cm_set_gamut_remap(
214 struct dpp *dpp_base,
215 const struct dpp_grph_csc_adjustment *adjust)
216{
217 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
218 int i = 0;
219
220 if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
221 /* Bypass if type is bypass or hw */
222 program_gamut_remap(dpp, NULL, select: DCN2_GAMUT_REMAP_BYPASS);
223 else {
224 struct fixed31_32 arr_matrix[12];
225 uint16_t arr_reg_val[12];
226
227 for (i = 0; i < 12; i++)
228 arr_matrix[i] = adjust->temperature_matrix[i];
229
230 convert_float_matrix(
231 matrix: arr_reg_val, flt: arr_matrix, buffer_size: 12);
232
233 program_gamut_remap(dpp, regval: arr_reg_val, select: DCN2_GAMUT_REMAP_COEF_A);
234 }
235}
236
237static void read_gamut_remap(struct dcn20_dpp *dpp,
238 uint16_t *regval,
239 enum dcn20_gamut_remap_select *select)
240{
241 struct color_matrices_reg gam_regs;
242 uint32_t selection;
243
244 IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
245 CM_TEST_DEBUG_DATA_STATUS_IDX,
246 CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE, &selection);
247
248 *select = selection;
249
250 gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
251 gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11;
252 gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
253 gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
254
255 if (*select == DCN2_GAMUT_REMAP_COEF_A) {
256 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
257 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
258
259 cm_helper_read_color_matrices(ctx: dpp->base.ctx,
260 regval,
261 reg: &gam_regs);
262
263 } else if (*select == DCN2_GAMUT_REMAP_COEF_B) {
264 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
265 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
266
267 cm_helper_read_color_matrices(ctx: dpp->base.ctx,
268 regval,
269 reg: &gam_regs);
270 }
271}
272
273void dpp2_cm_get_gamut_remap(struct dpp *dpp_base,
274 struct dpp_grph_csc_adjustment *adjust)
275{
276 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
277 uint16_t arr_reg_val[12];
278 enum dcn20_gamut_remap_select select;
279
280 read_gamut_remap(dpp, regval: arr_reg_val, select: &select);
281
282 if (select == DCN2_GAMUT_REMAP_BYPASS) {
283 adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
284 return;
285 }
286
287 adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
288 convert_hw_matrix(matrix: adjust->temperature_matrix,
289 reg: arr_reg_val, ARRAY_SIZE(arr_reg_val));
290}
291
292void dpp2_program_input_csc(
293 struct dpp *dpp_base,
294 enum dc_color_space color_space,
295 enum dcn20_input_csc_select input_select,
296 const struct out_csc_color_matrix *tbl_entry)
297{
298 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
299 int i;
300 int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
301 const uint16_t *regval = NULL;
302 uint32_t cur_select = 0;
303 enum dcn20_input_csc_select select;
304 struct color_matrices_reg icsc_regs;
305
306 if (input_select == DCN2_ICSC_SELECT_BYPASS) {
307 REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
308 return;
309 }
310
311 if (tbl_entry == NULL) {
312 for (i = 0; i < arr_size; i++)
313 if (dpp_input_csc_matrix[i].color_space == color_space) {
314 regval = dpp_input_csc_matrix[i].regval;
315 break;
316 }
317
318 if (regval == NULL) {
319 BREAK_TO_DEBUGGER();
320 return;
321 }
322 } else {
323 regval = tbl_entry->regval;
324 }
325
326 /* determine which CSC coefficients (A or B) we are using
327 * currently. select the alternate set to double buffer
328 * the CSC update so CSC is updated on frame boundary
329 */
330 IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
331 CM_TEST_DEBUG_DATA_STATUS_IDX,
332 CM_TEST_DEBUG_DATA_ICSC_MODE, &cur_select);
333
334 if (cur_select != DCN2_ICSC_SELECT_ICSC_A)
335 select = DCN2_ICSC_SELECT_ICSC_A;
336 else
337 select = DCN2_ICSC_SELECT_ICSC_B;
338
339 icsc_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
340 icsc_regs.masks.csc_c11 = dpp->tf_mask->CM_ICSC_C11;
341 icsc_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
342 icsc_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
343
344 if (select == DCN2_ICSC_SELECT_ICSC_A) {
345
346 icsc_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
347 icsc_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
348
349 } else {
350
351 icsc_regs.csc_c11_c12 = REG(CM_ICSC_B_C11_C12);
352 icsc_regs.csc_c33_c34 = REG(CM_ICSC_B_C33_C34);
353
354 }
355
356 cm_helper_program_color_matrices(
357 ctx: dpp->base.ctx,
358 regval,
359 reg: &icsc_regs);
360
361 REG_SET(CM_ICSC_CONTROL, 0,
362 CM_ICSC_MODE, select);
363}
364
365static void dpp20_power_on_blnd_lut(
366 struct dpp *dpp_base,
367 bool power_on)
368{
369 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
370
371 REG_SET(CM_MEM_PWR_CTRL, 0,
372 BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
373
374}
375
376static void dpp20_configure_blnd_lut(
377 struct dpp *dpp_base,
378 bool is_ram_a)
379{
380 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
381
382 REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
383 CM_BLNDGAM_LUT_WRITE_EN_MASK, 7);
384 REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
385 CM_BLNDGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
386 REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
387}
388
389static void dpp20_program_blnd_pwl(
390 struct dpp *dpp_base,
391 const struct pwl_result_data *rgb,
392 uint32_t num)
393{
394 uint32_t i;
395 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
396
397 for (i = 0 ; i < num; i++) {
398 REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
399 REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
400 REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);
401
402 REG_SET(CM_BLNDGAM_LUT_DATA, 0,
403 CM_BLNDGAM_LUT_DATA, rgb[i].delta_red_reg);
404 REG_SET(CM_BLNDGAM_LUT_DATA, 0,
405 CM_BLNDGAM_LUT_DATA, rgb[i].delta_green_reg);
406 REG_SET(CM_BLNDGAM_LUT_DATA, 0,
407 CM_BLNDGAM_LUT_DATA, rgb[i].delta_blue_reg);
408
409 }
410
411}
412
413static void dcn20_dpp_cm_get_reg_field(
414 struct dcn20_dpp *dpp,
415 struct xfer_func_reg *reg)
416{
417 reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
418 reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
419 reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
420 reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
421 reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
422 reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
423 reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
424 reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
425
426 reg->shifts.field_region_end = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
427 reg->masks.field_region_end = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
428 reg->shifts.field_region_end_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
429 reg->masks.field_region_end_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
430 reg->shifts.field_region_end_base = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
431 reg->masks.field_region_end_base = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
432 reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
433 reg->masks.field_region_linear_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
434 reg->shifts.exp_region_start = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
435 reg->masks.exp_region_start = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
436 reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
437 reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
438}
439
440/*program blnd lut RAM A*/
441static void dpp20_program_blnd_luta_settings(
442 struct dpp *dpp_base,
443 const struct pwl_params *params)
444{
445 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
446 struct xfer_func_reg gam_regs;
447
448 dcn20_dpp_cm_get_reg_field(dpp, reg: &gam_regs);
449
450 gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMA_START_CNTL_B);
451 gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMA_START_CNTL_G);
452 gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMA_START_CNTL_R);
453 gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_B);
454 gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_G);
455 gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_R);
456 gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMA_END_CNTL1_B);
457 gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMA_END_CNTL2_B);
458 gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMA_END_CNTL1_G);
459 gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMA_END_CNTL2_G);
460 gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMA_END_CNTL1_R);
461 gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMA_END_CNTL2_R);
462 gam_regs.region_start = REG(CM_BLNDGAM_RAMA_REGION_0_1);
463 gam_regs.region_end = REG(CM_BLNDGAM_RAMA_REGION_32_33);
464
465 cm_helper_program_xfer_func(ctx: dpp->base.ctx, params, reg: &gam_regs);
466}
467
468/*program blnd lut RAM B*/
469static void dpp20_program_blnd_lutb_settings(
470 struct dpp *dpp_base,
471 const struct pwl_params *params)
472{
473 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
474 struct xfer_func_reg gam_regs;
475
476 dcn20_dpp_cm_get_reg_field(dpp, reg: &gam_regs);
477
478 gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMB_START_CNTL_B);
479 gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMB_START_CNTL_G);
480 gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMB_START_CNTL_R);
481 gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_B);
482 gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_G);
483 gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_R);
484 gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMB_END_CNTL1_B);
485 gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMB_END_CNTL2_B);
486 gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMB_END_CNTL1_G);
487 gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMB_END_CNTL2_G);
488 gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMB_END_CNTL1_R);
489 gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMB_END_CNTL2_R);
490 gam_regs.region_start = REG(CM_BLNDGAM_RAMB_REGION_0_1);
491 gam_regs.region_end = REG(CM_BLNDGAM_RAMB_REGION_32_33);
492
493 cm_helper_program_xfer_func(ctx: dpp->base.ctx, params, reg: &gam_regs);
494}
495
496static enum dc_lut_mode dpp20_get_blndgam_current(struct dpp *dpp_base)
497{
498 enum dc_lut_mode mode;
499 uint32_t state_mode;
500 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
501
502 REG_GET(CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, &state_mode);
503
504 switch (state_mode) {
505 case 0:
506 mode = LUT_BYPASS;
507 break;
508 case 1:
509 mode = LUT_RAM_A;
510 break;
511 case 2:
512 mode = LUT_RAM_B;
513 break;
514 default:
515 mode = LUT_BYPASS;
516 break;
517 }
518
519 return mode;
520}
521
522bool dpp20_program_blnd_lut(
523 struct dpp *dpp_base, const struct pwl_params *params)
524{
525 enum dc_lut_mode current_mode;
526 enum dc_lut_mode next_mode;
527 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
528
529 if (params == NULL) {
530 REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE, 0);
531 return false;
532 }
533 current_mode = dpp20_get_blndgam_current(dpp_base);
534 if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
535 next_mode = LUT_RAM_B;
536 else
537 next_mode = LUT_RAM_A;
538
539 dpp20_power_on_blnd_lut(dpp_base, power_on: true);
540 dpp20_configure_blnd_lut(dpp_base, is_ram_a: next_mode == LUT_RAM_A);
541
542 if (next_mode == LUT_RAM_A)
543 dpp20_program_blnd_luta_settings(dpp_base, params);
544 else
545 dpp20_program_blnd_lutb_settings(dpp_base, params);
546
547 dpp20_program_blnd_pwl(
548 dpp_base, rgb: params->rgb_resulted, num: params->hw_points_num);
549
550 REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE,
551 next_mode == LUT_RAM_A ? 1:2);
552
553 return true;
554}
555
556
557static void dpp20_program_shaper_lut(
558 struct dpp *dpp_base,
559 const struct pwl_result_data *rgb,
560 uint32_t num)
561{
562 uint32_t i, red, green, blue;
563 uint32_t red_delta, green_delta, blue_delta;
564 uint32_t red_value, green_value, blue_value;
565
566 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
567
568 for (i = 0 ; i < num; i++) {
569
570 red = rgb[i].red_reg;
571 green = rgb[i].green_reg;
572 blue = rgb[i].blue_reg;
573
574 red_delta = rgb[i].delta_red_reg;
575 green_delta = rgb[i].delta_green_reg;
576 blue_delta = rgb[i].delta_blue_reg;
577
578 red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff);
579 green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
580 blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff);
581
582 REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, red_value);
583 REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, green_value);
584 REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, blue_value);
585 }
586
587}
588
589static enum dc_lut_mode dpp20_get_shaper_current(struct dpp *dpp_base)
590{
591 enum dc_lut_mode mode;
592 uint32_t state_mode;
593 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
594
595 REG_GET(CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_CONFIG_STATUS, &state_mode);
596
597 switch (state_mode) {
598 case 0:
599 mode = LUT_BYPASS;
600 break;
601 case 1:
602 mode = LUT_RAM_A;
603 break;
604 case 2:
605 mode = LUT_RAM_B;
606 break;
607 default:
608 mode = LUT_BYPASS;
609 break;
610 }
611
612 return mode;
613}
614
615static void dpp20_configure_shaper_lut(
616 struct dpp *dpp_base,
617 bool is_ram_a)
618{
619 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
620
621 REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
622 CM_SHAPER_LUT_WRITE_EN_MASK, 7);
623 REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
624 CM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
625 REG_SET(CM_SHAPER_LUT_INDEX, 0, CM_SHAPER_LUT_INDEX, 0);
626}
627
628/*program shaper RAM A*/
629
630static void dpp20_program_shaper_luta_settings(
631 struct dpp *dpp_base,
632 const struct pwl_params *params)
633{
634 const struct gamma_curve *curve;
635 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
636
637 REG_SET_2(CM_SHAPER_RAMA_START_CNTL_B, 0,
638 CM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
639 CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
640 REG_SET_2(CM_SHAPER_RAMA_START_CNTL_G, 0,
641 CM_SHAPER_RAMA_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
642 CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, 0);
643 REG_SET_2(CM_SHAPER_RAMA_START_CNTL_R, 0,
644 CM_SHAPER_RAMA_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
645 CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, 0);
646
647 REG_SET_2(CM_SHAPER_RAMA_END_CNTL_B, 0,
648 CM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
649 CM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
650
651 REG_SET_2(CM_SHAPER_RAMA_END_CNTL_G, 0,
652 CM_SHAPER_RAMA_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
653 CM_SHAPER_RAMA_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
654
655 REG_SET_2(CM_SHAPER_RAMA_END_CNTL_R, 0,
656 CM_SHAPER_RAMA_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
657 CM_SHAPER_RAMA_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
658
659 curve = params->arr_curve_points;
660 REG_SET_4(CM_SHAPER_RAMA_REGION_0_1, 0,
661 CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
662 CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
663 CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
664 CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
665
666 curve += 2;
667 REG_SET_4(CM_SHAPER_RAMA_REGION_2_3, 0,
668 CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
669 CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
670 CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
671 CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
672
673 curve += 2;
674 REG_SET_4(CM_SHAPER_RAMA_REGION_4_5, 0,
675 CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
676 CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
677 CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
678 CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
679
680 curve += 2;
681 REG_SET_4(CM_SHAPER_RAMA_REGION_6_7, 0,
682 CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
683 CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
684 CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
685 CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
686
687 curve += 2;
688 REG_SET_4(CM_SHAPER_RAMA_REGION_8_9, 0,
689 CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
690 CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
691 CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
692 CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
693
694 curve += 2;
695 REG_SET_4(CM_SHAPER_RAMA_REGION_10_11, 0,
696 CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
697 CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
698 CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
699 CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
700
701 curve += 2;
702 REG_SET_4(CM_SHAPER_RAMA_REGION_12_13, 0,
703 CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
704 CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
705 CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
706 CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
707
708 curve += 2;
709 REG_SET_4(CM_SHAPER_RAMA_REGION_14_15, 0,
710 CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
711 CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
712 CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
713 CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
714
715 curve += 2;
716 REG_SET_4(CM_SHAPER_RAMA_REGION_16_17, 0,
717 CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset,
718 CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
719 CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset,
720 CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
721
722 curve += 2;
723 REG_SET_4(CM_SHAPER_RAMA_REGION_18_19, 0,
724 CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset,
725 CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
726 CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset,
727 CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
728
729 curve += 2;
730 REG_SET_4(CM_SHAPER_RAMA_REGION_20_21, 0,
731 CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset,
732 CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
733 CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset,
734 CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
735
736 curve += 2;
737 REG_SET_4(CM_SHAPER_RAMA_REGION_22_23, 0,
738 CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset,
739 CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
740 CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset,
741 CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
742
743 curve += 2;
744 REG_SET_4(CM_SHAPER_RAMA_REGION_24_25, 0,
745 CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset,
746 CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
747 CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset,
748 CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
749
750 curve += 2;
751 REG_SET_4(CM_SHAPER_RAMA_REGION_26_27, 0,
752 CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset,
753 CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
754 CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset,
755 CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
756
757 curve += 2;
758 REG_SET_4(CM_SHAPER_RAMA_REGION_28_29, 0,
759 CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset,
760 CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
761 CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset,
762 CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
763
764 curve += 2;
765 REG_SET_4(CM_SHAPER_RAMA_REGION_30_31, 0,
766 CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset,
767 CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
768 CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset,
769 CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
770
771 curve += 2;
772 REG_SET_4(CM_SHAPER_RAMA_REGION_32_33, 0,
773 CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset,
774 CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
775 CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset,
776 CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
777}
778
779/*program shaper RAM B*/
780static void dpp20_program_shaper_lutb_settings(
781 struct dpp *dpp_base,
782 const struct pwl_params *params)
783{
784 const struct gamma_curve *curve;
785 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
786
787 REG_SET_2(CM_SHAPER_RAMB_START_CNTL_B, 0,
788 CM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
789 CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
790 REG_SET_2(CM_SHAPER_RAMB_START_CNTL_G, 0,
791 CM_SHAPER_RAMB_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
792 CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, 0);
793 REG_SET_2(CM_SHAPER_RAMB_START_CNTL_R, 0,
794 CM_SHAPER_RAMB_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
795 CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, 0);
796
797 REG_SET_2(CM_SHAPER_RAMB_END_CNTL_B, 0,
798 CM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
799 CM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
800
801 REG_SET_2(CM_SHAPER_RAMB_END_CNTL_G, 0,
802 CM_SHAPER_RAMB_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
803 CM_SHAPER_RAMB_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
804
805 REG_SET_2(CM_SHAPER_RAMB_END_CNTL_R, 0,
806 CM_SHAPER_RAMB_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
807 CM_SHAPER_RAMB_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
808
809 curve = params->arr_curve_points;
810 REG_SET_4(CM_SHAPER_RAMB_REGION_0_1, 0,
811 CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
812 CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
813 CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
814 CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
815
816 curve += 2;
817 REG_SET_4(CM_SHAPER_RAMB_REGION_2_3, 0,
818 CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
819 CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
820 CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
821 CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
822
823 curve += 2;
824 REG_SET_4(CM_SHAPER_RAMB_REGION_4_5, 0,
825 CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
826 CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
827 CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
828 CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
829
830 curve += 2;
831 REG_SET_4(CM_SHAPER_RAMB_REGION_6_7, 0,
832 CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
833 CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
834 CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
835 CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
836
837 curve += 2;
838 REG_SET_4(CM_SHAPER_RAMB_REGION_8_9, 0,
839 CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
840 CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
841 CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
842 CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
843
844 curve += 2;
845 REG_SET_4(CM_SHAPER_RAMB_REGION_10_11, 0,
846 CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
847 CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
848 CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
849 CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
850
851 curve += 2;
852 REG_SET_4(CM_SHAPER_RAMB_REGION_12_13, 0,
853 CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
854 CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
855 CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
856 CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
857
858 curve += 2;
859 REG_SET_4(CM_SHAPER_RAMB_REGION_14_15, 0,
860 CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
861 CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
862 CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
863 CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
864
865 curve += 2;
866 REG_SET_4(CM_SHAPER_RAMB_REGION_16_17, 0,
867 CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset,
868 CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
869 CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset,
870 CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
871
872 curve += 2;
873 REG_SET_4(CM_SHAPER_RAMB_REGION_18_19, 0,
874 CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset,
875 CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
876 CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset,
877 CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
878
879 curve += 2;
880 REG_SET_4(CM_SHAPER_RAMB_REGION_20_21, 0,
881 CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset,
882 CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
883 CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset,
884 CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
885
886 curve += 2;
887 REG_SET_4(CM_SHAPER_RAMB_REGION_22_23, 0,
888 CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset,
889 CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
890 CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset,
891 CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
892
893 curve += 2;
894 REG_SET_4(CM_SHAPER_RAMB_REGION_24_25, 0,
895 CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset,
896 CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
897 CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset,
898 CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
899
900 curve += 2;
901 REG_SET_4(CM_SHAPER_RAMB_REGION_26_27, 0,
902 CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset,
903 CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
904 CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset,
905 CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
906
907 curve += 2;
908 REG_SET_4(CM_SHAPER_RAMB_REGION_28_29, 0,
909 CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset,
910 CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
911 CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset,
912 CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
913
914 curve += 2;
915 REG_SET_4(CM_SHAPER_RAMB_REGION_30_31, 0,
916 CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset,
917 CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
918 CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset,
919 CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
920
921 curve += 2;
922 REG_SET_4(CM_SHAPER_RAMB_REGION_32_33, 0,
923 CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset,
924 CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
925 CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset,
926 CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
927
928}
929
930
931bool dpp20_program_shaper(
932 struct dpp *dpp_base,
933 const struct pwl_params *params)
934{
935 enum dc_lut_mode current_mode;
936 enum dc_lut_mode next_mode;
937
938 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
939
940 if (params == NULL) {
941 REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0);
942 return false;
943 }
944 current_mode = dpp20_get_shaper_current(dpp_base);
945
946 if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
947 next_mode = LUT_RAM_B;
948 else
949 next_mode = LUT_RAM_A;
950
951 dpp20_configure_shaper_lut(dpp_base, is_ram_a: next_mode == LUT_RAM_A);
952
953 if (next_mode == LUT_RAM_A)
954 dpp20_program_shaper_luta_settings(dpp_base, params);
955 else
956 dpp20_program_shaper_lutb_settings(dpp_base, params);
957
958 dpp20_program_shaper_lut(
959 dpp_base, rgb: params->rgb_resulted, num: params->hw_points_num);
960
961 REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
962
963 return true;
964
965}
966
967static enum dc_lut_mode get3dlut_config(
968 struct dpp *dpp_base,
969 bool *is_17x17x17,
970 bool *is_12bits_color_channel)
971{
972 uint32_t i_mode, i_enable_10bits, lut_size;
973 enum dc_lut_mode mode;
974 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
975
976 REG_GET_2(CM_3DLUT_READ_WRITE_CONTROL,
977 CM_3DLUT_CONFIG_STATUS, &i_mode,
978 CM_3DLUT_30BIT_EN, &i_enable_10bits);
979
980 switch (i_mode) {
981 case 0:
982 mode = LUT_BYPASS;
983 break;
984 case 1:
985 mode = LUT_RAM_A;
986 break;
987 case 2:
988 mode = LUT_RAM_B;
989 break;
990 default:
991 mode = LUT_BYPASS;
992 break;
993 }
994 if (i_enable_10bits > 0)
995 *is_12bits_color_channel = false;
996 else
997 *is_12bits_color_channel = true;
998
999 REG_GET(CM_3DLUT_MODE, CM_3DLUT_SIZE, &lut_size);
1000
1001 if (lut_size == 0)
1002 *is_17x17x17 = true;
1003 else
1004 *is_17x17x17 = false;
1005
1006 return mode;
1007}
1008/*
1009 * select ramA or ramB, or bypass
1010 * select color channel size 10 or 12 bits
1011 * select 3dlut size 17x17x17 or 9x9x9
1012 */
1013static void dpp20_set_3dlut_mode(
1014 struct dpp *dpp_base,
1015 enum dc_lut_mode mode,
1016 bool is_color_channel_12bits,
1017 bool is_lut_size17x17x17)
1018{
1019 uint32_t lut_mode;
1020 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1021
1022 if (mode == LUT_BYPASS)
1023 lut_mode = 0;
1024 else if (mode == LUT_RAM_A)
1025 lut_mode = 1;
1026 else
1027 lut_mode = 2;
1028
1029 REG_UPDATE_2(CM_3DLUT_MODE,
1030 CM_3DLUT_MODE, lut_mode,
1031 CM_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
1032}
1033
1034static void dpp20_select_3dlut_ram(
1035 struct dpp *dpp_base,
1036 enum dc_lut_mode mode,
1037 bool is_color_channel_12bits)
1038{
1039 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1040
1041 REG_UPDATE_2(CM_3DLUT_READ_WRITE_CONTROL,
1042 CM_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
1043 CM_3DLUT_30BIT_EN,
1044 is_color_channel_12bits == true ? 0:1);
1045}
1046
1047
1048
1049static void dpp20_set3dlut_ram12(
1050 struct dpp *dpp_base,
1051 const struct dc_rgb *lut,
1052 uint32_t entries)
1053{
1054 uint32_t i, red, green, blue, red1, green1, blue1;
1055 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1056
1057 for (i = 0 ; i < entries; i += 2) {
1058 red = lut[i].red<<4;
1059 green = lut[i].green<<4;
1060 blue = lut[i].blue<<4;
1061 red1 = lut[i+1].red<<4;
1062 green1 = lut[i+1].green<<4;
1063 blue1 = lut[i+1].blue<<4;
1064
1065 REG_SET_2(CM_3DLUT_DATA, 0,
1066 CM_3DLUT_DATA0, red,
1067 CM_3DLUT_DATA1, red1);
1068
1069 REG_SET_2(CM_3DLUT_DATA, 0,
1070 CM_3DLUT_DATA0, green,
1071 CM_3DLUT_DATA1, green1);
1072
1073 REG_SET_2(CM_3DLUT_DATA, 0,
1074 CM_3DLUT_DATA0, blue,
1075 CM_3DLUT_DATA1, blue1);
1076
1077 }
1078}
1079
1080/*
1081 * load selected lut with 10 bits color channels
1082 */
1083static void dpp20_set3dlut_ram10(
1084 struct dpp *dpp_base,
1085 const struct dc_rgb *lut,
1086 uint32_t entries)
1087{
1088 uint32_t i, red, green, blue, value;
1089 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1090
1091 for (i = 0; i < entries; i++) {
1092 red = lut[i].red;
1093 green = lut[i].green;
1094 blue = lut[i].blue;
1095
1096 value = (red<<20) | (green<<10) | blue;
1097
1098 REG_SET(CM_3DLUT_DATA_30BIT, 0, CM_3DLUT_DATA_30BIT, value);
1099 }
1100
1101}
1102
1103
1104static void dpp20_select_3dlut_ram_mask(
1105 struct dpp *dpp_base,
1106 uint32_t ram_selection_mask)
1107{
1108 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1109
1110 REG_UPDATE(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK,
1111 ram_selection_mask);
1112 REG_SET(CM_3DLUT_INDEX, 0, CM_3DLUT_INDEX, 0);
1113}
1114
1115bool dpp20_program_3dlut(
1116 struct dpp *dpp_base,
1117 struct tetrahedral_params *params)
1118{
1119 enum dc_lut_mode mode;
1120 bool is_17x17x17;
1121 bool is_12bits_color_channel;
1122 struct dc_rgb *lut0;
1123 struct dc_rgb *lut1;
1124 struct dc_rgb *lut2;
1125 struct dc_rgb *lut3;
1126 int lut_size0;
1127 int lut_size;
1128
1129 if (params == NULL) {
1130 dpp20_set_3dlut_mode(dpp_base, mode: LUT_BYPASS, is_color_channel_12bits: false, is_lut_size17x17x17: false);
1131 return false;
1132 }
1133 mode = get3dlut_config(dpp_base, is_17x17x17: &is_17x17x17, is_12bits_color_channel: &is_12bits_color_channel);
1134
1135 if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1136 mode = LUT_RAM_A;
1137 else
1138 mode = LUT_RAM_B;
1139
1140 is_17x17x17 = !params->use_tetrahedral_9;
1141 is_12bits_color_channel = params->use_12bits;
1142 if (is_17x17x17) {
1143 lut0 = params->tetrahedral_17.lut0;
1144 lut1 = params->tetrahedral_17.lut1;
1145 lut2 = params->tetrahedral_17.lut2;
1146 lut3 = params->tetrahedral_17.lut3;
1147 lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1148 sizeof(params->tetrahedral_17.lut0[0]);
1149 lut_size = sizeof(params->tetrahedral_17.lut1)/
1150 sizeof(params->tetrahedral_17.lut1[0]);
1151 } else {
1152 lut0 = params->tetrahedral_9.lut0;
1153 lut1 = params->tetrahedral_9.lut1;
1154 lut2 = params->tetrahedral_9.lut2;
1155 lut3 = params->tetrahedral_9.lut3;
1156 lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1157 sizeof(params->tetrahedral_9.lut0[0]);
1158 lut_size = sizeof(params->tetrahedral_9.lut1)/
1159 sizeof(params->tetrahedral_9.lut1[0]);
1160 }
1161
1162 dpp20_select_3dlut_ram(dpp_base, mode,
1163 is_color_channel_12bits: is_12bits_color_channel);
1164 dpp20_select_3dlut_ram_mask(dpp_base, ram_selection_mask: 0x1);
1165 if (is_12bits_color_channel)
1166 dpp20_set3dlut_ram12(dpp_base, lut: lut0, entries: lut_size0);
1167 else
1168 dpp20_set3dlut_ram10(dpp_base, lut: lut0, entries: lut_size0);
1169
1170 dpp20_select_3dlut_ram_mask(dpp_base, ram_selection_mask: 0x2);
1171 if (is_12bits_color_channel)
1172 dpp20_set3dlut_ram12(dpp_base, lut: lut1, entries: lut_size);
1173 else
1174 dpp20_set3dlut_ram10(dpp_base, lut: lut1, entries: lut_size);
1175
1176 dpp20_select_3dlut_ram_mask(dpp_base, ram_selection_mask: 0x4);
1177 if (is_12bits_color_channel)
1178 dpp20_set3dlut_ram12(dpp_base, lut: lut2, entries: lut_size);
1179 else
1180 dpp20_set3dlut_ram10(dpp_base, lut: lut2, entries: lut_size);
1181
1182 dpp20_select_3dlut_ram_mask(dpp_base, ram_selection_mask: 0x8);
1183 if (is_12bits_color_channel)
1184 dpp20_set3dlut_ram12(dpp_base, lut: lut3, entries: lut_size);
1185 else
1186 dpp20_set3dlut_ram10(dpp_base, lut: lut3, entries: lut_size);
1187
1188
1189 dpp20_set_3dlut_mode(dpp_base, mode, is_color_channel_12bits: is_12bits_color_channel,
1190 is_lut_size17x17x17: is_17x17x17);
1191
1192 return true;
1193}
1194
1195void dpp2_set_hdr_multiplier(
1196 struct dpp *dpp_base,
1197 uint32_t multiplier)
1198{
1199 struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1200
1201 REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
1202}
1203

source code of linux/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c