1 /*
2 * rk_aiq_algo_aldch_itf.c
3 *
4 * Copyright (c) 2019 Rockchip Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include "aldch/rk_aiq_algo_aldch_itf.h"
21 #include "aldch/rk_aiq_types_aldch_algo_prvt.h"
22 #include "rk_aiq_algo_types.h"
23 #include "RkAiqCalibDbV2Helper.h"
24 #include "xcam_log.h"
25 #include "rk_aiq_ldch_generate_mesh.h"
26 #include "aldch/rk_aiq_uapi_aldch_v21_int.h"
27
28
29 RKAIQ_BEGIN_DECLARE
30
31 static const uint8_t default_bic_table[9][4] = {
32 {0x00, 0x80, 0x00, 0x00}, // table0: 0, 0, 128, 0
33 {0xfc, 0x7f, 0x05, 0x00}, // table1: 0, 5, 127, -4
34 {0xfa, 0x7b, 0x0c, 0xff}, // table2: -1, 12, 123, -6
35 {0xf8, 0x76, 0x14, 0xfe}, // table3: -2, 20, 118, -8
36 {0xf7, 0x6f, 0x1d, 0xfd}, // table4: -3, 29, 111, -9
37 {0xf7, 0x66, 0x27, 0xfc}, // table4: -4, 39, 102, -9
38 {0xf7, 0x5d, 0x32, 0xfa}, // table4: -6, 50, 93, -9
39 {0xf7, 0x53, 0x3d, 0xf9}, // table4: -7, 61, 83, -9
40 {0xf8, 0x48, 0x48, 0xf8}, // table4: -8, 72, 72, -8
41 };
42
43 static XCamReturn
updateCalibConfig(RkAiqAlgoCom * params)44 updateCalibConfig(RkAiqAlgoCom* params)
45 {
46 LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH;
47 LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
48 RkAiqAlgoConfigAldch* rkaiqAldchConfig = (RkAiqAlgoConfigAldch*)params;
49
50 CalibDbV2_LDCH_t* calib_ldch_db =
51 (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(rkaiqAldchConfig->com.u.prepare.calibv2, aldch));
52 CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param;
53
54 ldchCtx->camCoeff.cx = calib_ldch->light_center[0];
55 ldchCtx->camCoeff.cy = calib_ldch->light_center[1];
56 ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0];
57 ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1];
58 ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2];
59 ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3];
60 memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile));
61
62 if (calib_ldch->ldch_en) {
63 if ((!ldchCtx->ldch_en || calib_ldch->correct_level != hLDCH->correct_level) && \
64 ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
65 if (aiqGenLdchMeshInit(hLDCH) != XCAM_RETURN_NO_ERROR) {
66 LOGE_ALDCH("Failed to init gen mesh");
67 return XCAM_RETURN_ERROR_FAILED;
68 }
69
70 bool success = aiqGenMesh(hLDCH, calib_ldch->correct_level);
71 if (!success) {
72 LOGE_ALDCH("lut is not exist");
73 put_ldch_buf(hLDCH);
74 return XCAM_RETURN_ERROR_PARAM;
75 }
76
77 if (ldchCtx->ldch_mem_info)
78 hLDCH->ready_lut_mem_fd = ldchCtx->ldch_mem_info->fd;
79
80 ldchCtx->isLutUpdated.store(true, std::memory_order_release);
81 }
82 }
83
84 ldchCtx->user_config.en = calib_ldch->ldch_en;
85 ldchCtx->user_config.correct_level = calib_ldch->correct_level;
86
87
88 LOGI_ALDCH("update calib en(%d), level(%d-%d), coeff(%f, %f, %f, %f, %f, %f)",
89 calib_ldch->ldch_en,
90 calib_ldch->correct_level,
91 calib_ldch->correct_level_max,
92 calib_ldch->light_center[0],
93 calib_ldch->light_center[1],
94 calib_ldch->coefficient[0],
95 calib_ldch->coefficient[1],
96 calib_ldch->coefficient[2],
97 calib_ldch->coefficient[3]);
98
99 return XCAM_RETURN_NO_ERROR;
100 }
101
update_custom_lut_from_file(LDCHContext_t * ldchCtx)102 static XCamReturn update_custom_lut_from_file(LDCHContext_t* ldchCtx)
103 {
104 XCamReturn ret = XCAM_RETURN_NO_ERROR;
105
106 if (get_ldch_buf(ldchCtx) != XCAM_RETURN_NO_ERROR) {
107 LOGE_ALDCH("Failed to get ldch buf\n");
108 ret = XCAM_RETURN_ERROR_MEM;
109 } else {
110 rk_aiq_ldch_lut_external_file_t *lut = &ldchCtx->user_config.lut.u.file;
111
112 char filename[200] = {0};
113 sprintf(filename, "%s/%s",
114 lut->config_file_dir,
115 lut->mesh_file_name);
116
117 LOGD_ALDCH("read lut file name: %s/%s\n",
118 lut->config_file_dir,
119 lut->mesh_file_name);
120
121 bool ret1 = read_mesh_from_file(ldchCtx, filename);
122 if (!ret1) {
123 LOGE_ALDCH("Failed to read mesh, disable ldch!");
124 ldchCtx->ldch_en = ldchCtx->user_config.en = false;
125 put_ldch_buf(ldchCtx);
126 ret = XCAM_RETURN_ERROR_FILE;
127 } else {
128 uint16_t *addr = (uint16_t *)ldchCtx->ldch_mem_info->addr;
129 LOGD_ALDCH("lut[0:15]: %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
130 addr[0], addr[1], addr[2], addr[3],
131 addr[4], addr[5], addr[6], addr[7],
132 addr[8], addr[9], addr[10], addr[11],
133 addr[12], addr[13], addr[14], addr[15]);
134 }
135
136 if (ldchCtx->ldch_mem_info) {
137 ldchCtx->ready_lut_mem_fd = ldchCtx->ldch_mem_info->fd;
138 ldchCtx->update_lut_mem_fd = ldchCtx->ready_lut_mem_fd;
139 }
140
141 LOGD_ALDCH("update custom lut from external file, lut_mem_fd %d\n", ldchCtx->update_lut_mem_fd);
142 }
143
144 return ret;
145 }
146
update_custom_lut_from_external_buffer(LDCHContext_t * ldchCtx)147 static XCamReturn update_custom_lut_from_external_buffer(LDCHContext_t* ldchCtx)
148 {
149 XCamReturn ret = XCAM_RETURN_NO_ERROR;
150
151 if (!ldchCtx->_lutCache->GetBuffer()) {
152 LOGE_ALDCH("Failed to get ldch lut cache\n");
153 ret = XCAM_RETURN_ERROR_MEM;
154 }
155
156 if (get_ldch_buf(ldchCtx) != XCAM_RETURN_NO_ERROR) {
157 LOGE_ALDCH("Failed to get ldch buf\n");
158 ret = XCAM_RETURN_ERROR_MEM;
159 } else {
160 uint16_t hpic, vpic, hsize, vsize, hstep, vstep;
161 uint32_t lut_size = 0;
162 uint16_t *addr = (uint16_t *)ldchCtx->_lutCache->GetBuffer();
163
164 hpic = *addr++;
165 vpic = *addr++;
166 hsize = *addr++;
167 vsize = *addr++;
168 hstep = *addr++;
169 vstep = *addr++;
170
171 lut_size = hsize * vsize * sizeof(uint16_t);
172 LOGD_ALDCH("lut info: [%d-%d-%d-%d-%d-%d]", hpic, vpic, hsize, vsize, hstep, vstep);
173
174 if (ldchCtx->src_width != hpic || ldchCtx->src_height != vpic || \
175 lut_size > (uint32_t)ldchCtx->ldch_mem_info->size) {
176 LOGE_ALDCH("mismatched lut pic resolution: src %dx%d, lut %dx%d, disable ldch",
177 ldchCtx->src_width, ldchCtx->src_height, hpic, vpic);
178 LOGE_ALDCH("Invalid lut buffer size %zu, ldch drv bufer size is %u, disable ldch",
179 lut_size, ldchCtx->ldch_mem_info->size);
180 ldchCtx->ldch_en = ldchCtx->user_config.en = false;
181 put_ldch_buf(ldchCtx);
182 ret = XCAM_RETURN_ERROR_PARAM;
183 } else {
184 ldchCtx->lut_h_size = hsize;
185 ldchCtx->lut_v_size = vsize;
186 ldchCtx->lut_mapxy_size = lut_size;
187 ldchCtx->lut_h_size = hsize / 2; //word unit
188
189 memcpy(ldchCtx->ldch_mem_info->addr, addr, ldchCtx->lut_mapxy_size);
190 LOGD_ALDCH("lut[0:15]: %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
191 addr[0], addr[1], addr[2], addr[3],
192 addr[4], addr[5], addr[6], addr[7],
193 addr[8], addr[9], addr[10], addr[11],
194 addr[12], addr[13], addr[14], addr[15]);
195 ldchCtx->_lutCache.release();
196 ldchCtx->_lutCache = nullptr;
197 }
198
199 if (ldchCtx->ldch_mem_info) {
200 ldchCtx->ready_lut_mem_fd = ldchCtx->ldch_mem_info->fd;
201 ldchCtx->update_lut_mem_fd = ldchCtx->ready_lut_mem_fd;
202 }
203
204 LOGD_ALDCH("update custom lut from external buffer, lut_mem_fd %d\n", ldchCtx->update_lut_mem_fd);
205 }
206
207 return ret;
208 }
209
update_uapi_attribute(LDCHContext_t * ldchCtx)210 static XCamReturn update_uapi_attribute(LDCHContext_t* ldchCtx)
211 {
212 XCamReturn ret = XCAM_RETURN_NO_ERROR;
213
214 if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_FROM_EXTERNAL_FILE) {
215 if (ldchCtx->user_config.en) {
216 if (ldchCtx->user_config.lut.update_flag) {
217 if (update_custom_lut_from_file(ldchCtx) < 0) {
218 LOGE_ALDCH("Failed update custom lut\n");
219 return XCAM_RETURN_ERROR_FAILED;
220 } else {
221 ldchCtx->user_config.lut.update_flag = false;
222 }
223 }
224 } else {
225 ldchCtx->ldch_en = false;
226 LOGD_ALDCH("disable ldch by user api\n");
227 }
228
229 ldchCtx->isAttribUpdated = false;
230 } else if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
231 if (ldchCtx->user_config.en) {
232 SmartPtr<rk_aiq_ldch_v21_attrib_t> attrPtr = new rk_aiq_ldch_v21_attrib_t;
233 if (attrPtr.ptr()) {
234 memcpy(attrPtr.ptr(), &ldchCtx->user_config, sizeof(ldchCtx->user_config));
235
236 ldchCtx->aldchReadMeshThread->push_attr(attrPtr);
237 ldchCtx->isAttribUpdated = false;
238 } else {
239 LOGE_ALDCH("Failed to new ldch attr, don't update attrib\n");
240 }
241 } else {
242 ldchCtx->ldch_en = false;
243 ldchCtx->isAttribUpdated = false;
244 }
245 } else if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_FROM_EXTERNAL_BUFFER) {
246 if (ldchCtx->user_config.en) {
247 if (ldchCtx->user_config.lut.update_flag) {
248 if (update_custom_lut_from_external_buffer(ldchCtx) < 0) {
249 LOGE_ALDCH("Failed update custom lut from external buffer\n");
250 } else {
251 ldchCtx->user_config.lut.update_flag = false;
252 }
253 }
254 } else {
255 ldchCtx->ldch_en = false;
256 LOGD_ALDCH("disable ldch by user api\n");
257 }
258
259 ldchCtx->isAttribUpdated = false;
260 } else {
261 LOGE_ALDCH("unknow updating lut mode %d\n", ldchCtx->user_config.update_lut_mode);
262 ldchCtx->isAttribUpdated = false;
263 ret = XCAM_RETURN_ERROR_PARAM;
264 }
265
266 // update user params after lut is generated by RKAiqAldchThread in online mode
267 if (ret == XCAM_RETURN_NO_ERROR && \
268 ldchCtx->user_config.update_lut_mode != RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
269 ldchCtx->ldch_en = ldchCtx->user_config.en;
270 ldchCtx->correct_level = ldchCtx->user_config.correct_level;
271 ldchCtx->zero_interp_en = ldchCtx->user_config.zero_interp_en;
272 ldchCtx->sample_avr_en = ldchCtx->user_config.sample_avr_en;
273 ldchCtx->bic_mode_en = ldchCtx->user_config.bic_mode_en;
274 memcpy(ldchCtx->bicubic, ldchCtx->user_config.bic_weight, sizeof(ldchCtx->bicubic));
275 }
276
277 return ret;
278 }
279
280 static XCamReturn
create_context(RkAiqAlgoContext ** context,const AlgoCtxInstanceCfg * cfg)281 create_context(RkAiqAlgoContext **context, const AlgoCtxInstanceCfg* cfg)
282 {
283 XCamReturn result = XCAM_RETURN_NO_ERROR;
284
285 LOG1_ALDCH("%s: (enter)\n", __FUNCTION__ );
286 RkAiqAlgoContext *ctx = new RkAiqAlgoContext();
287 if (ctx == NULL) {
288 LOGE_ALDCH( "%s: create aldch context fail!\n", __FUNCTION__);
289 return XCAM_RETURN_ERROR_MEM;
290 }
291 ctx->hLDCH = new LDCHContext_t;
292 if (ctx->hLDCH == NULL) {
293 LOGE_ALDCH( "%s: create aldch handle fail!\n", __FUNCTION__);
294 return XCAM_RETURN_ERROR_MEM;
295 }
296 /* setup config */
297 memset((void *)(ctx->hLDCH), 0, sizeof(LDCHContext_t) );
298
299 /* return handle */
300 *context = ctx;
301
302 ctx->hLDCH->isAttribUpdated = false;
303 ctx->hLDCH->aldchReadMeshThread = new RKAiqAldchThread(ctx->hLDCH);
304 ctx->hLDCH->isLutUpdated.store(false, std::memory_order_release);
305
306 LDCHHandle_t ldchCtx = ctx->hLDCH;
307 CalibDbV2_LDCH_t* calib_ldch_db =
308 (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(cfg->calibv2, aldch));
309 CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param;
310
311 ldchCtx->ldch_en = calib_ldch->ldch_en;
312 memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile));
313
314 ldchCtx->camCoeff.cx = calib_ldch->light_center[0];
315 ldchCtx->camCoeff.cy = calib_ldch->light_center[1];
316 ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0];
317 ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1];
318 ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2];
319 ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3];
320 LOGD_ALDCH("(%s) len light center(%.16f, %.16f)\n",
321 __FUNCTION__,
322 ldchCtx->camCoeff.cx, ldchCtx->camCoeff.cy);
323 LOGD_ALDCH("(%s) len coefficient(%.16f, %.16f, %.16f, %.16f)\n",
324 __FUNCTION__,
325 ldchCtx->camCoeff.a0, ldchCtx->camCoeff.a2,
326 ldchCtx->camCoeff.a3, ldchCtx->camCoeff.a4);
327
328 ldchCtx->correct_level = calib_ldch->correct_level;
329 ldchCtx->correct_level_max = calib_ldch->correct_level_max;
330
331 memset(&ldchCtx->user_config, 0, sizeof(ldchCtx->user_config));
332 ldchCtx->user_config.en = ldchCtx->ldch_en;
333 ldchCtx->user_config.correct_level = ldchCtx->correct_level;
334 ldchCtx->user_config.bic_mode_en = 1;
335 memcpy(ldchCtx->user_config.bic_weight, default_bic_table, sizeof(default_bic_table));
336
337 ldchCtx->frm_end_dis = 0;
338 ldchCtx->zero_interp_en = 0;
339 ldchCtx->sample_avr_en = 0;
340 ldchCtx->bic_mode_en = 1;
341 ldchCtx->force_map_en = 0;
342 ldchCtx->map13p3_en = 0;
343 memcpy(ldchCtx->bicubic, default_bic_table, sizeof(default_bic_table));
344
345 ldchCtx->update_lut_mem_fd = -1;
346 ldchCtx->ready_lut_mem_fd = -1;
347
348 ldchCtx->hasAllocShareMem.store(false, std::memory_order_release);
349 ldchCtx->_lutCache = nullptr;
350
351 LOGD_ALDCH("bic table0: 0x%x, table1: 0x%x, table2: 0x%x, table3: 0x%x,",
352 *(uint32_t *)ldchCtx->bicubic,
353 *(uint32_t *)(ldchCtx->bicubic + 4),
354 *(uint32_t *)(ldchCtx->bicubic + 8),
355 *(uint32_t *)(ldchCtx->bicubic + 12));
356 LOGD_ALDCH("bic table4: 0x%x, table5: 0x%x, table6: 0x%x, table7: 0x%x,",
357 *(uint32_t *)(ldchCtx->bicubic + 16),
358 *(uint32_t *)(ldchCtx->bicubic + 20),
359 *(uint32_t *)(ldchCtx->bicubic + 24),
360 *(uint32_t *)(ldchCtx->bicubic + 28));
361 LOGD_ALDCH("bic table8: 0x%x, bic_mode_en: %d", *(uint32_t *)(ldchCtx->bicubic + 32), ldchCtx->bic_mode_en);
362
363 LOGD_ALDCH("ldch en %d, meshfile: %s, correct_level-max: %d-%d from xml file",
364 calib_ldch->ldch_en,
365 ldchCtx->meshfile,
366 ldchCtx->correct_level,
367 ldchCtx->correct_level_max);
368
369 return XCAM_RETURN_NO_ERROR;
370 }
371
372 static XCamReturn
destroy_context(RkAiqAlgoContext * context)373 destroy_context(RkAiqAlgoContext *context)
374 {
375 LDCHHandle_t hLDCH = (LDCHHandle_t)context->hLDCH;
376 LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
377
378 if (ldchCtx->aldchReadMeshThread->is_running()) {
379 ldchCtx->aldchReadMeshThread->triger_stop();
380 ldchCtx->aldchReadMeshThread->stop();
381 }
382
383 if (!hLDCH->aldchReadMeshThread->is_empty()) {
384 hLDCH->aldchReadMeshThread->clear_attr();
385 }
386
387 if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
388 genLdchMeshDeInit(ldchCtx->ldchParams);
389 }
390
391 release_ldch_buf(ldchCtx);
392 delete context->hLDCH;
393 context->hLDCH = NULL;
394 delete context;
395 context = NULL;
396 return XCAM_RETURN_NO_ERROR;
397 }
398
399 static XCamReturn
prepare(RkAiqAlgoCom * params)400 prepare(RkAiqAlgoCom* params)
401 {
402 LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH;
403 LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
404 RkAiqAlgoConfigAldch* rkaiqAldchConfig = (RkAiqAlgoConfigAldch*)params;
405
406 ldchCtx->src_width = params->u.prepare.sns_op_width;
407 ldchCtx->src_height = params->u.prepare.sns_op_height;
408 ldchCtx->dst_width = params->u.prepare.sns_op_width;
409 ldchCtx->dst_height = params->u.prepare.sns_op_height;
410 ldchCtx->resource_path = rkaiqAldchConfig->resource_path;
411 ldchCtx->share_mem_ops = rkaiqAldchConfig->mem_ops_ptr;
412
413 LOGD_ALDCH("update_lut_mode %d\n", ldchCtx->user_config.update_lut_mode);
414
415 // 1.update cailb
416 bool config_calib = !!(params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB);
417 if (config_calib) {
418 if(updateCalibConfig(params) != XCAM_RETURN_NO_ERROR) {
419 LOGW_ALDCH("Failed to update calib config");
420 }
421
422 return XCAM_RETURN_NO_ERROR;
423 }
424
425 // 2.process the new attrib set before prepare
426 if (ldchCtx->aldchReadMeshThread->is_running()) {
427 hLDCH->aldchReadMeshThread->triger_stop();
428 hLDCH->aldchReadMeshThread->stop();
429 }
430
431 if (!hLDCH->aldchReadMeshThread->is_empty()) {
432 hLDCH->aldchReadMeshThread->clear_attr();
433 }
434
435 // discard the lut generated ReadMeshThread in before aiq prepare
436 if (ldchCtx->isLutUpdated.load(std::memory_order_acquire)) {
437 put_ldch_buf(hLDCH);
438 ldchCtx->isLutUpdated.store(false, std::memory_order_release);
439 }
440
441 // 3.update uapi attribute
442 if (ldchCtx->isAttribUpdated) {
443 ldchCtx->ldch_en = ldchCtx->user_config.en;
444 ldchCtx->correct_level = ldchCtx->user_config.correct_level;
445 ldchCtx->zero_interp_en = ldchCtx->user_config.zero_interp_en;
446 ldchCtx->sample_avr_en = ldchCtx->user_config.sample_avr_en;
447 ldchCtx->bic_mode_en = ldchCtx->user_config.bic_mode_en;
448 memcpy(ldchCtx->bicubic, ldchCtx->user_config.bic_weight, sizeof(ldchCtx->bicubic));
449
450 ldchCtx->isAttribUpdated = false;
451 }
452
453 // 4.update ldch result
454 if (ldchCtx->ldch_en) {
455 if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_FROM_EXTERNAL_FILE) {
456 if (ldchCtx->user_config.lut.update_flag) {
457 if (update_custom_lut_from_file(ldchCtx) < 0) {
458 LOGE_ALDCH("Failed update custom lut from file\n");
459 ldchCtx->ldch_en = false;
460 } else {
461 ldchCtx->user_config.lut.update_flag = false;
462 }
463 }
464 } else if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
465 if (aiqGenLdchMeshInit(ldchCtx) == XCAM_RETURN_NO_ERROR) {
466 bool success = aiqGenMesh(hLDCH, ldchCtx->correct_level);
467 if (!success) {
468 LOGW_ALDCH("lut is not exist, disable ldch!");
469 put_ldch_buf(hLDCH);
470 ldchCtx->ldch_en = false;
471 }
472
473 if (ldchCtx->ldch_mem_info)
474 hLDCH->ready_lut_mem_fd = ldchCtx->ldch_mem_info->fd;
475 }
476 } else if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_FROM_EXTERNAL_BUFFER) {
477 if (ldchCtx->user_config.lut.update_flag) {
478 if (update_custom_lut_from_external_buffer(ldchCtx) < 0) {
479 LOGE_ALDCH("Failed update custom lut from external buffer\n");
480 ldchCtx->ldch_en = false;
481 } else {
482 ldchCtx->user_config.lut.update_flag = false;
483 }
484 }
485 } else {
486 LOGE_ALDCH("unknow updating lut mode %d\n", ldchCtx->user_config.update_lut_mode);
487 }
488 }
489
490 if (ldchCtx->user_config.update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE) {
491 hLDCH->aldchReadMeshThread->triger_start();
492 hLDCH->aldchReadMeshThread->start();
493 }
494
495 return XCAM_RETURN_NO_ERROR;
496 }
497
498 static XCamReturn
pre_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)499 pre_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
500 {
501 return XCAM_RETURN_NO_ERROR;
502 }
503
504 static XCamReturn
processing(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)505 processing(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
506 {
507 LDCHHandle_t hLDCH = (LDCHHandle_t)inparams->ctx->hLDCH;
508 LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
509 RkAiqAlgoProcResAldchV21* ldchPreOut = (RkAiqAlgoProcResAldchV21*)outparams;
510 bool update_params = false;
511
512 // 1.initial state processing or updating uapi attrib after lut is generated by RKAiqAldchThread
513 if (inparams->u.proc.init) {
514 if (ldchCtx->ready_lut_mem_fd >= 0) {
515 ldchCtx->update_lut_mem_fd = ldchCtx->ready_lut_mem_fd;
516 }
517 update_params = true;
518 } else if (ldchCtx->isLutUpdated.load(std::memory_order_acquire)) {
519 // update user params after lut is generated by RKAiqAldchThread
520 ldchCtx->ldch_en = ldchCtx->user_config.en;
521 ldchCtx->correct_level = ldchCtx->user_config.correct_level;
522 ldchCtx->zero_interp_en = ldchCtx->user_config.zero_interp_en;
523 ldchCtx->sample_avr_en = ldchCtx->user_config.sample_avr_en;
524 ldchCtx->bic_mode_en = ldchCtx->user_config.bic_mode_en;
525 memcpy(ldchCtx->bicubic, ldchCtx->user_config.bic_weight, sizeof(ldchCtx->bicubic));
526
527 if (ldchCtx->ready_lut_mem_fd >= 0)
528 ldchCtx->update_lut_mem_fd = ldchCtx->ready_lut_mem_fd;
529 LOGD_ALDCH("update update_lut_mem_fd %d\n", ldchCtx->update_lut_mem_fd);
530
531 update_params = true;
532 ldchCtx->isLutUpdated.store(false, std::memory_order_release);
533 }
534
535 // 2.update uapi attribute
536 if (ldchCtx->isAttribUpdated) {
537 if (update_uapi_attribute(ldchCtx) < 0) {
538 LOGE_ALDCH("Failed to update uapi attribute %d", ldchCtx->update_lut_mem_fd);
539 }
540
541 // update params asynchronously after lut is generated by RKAiqAldchThread
542 // in online mode
543 auto update_lut_mode = ldchCtx->user_config.update_lut_mode;
544 if (update_lut_mode != RK_AIQ_LDCH_UPDATE_LUT_ON_LINE ||
545 (update_lut_mode == RK_AIQ_LDCH_UPDATE_LUT_ON_LINE && !ldchCtx->ldch_en)) {
546 update_params = true;
547 }
548 }
549
550 // 3.update ldch result
551 if (ldchCtx->ldch_en) {
552 if (ldchCtx->update_lut_mem_fd < 0) {
553 LOGE_ALDCH("no available ldch buf, lut fd: %d", ldchCtx->update_lut_mem_fd);
554 if (inparams->u.proc.init) {
555 LOGE_ALDCH("mesh buf is invalid, disable LDCH!");
556 ldchCtx->ldch_en = ldchCtx->user_config.en = false;
557 ldchPreOut->ldch_result->base.sw_ldch_en = false;
558 outparams->cfg_update = true;
559 } else {
560 outparams->cfg_update = false;
561 }
562 return XCAM_RETURN_NO_ERROR;
563 }
564
565 ldchPreOut->ldch_result->base.lut_mapxy_buf_fd = ldchCtx->update_lut_mem_fd;
566 ldchPreOut->ldch_result->base.lut_h_size = ldchCtx->lut_h_size;
567 ldchPreOut->ldch_result->base.lut_v_size = ldchCtx->lut_v_size;
568 ldchPreOut->ldch_result->base.lut_map_size = ldchCtx->lut_mapxy_size;
569
570 ldchPreOut->ldch_result->frm_end_dis = ldchCtx->frm_end_dis;
571 ldchPreOut->ldch_result->zero_interp_en = ldchCtx->zero_interp_en;
572 ldchPreOut->ldch_result->sample_avr_en = ldchCtx->sample_avr_en;
573 ldchPreOut->ldch_result->bic_mode_en = ldchCtx->bic_mode_en;
574 ldchPreOut->ldch_result->force_map_en = ldchCtx->force_map_en;
575 ldchPreOut->ldch_result->map13p3_en = ldchCtx->map13p3_en;
576 memcpy(ldchPreOut->ldch_result->bicubic, ldchCtx->bicubic, sizeof(ldchCtx->bicubic));
577 }
578
579 ldchPreOut->ldch_result->base.sw_ldch_en = ldchCtx->ldch_en;
580 outparams->cfg_update = update_params;
581
582 LOGV_ALDCH("en:%d, level:%d, h/v: %dx%d, interp_en:%d, avr_en:%d, bic_en:%d, force_map_en:%d, map13p3_en:%d\n",
583 ldchCtx->ldch_en,
584 ldchCtx->correct_level,
585 ldchCtx->lut_h_size,
586 ldchCtx->lut_v_size,
587 ldchCtx->zero_interp_en,
588 ldchCtx->sample_avr_en,
589 ldchCtx->bic_mode_en,
590 ldchCtx->force_map_en,
591 ldchCtx->map13p3_en);
592
593 LOGV_ALDCH("update_lut_mode %d, lut fd %d, cfg_update %d\n",
594 ldchCtx->user_config.update_lut_mode,
595 ldchPreOut->ldch_result->base.lut_mapxy_buf_fd,
596 outparams->cfg_update);
597
598 return XCAM_RETURN_NO_ERROR;
599 }
600
601 static XCamReturn
post_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)602 post_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
603 {
604 return XCAM_RETURN_NO_ERROR;
605 }
606
607 RkAiqAlgoDescription g_RkIspAlgoDescAldch = {
608 .common = {
609 .version = RKISP_ALGO_ALDCH_VERSION,
610 .vendor = RKISP_ALGO_ALDCH_VENDOR,
611 .description = RKISP_ALGO_ALDCH_DESCRIPTION,
612 .type = RK_AIQ_ALGO_TYPE_ALDCH,
613 .id = 0,
614 .create_context = create_context,
615 .destroy_context = destroy_context,
616 },
617 .prepare = prepare,
618 .pre_process = pre_process,
619 .processing = processing,
620 .post_process = post_process,
621 };
622
623 RKAIQ_END_DECLARE
624
625
loop()626 bool RKAiqAldchThread::loop()
627 {
628 XCamReturn ret = XCAM_RETURN_NO_ERROR;
629 ENTER_ANALYZER_FUNCTION();
630
631 const static int32_t timeout = -1;
632 SmartPtr<rk_aiq_ldch_v21_cfg_t> attrib = mAttrQueue.pop (timeout);
633
634 if (!attrib.ptr()) {
635 LOGW_ALDCH("RKAiqAldchThread got empty attrib, stop thread");
636 return false;
637 }
638
639 if (!hLDCH->ldch_en || attrib->correct_level != hLDCH->correct_level) {
640 if (aiqGenLdchMeshInit(hLDCH) == XCAM_RETURN_NO_ERROR) {
641 bool success = aiqGenMesh(hLDCH, attrib->correct_level);
642 if (!success) {
643 LOGW_ALDCH("lut is not exist");
644 ret = XCAM_RETURN_ERROR_PARAM;
645 put_ldch_buf(hLDCH);
646 return true;
647 }
648 } else {
649 LOGE_ALDCH("Failed to init gen mesh");
650 ret = XCAM_RETURN_ERROR_PARAM;
651 return true;
652 }
653 }
654
655 if (ret == XCAM_RETURN_NO_ERROR) {
656 if (hLDCH->ldch_mem_info)
657 hLDCH->ready_lut_mem_fd = hLDCH->ldch_mem_info->fd;
658 hLDCH->isLutUpdated.store(true, std::memory_order_release);
659
660 LOGD_ALDCH("ldch update attrib en(%d), level(%d), ready lut fd%d\n",
661 attrib->en, attrib->correct_level, hLDCH->ready_lut_mem_fd);
662
663 return true;
664 }
665
666 LOGE_ALDCH("RKAiqAldchThread failed to read mesh table!");
667
668 EXIT_ANALYZER_FUNCTION();
669
670 return true;
671 }
672