1 /*
2 * rk_aiq_accm_algo_v1.cpp
3
4 * for rockchip v2.0.0
5 *
6 * Copyright (c) 2019 Rockchip Corporation
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21 /* for rockchip v2.0.0*/
22
23 #include "accm/rk_aiq_accm_algo_com.h"
24 #include "xcam_log.h"
25 #include "interpolation.h"
26
27 RKAIQ_BEGIN_DECLARE
28
CCMV1PrintReg(const rk_aiq_ccm_cfg_t * hw_param)29 void CCMV1PrintReg(const rk_aiq_ccm_cfg_t* hw_param) {
30 LOG1_ACCM(
31 " CCM V1 reg values: "
32 " sw_ccm_highy_adjust_dis 0"
33 " sw_ccm_en_i %d"
34 " sw_ccm_coeff ([%f,%f,%f,%f,%f,%f,%f,%f,%f]-E)X128"
35 " sw_ccm_offset [%f,%f,%f]"
36 " sw_ccm_coeff_y [%f,%f,%f]"
37 " sw_ccm_alp_y [%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f]"
38 " sw_ccm_bound_bit %f",
39 hw_param->ccmEnable,
40 hw_param->matrix[0], hw_param->matrix[1], hw_param->matrix[2],
41 hw_param->matrix[3], hw_param->matrix[4], hw_param->matrix[5],
42 hw_param->matrix[6], hw_param->matrix[7], hw_param->matrix[8],
43 hw_param->offs[0], hw_param->offs[1], hw_param->offs[2],
44 hw_param->rgb2y_para[0], hw_param->rgb2y_para[1], hw_param->rgb2y_para[2],
45 hw_param->alp_y[0], hw_param->alp_y[1], hw_param->alp_y[2], hw_param->alp_y[3],
46 hw_param->alp_y[4], hw_param->alp_y[5], hw_param->alp_y[6], hw_param->alp_y[7],
47 hw_param->alp_y[8], hw_param->alp_y[9], hw_param->alp_y[10],hw_param->alp_y[11],
48 hw_param->alp_y[12],hw_param->alp_y[13],hw_param->alp_y[14],hw_param->alp_y[15],
49 hw_param->alp_y[16], hw_param->bound_bit);
50 }
51
CCMV1PrintDBG(const accm_context_t * accm_context)52 void CCMV1PrintDBG(const accm_context_t* accm_context) {
53 const CalibDbV2_Ccm_Para_V2_t* pCcm = accm_context->ccm_v1;
54 const float *pMatrixUndamped = accm_context->accmRest.undampedCcmMatrix;
55 const float *pOffsetUndamped = accm_context->accmRest.undampedCcOffset;
56 const float *pMatrixDamped = accm_context->ccmHwConf.matrix;
57 const float *pOffsetDamped = accm_context->ccmHwConf.offs;
58
59 LOG1_ACCM("Illu Probability Estimation Enable: %d"
60 "color_inhibition sensorGain: %f,%f,%f,%f "
61 "color_inhibition level: %f,%f,%f,%f"
62 "color_saturation sensorGain: %f,%f,%f,%f "
63 "color_saturation level: %f,%f,%f,%f"
64 "dampfactor: %f"
65 " undampedCcmMatrix: %f,%f,%f,%f,%f,%f,%f,%f,%f"
66 " undampedCcOffset: %f,%f,%f "
67 " dampedCcmMatrix: %f,%f,%f,%f,%f,%f,%f,%f,%f"
68 " dampedCcOffset:%f,%f,%f",
69 pCcm->TuningPara.illu_estim.interp_enable,
70 accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[0],
71 accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[1],
72 accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[2],
73 accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[3],
74 accm_context->mCurAtt.stAuto.color_inhibition.level[0],
75 accm_context->mCurAtt.stAuto.color_inhibition.level[1],
76 accm_context->mCurAtt.stAuto.color_inhibition.level[2],
77 accm_context->mCurAtt.stAuto.color_inhibition.level[3],
78 accm_context->mCurAtt.stAuto.color_saturation.sensorGain[0],
79 accm_context->mCurAtt.stAuto.color_saturation.sensorGain[1],
80 accm_context->mCurAtt.stAuto.color_saturation.sensorGain[2],
81 accm_context->mCurAtt.stAuto.color_saturation.sensorGain[3],
82 accm_context->mCurAtt.stAuto.color_saturation.level[0],
83 accm_context->mCurAtt.stAuto.color_saturation.level[1],
84 accm_context->mCurAtt.stAuto.color_saturation.level[2],
85 accm_context->mCurAtt.stAuto.color_saturation.level[3],
86 pCcm->TuningPara.damp_enable,
87 pMatrixUndamped[0], pMatrixUndamped[1], pMatrixUndamped[2],
88 pMatrixUndamped[3], pMatrixUndamped[4], pMatrixUndamped[5],
89 pMatrixUndamped[6], pMatrixUndamped[7], pMatrixUndamped[8],
90 pOffsetUndamped[0], pOffsetUndamped[1], pOffsetUndamped[2],
91 pMatrixDamped[0], pMatrixDamped[1], pMatrixDamped[2],
92 pMatrixDamped[3], pMatrixDamped[4], pMatrixDamped[5],
93 pMatrixDamped[6], pMatrixDamped[7], pMatrixDamped[8],
94 pOffsetDamped[0], pOffsetDamped[1], pOffsetDamped[2]);
95
96 }
97
AccmAutoConfig(accm_handle_t hAccm)98 XCamReturn AccmAutoConfig
99 (
100 accm_handle_t hAccm
101 ) {
102
103 LOG1_ACCM("%s: (enter)\n", __FUNCTION__);
104
105 XCamReturn ret = XCAM_RETURN_NO_ERROR;
106
107 if (hAccm == NULL) {
108 return XCAM_RETURN_ERROR_PARAM;
109 }
110
111 const CalibDbV2_Ccm_Para_V2_t * pCcm = NULL;
112 float sensorGain = hAccm->accmSwInfo.sensorGain;
113 float fSaturation = 0;
114 pCcm = hAccm->ccm_v1;
115 if (hAccm->update) {
116 if (pCcm->TuningPara.illu_estim.interp_enable) {
117 hAccm->isReCal_ = true;
118 ret = interpCCMbywbgain(&pCcm->TuningPara, hAccm, fSaturation);
119 RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR);
120 } else {
121 ret = selectCCM(&pCcm->TuningPara, hAccm, fSaturation);
122 RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR);
123 }
124 }
125 if (hAccm->update || hAccm->updateAtt) {
126
127 //4) calc scale for y_alpha_curve
128 float fScale = 1.0;
129 #if 1
130 //real use
131 interpolation(pCcm->lumaCCM.gain_alphaScale_curve.gain,
132 pCcm->lumaCCM.gain_alphaScale_curve.scale,
133 9,
134 sensorGain, &fScale);
135 #else
136 //for test, to be same with demo
137 for( int i = 0; i < 9; i++)
138 {
139 int j = uint16_t(sensorGain);
140 j = (j > (1 << 8)) ? (1 << 8) : j;
141
142 if(j <= (1 << i))
143 {
144 fScale = pCcm->lumaCCM.gain_alphaScale_curve.scale[i];
145 break;
146 }
147 }
148 #endif
149 // 5) color inhibition adjust for api
150 interpolation(hAccm->mCurAtt.stAuto.color_inhibition.sensorGain,
151 hAccm->mCurAtt.stAuto.color_inhibition.level,
152 RK_AIQ_ACCM_COLOR_GAIN_NUM,
153 sensorGain, &hAccm->accmRest.color_inhibition_level);
154
155 if(hAccm->accmRest.color_inhibition_level > 100 || hAccm->accmRest.color_inhibition_level < 0) {
156 LOGE_ACCM("flevel2: %f is out of range [0 100]\n", hAccm->accmRest.color_inhibition_level);
157 return XCAM_RETURN_ERROR_PARAM;
158 }
159
160 fScale *= (100 - hAccm->accmRest.color_inhibition_level) / 100;
161
162 // 6) saturation adjust for api
163 float saturation_level = 100;
164 interpolation(hAccm->mCurAtt.stAuto.color_saturation.sensorGain,
165 hAccm->mCurAtt.stAuto.color_saturation.level,
166 RK_AIQ_ACCM_COLOR_GAIN_NUM,
167 sensorGain, &saturation_level );
168
169 if(saturation_level > 100 || saturation_level < 0) {
170 LOGE_ACCM("flevel1: %f is out of range [0 100]\n", saturation_level);
171 return XCAM_RETURN_ERROR_PARAM;
172 }
173
174 LOGD_ACCM("CcmProfile changed: %d, fScale: %f->%f, sat_level: %f->%f",
175 hAccm->isReCal_, hAccm->accmRest.fScale, fScale,
176 hAccm->accmRest.color_saturation_level, saturation_level);
177
178 hAccm->isReCal_ = hAccm->isReCal_ ||
179 fabs(fScale - hAccm->accmRest.fScale) > DIVMIN ||
180 fabs(saturation_level - hAccm->accmRest.color_saturation_level) > DIVMIN;
181
182 if (hAccm->isReCal_) {
183 hAccm->accmRest.fScale = fScale;
184 hAccm->accmRest.color_saturation_level = saturation_level;
185 Saturationadjust(fScale, saturation_level, hAccm->accmRest.undampedCcmMatrix);
186 LOGD_ACCM("Adjust ccm by sat: %d, undampedCcmMatrix[0]: %f",
187 hAccm->isReCal_, hAccm->accmRest.undampedCcmMatrix[0]);
188
189 for(int i = 0; i < CCM_CURVE_DOT_NUM; i++) { //set to ic to do bit check
190 hAccm->ccmHwConf.alp_y[i] = fScale * pCcm->lumaCCM.y_alpha_curve[i];
191 }
192 }
193 }
194 // 7) . Damping
195 float dampCoef = (pCcm->TuningPara.damp_enable && (hAccm->count > 1 || hAccm->invarMode > 0)) ? hAccm->accmSwInfo.awbIIRDampCoef : 0;
196 if (!hAccm->accmSwInfo.ccmConverged || hAccm->isReCal_) {
197 ret = Damping(dampCoef,
198 hAccm->accmRest.undampedCcmMatrix, hAccm->ccmHwConf.matrix,
199 hAccm->accmRest.undampedCcOffset, hAccm->ccmHwConf.offs,
200 &hAccm->accmSwInfo.ccmConverged);
201 hAccm->isReCal_ = true;
202 LOGD_ACCM("damping: %f, ccm coef[0]: %f->%f, ccm coef[8]: %f->%f \n",
203 dampCoef, hAccm->accmRest.undampedCcmMatrix[0], hAccm->ccmHwConf.matrix[0],
204 hAccm->accmRest.undampedCcmMatrix[8], hAccm->ccmHwConf.matrix[8]);
205 }
206
207 LOGD_ACCM("final isReCal_ = %d \n", hAccm->isReCal_);
208 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
209
210 return (ret);
211 }
212
AccmManualConfig(accm_handle_t hAccm)213 XCamReturn AccmManualConfig
214 (
215 accm_handle_t hAccm
216 ) {
217 LOG1_ACCM("%s: (enter)\n", __FUNCTION__);
218
219 XCamReturn ret = XCAM_RETURN_NO_ERROR;
220
221 memcpy(hAccm->ccmHwConf.matrix, hAccm->mCurAtt.stManual.ccMatrix, sizeof(hAccm->mCurAtt.stManual.ccMatrix));
222 memcpy(hAccm->ccmHwConf.offs, hAccm->mCurAtt.stManual.ccOffsets, sizeof(hAccm->mCurAtt.stManual.ccOffsets));
223 memcpy(hAccm->ccmHwConf.alp_y, hAccm->mCurAtt.stManual.y_alpha_curve, sizeof(hAccm->mCurAtt.stManual.y_alpha_curve));
224 hAccm->ccmHwConf.bound_bit = hAccm->mCurAtt.stManual.low_bound_pos_bit;
225 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
226 return ret;
227
228 }
229
AccmConfig(accm_handle_t hAccm)230 XCamReturn AccmConfig
231 (
232 accm_handle_t hAccm
233 ) {
234 LOG1_ACCM("%s: (enter)\n", __FUNCTION__);
235
236 XCamReturn ret = XCAM_RETURN_NO_ERROR;
237 LOGD_ACCM("%s: byPass: %d mode:%d updateAtt: %d \n", __FUNCTION__,
238 hAccm->mCurAtt.byPass, hAccm->mCurAtt.mode, hAccm->updateAtt);
239 if (hAccm->mCurAtt.byPass != true && hAccm->accmSwInfo.grayMode != true) {
240 hAccm->ccmHwConf.ccmEnable = true;
241 if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_AUTO) {
242 hAccm->update = JudgeCcmRes3aConverge(&hAccm->accmRest.res3a_info, &hAccm->accmSwInfo,
243 hAccm->ccm_v1->control.gain_tolerance,
244 hAccm->ccm_v1->control.wbgain_tolerance);
245 hAccm->update = hAccm->update || hAccm->calib_update;
246 LOGD_ACCM("%s: CCM update (gain/awbgain/calib): %d, CCM Converged: %d\n",
247 __FUNCTION__, hAccm->update, hAccm->accmSwInfo.ccmConverged);
248 if (hAccm->updateAtt || hAccm->update ||(!hAccm->accmSwInfo.ccmConverged)) {
249 AccmAutoConfig(hAccm);
250 CCMV1PrintDBG(hAccm);
251 }
252 } else if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_MANUAL) {
253 if (hAccm->updateAtt) {
254 AccmManualConfig(hAccm);
255 hAccm->isReCal_ = true;
256 }
257 } else {
258 LOGE_ACCM("%s: hAccm->mCurAtt.mode(%d) is invalid \n", __FUNCTION__, hAccm->mCurAtt.mode);
259 }
260 } else {
261 hAccm->ccmHwConf.ccmEnable = false;
262 // change to graymode / bypass by api/calib
263 hAccm->isReCal_ = hAccm->isReCal_ || hAccm->updateAtt || hAccm->calib_update;
264
265 }
266 hAccm->updateAtt = false;
267 hAccm->calib_update = false;
268 hAccm->count = ((hAccm->count + 2) > (65536)) ? 2 : (hAccm->count + 1);
269
270 CCMV1PrintReg(&hAccm->ccmHwConf);
271
272 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
273 return ret;
274
275 }
276
277 /**********************************
278 *Update CCM CalibV2 Para
279 * Prepare init
280 * Mode change: reinit
281 * Res change: continue
282 * Calib change: continue
283 ***************************************/
UpdateCcmCalibV2ParaV1(accm_handle_t hAccm)284 static XCamReturn UpdateCcmCalibV2ParaV1(accm_handle_t hAccm)
285 {
286 LOG1_ACCM("%s: (enter) \n", __FUNCTION__);
287 XCamReturn ret = XCAM_RETURN_NO_ERROR;
288
289 bool config_calib = !!(hAccm->accmSwInfo.prepare_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB);
290 const CalibDbV2_Ccm_Para_V2_t* calib_ccm = hAccm->ccm_v1;
291
292 if (!config_calib)
293 {
294 return(ret);
295 }
296
297 if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_AUTO) {
298 #if RKAIQ_ACCM_ILLU_VOTE
299 ReloadCCMCalibV2(hAccm, &calib_ccm->TuningPara);
300 #endif
301
302 ret = pCcmMatrixAll_init(hAccm, &calib_ccm->TuningPara);
303
304 hAccm->mCurAtt.byPass = !(calib_ccm->control.enable);
305
306 hAccm->ccmHwConf.bound_bit = calib_ccm->lumaCCM.low_bound_pos_bit;
307 memcpy(hAccm->ccmHwConf.rgb2y_para, calib_ccm->lumaCCM.rgb2y_para,
308 sizeof(calib_ccm->lumaCCM.rgb2y_para));
309 memcpy(hAccm->ccmHwConf.alp_y, calib_ccm->lumaCCM.y_alpha_curve, sizeof(hAccm->ccmHwConf.alp_y));
310
311 hAccm->accmSwInfo.ccmConverged = false;
312 hAccm->calib_update = true;
313 }
314
315 clear_list(&hAccm->accmRest.problist);
316
317 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
318 return(ret);
319 }
320
AccmInit(accm_handle_t * hAccm,const CamCalibDbV2Context_t * calibv2)321 XCamReturn AccmInit(accm_handle_t *hAccm, const CamCalibDbV2Context_t* calibv2)
322 {
323 LOGI_ACCM("%s: (enter)\n", __FUNCTION__);
324
325 XCamReturn ret = XCAM_RETURN_NO_ERROR;
326
327 if(calibv2 == NULL) {
328 return XCAM_RETURN_ERROR_PARAM;
329 }
330
331 const CalibDbV2_Ccm_Para_V2_t *calib_ccm =
332 (CalibDbV2_Ccm_Para_V2_t*)(CALIBDBV2_GET_MODULE_PTR((void*)calibv2, ccm_calib));
333 if (calib_ccm == NULL)
334 return XCAM_RETURN_ERROR_MEM;
335
336 *hAccm = (accm_context_t*)malloc(sizeof(accm_context_t));
337 accm_context_t* accm_context = *hAccm;
338 memset(accm_context, 0, sizeof(accm_context_t));
339
340 accm_context->accmSwInfo.sensorGain = 1.0;
341 accm_context->accmSwInfo.awbIIRDampCoef = 0;
342 accm_context->accmSwInfo.varianceLuma = 255;
343 accm_context->accmSwInfo.awbConverged = false;
344
345 accm_context->accmSwInfo.awbGain[0] = 1;
346 accm_context->accmSwInfo.awbGain[1] = 1;
347
348 accm_context->accmRest.res3a_info.sensorGain = 1.0;
349 accm_context->accmRest.res3a_info.awbGain[0] = 1.0;
350 accm_context->accmRest.res3a_info.awbGain[1] = 1.0;
351
352 accm_context->count = 0;
353 accm_context->isReCal_ = 1;
354 accm_context->invarMode = 1;
355
356 accm_context->accmSwInfo.prepare_type = RK_AIQ_ALGO_CONFTYPE_UPDATECALIB | RK_AIQ_ALGO_CONFTYPE_NEEDRESET;
357
358 // todo whm --- CalibDbV2_Ccm_Para
359 accm_context->ccm_v1 = calib_ccm;
360 accm_context->mCurAtt.mode = RK_AIQ_CCM_MODE_AUTO;
361 #if RKAIQ_ACCM_ILLU_VOTE
362 INIT_LIST_HEAD(&accm_context->accmRest.dominateIlluList);
363 #endif
364 INIT_LIST_HEAD(&accm_context->accmRest.problist);
365 ret = UpdateCcmCalibV2ParaV1(accm_context);
366
367 for(int i = 0; i < RK_AIQ_ACCM_COLOR_GAIN_NUM; i++) {
368 accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[i] = 1;
369 accm_context->mCurAtt.stAuto.color_inhibition.level[i] = 0;
370 accm_context->mCurAtt.stAuto.color_saturation.sensorGain[i] = 1;
371 accm_context->mCurAtt.stAuto.color_saturation.level[i] = 50;
372 }
373 accm_context->accmRest.fScale = 1;
374 accm_context->accmRest.color_inhibition_level = 0;
375 accm_context->accmRest.color_saturation_level = 100;
376
377 LOGI_ACCM("%s: (exit)\n", __FUNCTION__);
378 return(ret);
379 }
380
AccmRelease(accm_handle_t hAccm)381 XCamReturn AccmRelease(accm_handle_t hAccm)
382 {
383 LOGI_ACCM("%s: (enter)\n", __FUNCTION__);
384
385 XCamReturn ret = XCAM_RETURN_NO_ERROR;
386 #if RKAIQ_ACCM_ILLU_VOTE
387 clear_list(&hAccm->accmRest.dominateIlluList);
388 #endif
389 clear_list(&hAccm->accmRest.problist);
390 free(hAccm);
391 hAccm = NULL;
392
393 LOGI_ACCM("%s: (exit)\n", __FUNCTION__);
394 return(ret);
395
396 }
397
398 // todo whm
AccmPrepare(accm_handle_t hAccm)399 XCamReturn AccmPrepare(accm_handle_t hAccm)
400 {
401 LOGI_ACCM("%s: (enter)\n", __FUNCTION__);
402
403 XCamReturn ret = XCAM_RETURN_NO_ERROR;
404
405 ret = UpdateCcmCalibV2ParaV1(hAccm);
406 RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR);
407
408 LOGI_ACCM("%s: (exit)\n", __FUNCTION__);
409 return ret;
410 }
411
412
AccmPreProc(accm_handle_t hAccm)413 XCamReturn AccmPreProc(accm_handle_t hAccm)
414 {
415
416 LOG1_ACCM("%s: (enter)\n", __FUNCTION__);
417
418 XCamReturn ret = XCAM_RETURN_NO_ERROR;
419
420 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
421 return(ret);
422
423 }
AccmProcessing(accm_handle_t hAccm)424 XCamReturn AccmProcessing(accm_handle_t hAccm)
425 {
426 LOG1_ACCM("%s: (enter)\n", __FUNCTION__);
427
428 XCamReturn ret = XCAM_RETURN_NO_ERROR;
429
430 LOG1_ACCM("%s: (exit)\n", __FUNCTION__);
431 return(ret);
432 }
433
434
435
436
437 RKAIQ_END_DECLARE
438
439
440