xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/algos/accm/rk_aiq_accm_algo_v1.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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