xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/chip/vpe10/vpe10_dpp_cm.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 
2 #include "vpe_priv.h"
3 #include "reg_helper.h"
4 #include "vpe10/inc/vpe10_cm_common.h"
5 #include "vpe10_dpp.h"
6 #include "conversion.h"
7 #define CTX      vpe10_dpp
8 #define CTX_BASE dpp
9 
vpe10_enable_cm_block(struct dpp * dpp)10 static void vpe10_enable_cm_block(struct dpp *dpp)
11 {
12     unsigned int cm_bypass_mode = 0;
13 
14     PROGRAM_ENTRY();
15 
16     // debug option: put CM in bypass mode
17     if (vpe_priv->init.debug.cm_in_bypass)
18         cm_bypass_mode = 1;
19 
20     REG_SET(VPCM_CONTROL, 0, VPCM_BYPASS, cm_bypass_mode);
21 }
22 
vpe10_power_on_gamcor_lut(struct dpp * dpp,bool power_on)23 static void vpe10_power_on_gamcor_lut(struct dpp *dpp, bool power_on)
24 {
25     PROGRAM_ENTRY();
26 
27     if (vpe_priv->init.debug.enable_mem_low_power.bits.cm) {
28         if (power_on) {
29             REG_SET_2(VPCM_MEM_PWR_CTRL, REG_DEFAULT(VPCM_MEM_PWR_CTRL), GAMCOR_MEM_PWR_DIS, 0,
30                 GAMCOR_MEM_PWR_FORCE, 0);
31 
32             // two dummy updates (10-15clks each) for wake up delay
33             REG_SET_2(VPCM_MEM_PWR_CTRL, REG_DEFAULT(VPCM_MEM_PWR_CTRL), GAMCOR_MEM_PWR_DIS, 0,
34                 GAMCOR_MEM_PWR_FORCE, 0);
35             REG_SET_2(VPCM_MEM_PWR_CTRL, REG_DEFAULT(VPCM_MEM_PWR_CTRL), GAMCOR_MEM_PWR_DIS, 0,
36                 GAMCOR_MEM_PWR_FORCE, 0);
37         } else {
38             REG_SET_2(VPCM_MEM_PWR_CTRL, REG_DEFAULT(VPCM_MEM_PWR_CTRL), GAMCOR_MEM_PWR_DIS, 0,
39                 GAMCOR_MEM_PWR_FORCE, 3);
40         }
41     } else {
42         REG_SET_2(VPCM_MEM_PWR_CTRL, REG_DEFAULT(VPCM_MEM_PWR_CTRL), GAMCOR_MEM_PWR_DIS,
43             power_on == true ? 1 : 0, GAMCOR_MEM_PWR_FORCE, 0);
44     }
45 }
46 
vpe10_configure_gamcor_lut(struct dpp * dpp)47 static void vpe10_configure_gamcor_lut(struct dpp *dpp)
48 {
49     PROGRAM_ENTRY();
50 
51     REG_SET(VPCM_GAMCOR_LUT_CONTROL, 0, VPCM_GAMCOR_LUT_WRITE_COLOR_MASK, 7);
52     REG_SET(VPCM_GAMCOR_LUT_INDEX, 0, VPCM_GAMCOR_LUT_INDEX, 0);
53 }
54 
vpe10_dpp_gamcor_reg_field(struct dpp * dpp,struct vpe10_xfer_func_reg * reg)55 static void vpe10_dpp_gamcor_reg_field(struct dpp *dpp, struct vpe10_xfer_func_reg *reg)
56 {
57     struct vpe10_dpp *vpe10_dpp = (struct vpe10_dpp *)dpp;
58 
59     reg->shifts.field_region_start_base =
60         vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
61     reg->masks.field_region_start_base = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
62     reg->shifts.field_offset           = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_OFFSET_B;
63     reg->masks.field_offset            = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_OFFSET_B;
64 
65     reg->shifts.exp_region0_lut_offset = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
66     reg->masks.exp_region0_lut_offset  = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
67     reg->shifts.exp_region0_num_segments =
68         vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
69     reg->masks.exp_region0_num_segments =
70         vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
71     reg->shifts.exp_region1_lut_offset = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
72     reg->masks.exp_region1_lut_offset  = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
73     reg->shifts.exp_region1_num_segments =
74         vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
75     reg->masks.exp_region1_num_segments =
76         vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
77 
78     reg->shifts.field_region_end       = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_END_B;
79     reg->masks.field_region_end        = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_END_B;
80     reg->shifts.field_region_end_slope = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
81     reg->masks.field_region_end_slope  = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
82     reg->shifts.field_region_end_base  = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
83     reg->masks.field_region_end_base   = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
84     reg->shifts.field_region_linear_slope =
85         vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
86     reg->masks.field_region_linear_slope =
87         vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
88     reg->shifts.exp_region_start = vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_START_B;
89     reg->masks.exp_region_start  = vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_START_B;
90     reg->shifts.exp_region_start_segment =
91         vpe10_dpp->shift->VPCM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
92     reg->masks.exp_region_start_segment =
93         vpe10_dpp->mask->VPCM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
94 }
95 
vpe10_dpp_program_gammcor_lut(struct dpp * dpp,const struct pwl_result_data * rgb,uint32_t num)96 static void vpe10_dpp_program_gammcor_lut(
97     struct dpp *dpp, const struct pwl_result_data *rgb, uint32_t num)
98 {
99     uint32_t last_base_value_red   = rgb[num].red_reg;
100     uint32_t last_base_value_green = rgb[num].blue_reg;
101     uint32_t last_base_value_blue  = rgb[num].green_reg;
102 
103     PROGRAM_ENTRY();
104 
105     /*fill in the LUT with all base values to be used by pwl module
106      * HW auto increments the LUT index: back-to-back write
107      */
108     if (vpe_is_rgb_equal(rgb, num)) {
109         vpe10_cm_helper_program_pwl(config_writer, rgb, last_base_value_red, num,
110             REG_OFFSET(VPCM_GAMCOR_LUT_DATA), REG_FIELD_SHIFT(VPCM_GAMCOR_LUT_DATA),
111             REG_FIELD_MASK(VPCM_GAMCOR_LUT_DATA), CM_PWL_R);
112     } else {
113         REG_UPDATE(VPCM_GAMCOR_LUT_CONTROL, VPCM_GAMCOR_LUT_WRITE_COLOR_MASK, 4);
114 
115         vpe10_cm_helper_program_pwl(config_writer, rgb, last_base_value_red, num,
116             REG_OFFSET(VPCM_GAMCOR_LUT_DATA), REG_FIELD_SHIFT(VPCM_GAMCOR_LUT_DATA),
117             REG_FIELD_MASK(VPCM_GAMCOR_LUT_DATA), CM_PWL_R);
118 
119         REG_SET(VPCM_GAMCOR_LUT_INDEX, 0, VPCM_GAMCOR_LUT_INDEX, 0);
120         REG_UPDATE(VPCM_GAMCOR_LUT_CONTROL, VPCM_GAMCOR_LUT_WRITE_COLOR_MASK, 2);
121 
122         vpe10_cm_helper_program_pwl(config_writer, rgb, last_base_value_green, num,
123             REG_OFFSET(VPCM_GAMCOR_LUT_DATA), REG_FIELD_SHIFT(VPCM_GAMCOR_LUT_DATA),
124             REG_FIELD_MASK(VPCM_GAMCOR_LUT_DATA), CM_PWL_G);
125 
126         REG_SET(VPCM_GAMCOR_LUT_INDEX, 0, VPCM_GAMCOR_LUT_INDEX, 0);
127         REG_UPDATE(VPCM_GAMCOR_LUT_CONTROL, VPCM_GAMCOR_LUT_WRITE_COLOR_MASK, 1);
128 
129         vpe10_cm_helper_program_pwl(config_writer, rgb, last_base_value_blue, num,
130             REG_OFFSET(VPCM_GAMCOR_LUT_DATA), REG_FIELD_SHIFT(VPCM_GAMCOR_LUT_DATA),
131             REG_FIELD_MASK(VPCM_GAMCOR_LUT_DATA), CM_PWL_B);
132     }
133 }
134 
vpe10_dpp_program_gamcor_lut(struct dpp * dpp,const struct pwl_params * params)135 static void vpe10_dpp_program_gamcor_lut(struct dpp *dpp, const struct pwl_params *params)
136 {
137     struct vpe10_xfer_func_reg gam_regs = {0};
138 
139     PROGRAM_ENTRY();
140 
141     vpe10_enable_cm_block(dpp);
142 
143     if (dpp->vpe_priv->init.debug.bypass_gamcor || params == NULL) {
144         // bypass
145         REG_SET(VPCM_GAMCOR_CONTROL, 0, VPCM_GAMCOR_MODE, 0);
146         vpe10_power_on_gamcor_lut(dpp, false);
147         return;
148     }
149 
150     vpe10_power_on_gamcor_lut(dpp, true);
151     vpe10_configure_gamcor_lut(dpp);
152 
153     REG_SET(VPCM_GAMCOR_CONTROL, 0, VPCM_GAMCOR_MODE, 2); // programmable RAM
154 
155     gam_regs.start_cntl_b       = REG_OFFSET(VPCM_GAMCOR_RAMA_START_CNTL_B);
156     gam_regs.start_cntl_g       = REG_OFFSET(VPCM_GAMCOR_RAMA_START_CNTL_G);
157     gam_regs.start_cntl_r       = REG_OFFSET(VPCM_GAMCOR_RAMA_START_CNTL_R);
158     gam_regs.start_slope_cntl_b = REG_OFFSET(VPCM_GAMCOR_RAMA_START_SLOPE_CNTL_B);
159     gam_regs.start_slope_cntl_g = REG_OFFSET(VPCM_GAMCOR_RAMA_START_SLOPE_CNTL_G);
160     gam_regs.start_slope_cntl_r = REG_OFFSET(VPCM_GAMCOR_RAMA_START_SLOPE_CNTL_R);
161     gam_regs.start_end_cntl1_b  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL1_B);
162     gam_regs.start_end_cntl2_b  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL2_B);
163     gam_regs.start_end_cntl1_g  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL1_G);
164     gam_regs.start_end_cntl2_g  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL2_G);
165     gam_regs.start_end_cntl1_r  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL1_R);
166     gam_regs.start_end_cntl2_r  = REG_OFFSET(VPCM_GAMCOR_RAMA_END_CNTL2_R);
167     gam_regs.region_start       = REG_OFFSET(VPCM_GAMCOR_RAMA_REGION_0_1);
168     gam_regs.region_end         = REG_OFFSET(VPCM_GAMCOR_RAMA_REGION_32_33);
169     gam_regs.offset_b           = REG_OFFSET(VPCM_GAMCOR_RAMA_OFFSET_B);
170     gam_regs.offset_g           = REG_OFFSET(VPCM_GAMCOR_RAMA_OFFSET_G);
171     gam_regs.offset_r           = REG_OFFSET(VPCM_GAMCOR_RAMA_OFFSET_R);
172     gam_regs.start_base_cntl_b  = REG_OFFSET(VPCM_GAMCOR_RAMA_START_BASE_CNTL_B);
173     gam_regs.start_base_cntl_g  = REG_OFFSET(VPCM_GAMCOR_RAMA_START_BASE_CNTL_G);
174     gam_regs.start_base_cntl_r  = REG_OFFSET(VPCM_GAMCOR_RAMA_START_BASE_CNTL_R);
175 
176     vpe10_dpp_gamcor_reg_field(dpp, &gam_regs);
177 
178     vpe10_cm_helper_program_gamcor_xfer_func(config_writer, params, &gam_regs);
179     vpe10_dpp_program_gammcor_lut(dpp, params->rgb_resulted, params->hw_points_num);
180 }
181 
vpe10_dpp_program_input_transfer_func(struct dpp * dpp,struct transfer_func * input_tf)182 void vpe10_dpp_program_input_transfer_func(struct dpp *dpp, struct transfer_func *input_tf)
183 {
184     struct pwl_params *params = NULL;
185 
186     PROGRAM_ENTRY();
187 
188     // There should always have input_tf
189     VPE_ASSERT(input_tf);
190     // Only accept either DISTRIBUTED_POINTS or BYPASS
191     // No support for PREDEFINED case
192     VPE_ASSERT(input_tf->type == TF_TYPE_DISTRIBUTED_POINTS || input_tf->type == TF_TYPE_BYPASS);
193 
194     // VPE always do NL scaling using gamcor, thus skipping dgam (default bypass)
195     // dpp->funcs->program_pre_dgam(dpp, tf);
196     if (input_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
197         vpe10_cm_helper_translate_curve_to_degamma_hw_format(input_tf, &dpp->degamma_params);
198         params = &dpp->degamma_params;
199     }
200     vpe10_dpp_program_gamcor_lut(dpp, params);
201 }
202 
vpe10_dpp_program_gamut_remap(struct dpp * dpp,struct colorspace_transform * gamut_remap)203 void vpe10_dpp_program_gamut_remap(struct dpp *dpp, struct colorspace_transform *gamut_remap)
204 {
205     struct color_matrices_reg gam_regs;
206     uint16_t                  arr_reg_val[12];
207 
208     PROGRAM_ENTRY();
209 
210     if (!gamut_remap || !gamut_remap->enable_remap ||
211         dpp->vpe_priv->init.debug.bypass_dpp_gamut_remap) {
212         REG_SET(VPCM_GAMUT_REMAP_CONTROL, 0, VPCM_GAMUT_REMAP_MODE, 0);
213         return;
214     }
215 
216     gam_regs.shifts.csc_c11 = REG_FIELD_SHIFT(VPCM_GAMUT_REMAP_C11);
217     gam_regs.masks.csc_c11  = REG_FIELD_MASK(VPCM_GAMUT_REMAP_C11);
218     gam_regs.shifts.csc_c12 = REG_FIELD_SHIFT(VPCM_GAMUT_REMAP_C12);
219     gam_regs.masks.csc_c12  = REG_FIELD_MASK(VPCM_GAMUT_REMAP_C12);
220     gam_regs.csc_c11_c12    = REG_OFFSET(VPCM_GAMUT_REMAP_C11_C12);
221     gam_regs.csc_c33_c34    = REG_OFFSET(VPCM_GAMUT_REMAP_C33_C34);
222 
223     conv_convert_float_matrix(arr_reg_val, gamut_remap->matrix, 12);
224 
225     vpe10_cm_helper_program_color_matrices(config_writer, arr_reg_val, &gam_regs);
226 
227     REG_SET(VPCM_GAMUT_REMAP_CONTROL, 0, VPCM_GAMUT_REMAP_MODE, 1);
228 }
229 
230 /*program post scaler scs block in dpp CM*/
vpe10_dpp_program_post_csc(struct dpp * dpp,enum color_space color_space,enum input_csc_select input_select,struct vpe_csc_matrix * input_cs)231 void vpe10_dpp_program_post_csc(struct dpp *dpp, enum color_space color_space,
232     enum input_csc_select input_select, struct vpe_csc_matrix *input_cs)
233 {
234     PROGRAM_ENTRY();
235     int             i;
236     int             arr_size = sizeof(vpe_input_csc_matrix_fixed) / sizeof(struct vpe_csc_matrix);
237     const uint16_t *regval   = NULL;
238     struct color_matrices_reg gam_regs;
239 
240     if (input_select == INPUT_CSC_SELECT_BYPASS || dpp->vpe_priv->init.debug.bypass_post_csc) {
241         REG_SET(VPCM_POST_CSC_CONTROL, 0, VPCM_POST_CSC_MODE, 0);
242         return;
243     }
244 
245     if (input_cs == NULL) {
246         for (i = 0; i < arr_size; i++)
247             if (vpe_input_csc_matrix_fixed[i].cs == color_space) {
248                 regval = vpe_input_csc_matrix_fixed[i].regval;
249                 break;
250             }
251 
252         if (regval == NULL) {
253             VPE_ASSERT(0);
254             return;
255         }
256     } else {
257         regval = input_cs->regval;
258     }
259 
260     /* Always use the only one set of CSC matrix
261      */
262 
263     gam_regs.shifts.csc_c11 = REG_FIELD_SHIFT(VPCM_POST_CSC_C11);
264     gam_regs.masks.csc_c11  = REG_FIELD_MASK(VPCM_POST_CSC_C11);
265     gam_regs.shifts.csc_c12 = REG_FIELD_SHIFT(VPCM_POST_CSC_C12);
266     gam_regs.masks.csc_c12  = REG_FIELD_MASK(VPCM_POST_CSC_C12);
267     gam_regs.csc_c11_c12    = REG_OFFSET(VPCM_POST_CSC_C11_C12);
268     gam_regs.csc_c33_c34    = REG_OFFSET(VPCM_POST_CSC_C33_C34);
269 
270     vpe10_cm_helper_program_color_matrices(config_writer, regval, &gam_regs);
271 
272     REG_SET(VPCM_POST_CSC_CONTROL, 0, VPCM_POST_CSC_MODE, input_select);
273 }
274 
vpe10_dpp_set_hdr_multiplier(struct dpp * dpp,uint32_t multiplier)275 void vpe10_dpp_set_hdr_multiplier(struct dpp *dpp, uint32_t multiplier)
276 {
277     PROGRAM_ENTRY();
278 
279     REG_SET(VPCM_HDR_MULT_COEF, REG_DEFAULT(VPCM_HDR_MULT_COEF), VPCM_HDR_MULT_COEF, multiplier);
280 }
281