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