1 /*
2 * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Author: Cody Xie <cody.xie@rock-chips.com>
17 */
18 #include "cac_adaptor.h"
19
20 #include <fcntl.h>
21
22 #include <fstream>
23 #include <iostream>
24
25 #define __STDC_FORMAT_MACROS
26 #include <cinttypes>
27
28 #include "algos/acac/lut_buffer.h"
29 #include "algos/acac/rk_aiq_types_acac_algo.h"
30 #include "common/rk_aiq_comm.h"
31 #include "common/rk_aiq_types_priv.h"
32 #include "xcore/base/xcam_log.h"
33
34 namespace RkCam {
35
36 #define RKCAC_STRENGTH_FIX_BITS 7
37 #define RKCAC_EDGE_DETECT_FIX_BITS 4
38
39 #define CAC_PSF_BUF_NUM 2
40 #define BITS_PER_BYTE 8
41 #define BYTES_PER_WORD 4
42 #define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
43
44 #define INTERP_CAC(x0, x1, ratio) ((ratio) * ((x1) - (x0)) + (x0))
45
46 #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
47
48 #if RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10
49 static const uint32_t IspBigModeWidthLimit = 2688;
50 static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 1536;
51 static const uint32_t CacPsfCountLimit = 1632;
52 static const uint8_t CacChannelCount = 2;
53 #else // RKAIQ_HAVE_CAC_V11
54 static const uint32_t IspBigModeWidthLimit = 1536;
55 static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 864;
56 static const uint32_t CacPsfCountLimit = 336;
57 static const uint8_t CacChannelCount = 2;
58 #endif
59 static const uint8_t CacScaleFactorDefault = 64;
60 static const uint8_t CacScaleFactorBigMode = 128;
61 static const uint8_t CacStrengthDistance = 128;
62 static const uint8_t CacPsfKernelSize = 7 * 5;
63 static const uint8_t CacPsfKernelWordSizeInMemory =
64 DIV_ROUND_UP((CacPsfKernelSize - 1) * BITS_PER_BYTE, BITS_PER_WORD);
65 static const uint8_t CacPsfBufferCount = CAC_PSF_BUF_NUM;
66
67 template<class T>
CacClamp(const T & v,const T & lo,const T & hi)68 static constexpr const T& CacClamp( const T& v, const T& lo, const T& hi ) {
69 return v < lo ? lo : hi < v ? hi : v;
70 }
71
IsIspBigMode(uint32_t width,uint32_t height,bool is_multi_sensor)72 static inline bool IsIspBigMode(uint32_t width, uint32_t height, bool is_multi_sensor) {
73 if (is_multi_sensor || width > IspBigModeWidthLimit || width * height > IspBigModeSizeLimit) {
74 return true;
75 }
76
77 return false;
78 }
79
80 /**
81 * cac_wsize=bigmode_en ? (pic_width+126)>>7 : (pic_width+62)>>6;
82 * cac_hsize=bigmode_en ? (pic_height+126)>>7 : (pic_height+62)>>6;
83 * lut_h_wsize = cac_wsize*9
84 * lut_v_size = cac_hsize*2
85 */
CalcCacLutConfig(uint32_t width,uint32_t height,bool is_big_mode,LutBufferConfig & config)86 static inline void CalcCacLutConfig(uint32_t width, uint32_t height, bool is_big_mode,
87 LutBufferConfig& config) {
88 config.Width = width;
89 config.Height = height;
90 config.IsBigMode = is_big_mode;
91 if (config.IsBigMode) {
92 config.ScaleFactor = CacScaleFactorBigMode;
93 } else {
94 config.ScaleFactor = CacScaleFactorDefault;
95 }
96 /**
97 * CAC only processes R & B channels, that means for R or R channels,
98 * which have only half size of full picture, only need to div round up by 32(scale==64) or
99 * 64(scale==128). For calculate convinient, use full picture size to calculate
100 */
101 config.LutHCount = is_big_mode ? (width + 126) >> 7 : (width + 62) >> 6;
102 config.LutVCount = is_big_mode ? (height + 126) >> 7 : (height + 62) >> 6;
103 config.PsfCfgCount = config.LutHCount * config.LutVCount;
104 XCAM_ASSERT(config.PsfCfgCount <= CacPsfCountLimit);
105 /**
106 * CAC stores one PSF point's kernel in 9 words, one kernel size is 8 bytes.
107 * (8bytes*8bits/byte + 32 - 1) / 32bits/word = 9 words.
108 */
109 }
110
~CacAlgoAdaptor()111 CacAlgoAdaptor::~CacAlgoAdaptor() {
112 current_lut_.clear();
113 lut_manger_ = nullptr;
114 };
115
116 #if RKAIQ_HAVE_CAC_V03
SetApiAttr(const rkaiq_cac_v03_api_attr_t * attr)117 XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v03_api_attr_t* attr) {
118 if (!attr_) {
119 attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
120 }
121 if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
122 return XCAM_RETURN_ERROR_PARAM;
123 } else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
124 attr_->iso_cnt = attr->iso_cnt;
125 attr_->op_mode = attr->op_mode;
126 memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
127 } else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
128 attr_->op_mode = attr->op_mode;
129 memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
130 }
131 enable_ = attr_->enable = attr->enable;
132 isReCal_ = true;
133
134 return XCAM_RETURN_NO_ERROR;
135 }
136 #elif RKAIQ_HAVE_CAC_V10
SetApiAttr(const rkaiq_cac_v10_api_attr_t * attr)137 XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v10_api_attr_t* attr) {
138 if (!attr_) {
139 attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
140 }
141 if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
142 return XCAM_RETURN_ERROR_PARAM;
143 } else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
144 attr_->iso_cnt = attr->iso_cnt;
145 memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
146 } else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
147 memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
148 }
149 attr_->op_mode = attr->op_mode;
150 enable_ = attr_->enable = attr->enable;
151 isReCal_ = true;
152
153 return XCAM_RETURN_NO_ERROR;
154 }
155 #elif RKAIQ_HAVE_CAC_V11
SetApiAttr(const rkaiq_cac_v11_api_attr_t * attr)156 XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v11_api_attr_t* attr) {
157 if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
158 return XCAM_RETURN_ERROR_PARAM;
159 }
160
161 if (!attr_) {
162 attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
163 }
164
165 attr_->op_mode = attr->op_mode;
166 if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
167 attr_->iso_cnt = attr->iso_cnt;
168 memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
169 } else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
170 memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
171 }
172 enable_ = attr_->enable = attr->enable;
173 isReCal_ = true;
174
175 return XCAM_RETURN_NO_ERROR;
176 }
177 #endif
178
179 #if RKAIQ_HAVE_CAC_V03
GetApiAttr(rkaiq_cac_v03_api_attr_t * attr)180 XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v03_api_attr_t* attr) {
181 if (attr_ == nullptr) {
182 return XCAM_RETURN_ERROR_FAILED;
183 }
184 memcpy(attr, attr_.get(), sizeof(*attr));
185
186 return XCAM_RETURN_NO_ERROR;
187 }
188 #elif RKAIQ_HAVE_CAC_V10
GetApiAttr(rkaiq_cac_v10_api_attr_t * attr)189 XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v10_api_attr_t* attr) {
190 if (attr_ == nullptr) {
191 return XCAM_RETURN_ERROR_FAILED;
192 }
193 memcpy(attr, attr_.get(), sizeof(*attr));
194
195 return XCAM_RETURN_NO_ERROR;
196 }
197 #elif RKAIQ_HAVE_CAC_V11
GetApiAttr(rkaiq_cac_v11_api_attr_t * attr)198 XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v11_api_attr_t* attr) {
199 if (attr_ == nullptr) {
200 return XCAM_RETURN_ERROR_FAILED;
201 }
202 memcpy(attr, attr_.get(), sizeof(*attr));
203
204 return XCAM_RETURN_NO_ERROR;
205 }
206 #endif
207
208 #if RKAIQ_HAVE_CAC_V03
Config(const AlgoCtxInstanceCfg * config,const CalibDbV2_Cac_V03_t * calib)209 XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
210 const CalibDbV2_Cac_V03_t* calib) {
211 #elif RKAIQ_HAVE_CAC_V10
212 XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
213 const CalibDbV2_Cac_V10_t* calib) {
214 #elif RKAIQ_HAVE_CAC_V11
215 XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
216 const CalibDbV2_Cac_V11_t* calib) {
217 #endif
218 (void)(config);
219
220 LOGD_ACAC("%s : Enter", __func__);
221 ctx_config_ = config;
222 enable_ = calib != nullptr ? calib->SettingPara.enable : false;
223 calib_ = calib;
224
225 if (attr_ == nullptr) {
226 #if RKAIQ_HAVE_CAC_V03
227 attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
228 #elif RKAIQ_HAVE_CAC_V10
229 attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
230 #elif RKAIQ_HAVE_CAC_V11
231 attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
232 #endif
233 }
234
235 attr_->op_mode = RKAIQ_CAC_API_OPMODE_AUTO;
236 attr_->iso_cnt = calib_->TuningPara.SettingByIso_len;
237 XCAM_ASSERT(attr_->iso_cnt <= RKAIQ_CAC_MAX_ISO_CNT);
238 memcpy(attr_->auto_params, calib_->TuningPara.SettingByIso,
239 sizeof(calib_->TuningPara.SettingByIso[0]) * attr_->iso_cnt);
240 #if !RKAIQ_HAVE_CAC_V03
241 memcpy(&attr_->persist_params, &calib->SettingPara, sizeof(calib->SettingPara));
242 attr_->enable = attr_->persist_params.enable;
243 #else
244 attr_->enable = enable_;
245 #endif
246
247 if (!enable_) {
248 attr_->enable = false;
249 return XCAM_RETURN_BYPASS;
250 }
251
252 valid_ = true;
253 return XCAM_RETURN_NO_ERROR;
254 }
255
256 XCamReturn CacAlgoAdaptor::Prepare(const RkAiqAlgoConfigAcac* config) {
257 LutBufferConfig lut_config{};
258 LutBufferConfig full_lut_config{};
259 uint32_t width = config->width;
260 uint32_t height = config->height;
261 bool is_big_mode = IsIspBigMode(width, height, config->is_multi_sensor);
262 char cac_map_path[RKCAC_MAX_PATH_LEN] = {0};
263
264 LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
265
266 isReCal_ = true;
267
268 if (!enable_ || !valid_) {
269 return XCAM_RETURN_BYPASS;
270 }
271
272 config_ = config;
273 if (config->is_multi_isp) {
274 #if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
275 CalcCacLutConfig(width, height, is_big_mode, full_lut_config);
276 width = width / 2 + config->multi_isp_extended_pixel;
277 CalcCacLutConfig(width, height, is_big_mode, lut_config);
278 #endif
279 } else {
280 CalcCacLutConfig(width, height, is_big_mode, lut_config);
281 }
282 if (lut_manger_ == nullptr) {
283 lut_manger_ =
284 std::unique_ptr<LutBufferManager>(new LutBufferManager(lut_config, config->mem_ops));
285 lut_manger_->ImportHwBuffers(0);
286 if (config->is_multi_isp) {
287 lut_manger_->ImportHwBuffers(1);
288 }
289 }
290 auto* buf = lut_manger_->GetFreeHwBuffer(0);
291 if (buf == nullptr) {
292 LOGW_ACAC("No buffer available, maybe only one buffer ?!");
293 return XCAM_RETURN_NO_ERROR;
294 }
295 current_lut_.clear();
296 current_lut_.emplace_back(buf);
297 if (buf->State != LutBufferState::kInitial) {
298 LOGW_ACAC("Buffer in use, will not update lut!");
299 return XCAM_RETURN_NO_ERROR;
300 }
301 #if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
302 if (config->is_multi_isp) {
303 auto* buf = lut_manger_->GetFreeHwBuffer(1);
304 if (buf == nullptr) {
305 LOGW_ACAC("No buffer available, maybe only one buffer ?!");
306 return XCAM_RETURN_NO_ERROR;
307 }
308 current_lut_.emplace_back(buf);
309 }
310 #endif
311 XCAM_ASSERT(current_lut_.size() == (uint32_t)(config->is_multi_isp + 1));
312
313 #if !RKAIQ_HAVE_CAC_V03
314 if (attr_->persist_params.psf_path[0] != '/') {
315 strcpy(cac_map_path, config->iqpath);
316 strcat(cac_map_path, "/");
317 }
318 strcat(cac_map_path, attr_->persist_params.psf_path);
319
320 std::ifstream ifs(cac_map_path, std::ios::binary);
321 if (!ifs.is_open()) {
322 LOGE_ACAC("Failed to open PSF file %s", cac_map_path);
323 valid_ = false;
324 return XCAM_RETURN_ERROR_FILE;
325 }
326
327 if (!config->is_multi_isp) {
328 uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
329 uint32_t size = lut_config.LutHCount * lut_config.LutVCount * CacPsfKernelWordSizeInMemory *
330 BYTES_PER_WORD;
331 for (int ch = 0; ch < CacChannelCount; ch++) {
332 char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) + ch * size;
333 ifs.read(addr0, size);
334 }
335 } else {
336 #if RKAIQ_HAVE_CAC_V10 && defined(ISP_HW_V30)
337 XCAM_ASSERT(current_lut_.size() > 1);
338 // Read and Split Memory
339 // a == line_size - line_offset
340 // b == line_offset
341 // c == line_offset - a = 2 * line_offset - line_size
342 // For each line:
343 // read b size to left
344 // copy c from left to right
345 // read a' to right
346 // - +---------------------------+
347 // | |<---a---->| | |<---a'--->|
348 // | | |<-c->| |
349 // v |<---b---------->| |
350 // | | | | | |
351 // - +---------------------------+
352 // |<---------line_size------->|
353 //
354 uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
355 uint32_t line_size =
356 full_lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
357 for (int ch = 0; ch < CacChannelCount; ch++) {
358 char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) +
359 ch * line_offset * lut_config.LutVCount;
360 char* addr1 = reinterpret_cast<char*>(current_lut_[1]->Addr) +
361 ch * line_offset * lut_config.LutVCount;
362 for (uint32_t i = 0; i < full_lut_config.LutVCount; i++) {
363 ifs.read(addr0 + (i * line_offset), line_offset);
364 memcpy(addr1 + (i * line_offset),
365 addr0 + (i * line_offset) + line_size - line_offset,
366 2 * line_offset - line_size);
367 ifs.read(addr1 + (i * line_size) + line_offset, line_size - line_offset);
368 }
369 }
370 #endif
371 }
372 #endif
373
374 return XCAM_RETURN_NO_ERROR;
375 }
376
377 void CacAlgoAdaptor::OnFrameEvent(const RkAiqAlgoProcAcac* input, RkAiqAlgoProcResAcac* output) {
378 int i;
379 int iso_low = 50;
380 int iso_high = 50;
381 int gain_high, gain_low;
382 float ratio = 1.0;
383 int iso_div = 50;
384 int max_iso_step = attr_->iso_cnt;
385 int iso = input->iso;
386 LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
387
388 if (current_lut_.empty()) {
389 valid_ = false;
390 } else {
391 valid_ = true;
392 }
393
394 if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO &&
395 lastIso_ != input->iso)
396 isReCal_ = true;
397
398 lastIso_ = input->iso;
399 if (!isReCal_) {
400 output->res_com.cfg_update = false;
401 LOGD_ACAC("skip cac reCalc");
402 return ;
403 }
404
405 output->res_com.cfg_update = true;
406 isReCal_ = false;
407
408 if (!enable_ || !valid_) {
409 output->config[0].bypass_en = 1;
410 #if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
411 output->config[1].bypass_en = 1;
412 #endif
413 output->enable = false;
414 return;
415 }
416
417 for (i = max_iso_step - 1; i >= 0; i--) {
418 if (iso < iso_div * (2 << i)) {
419 iso_low = iso_div * (2 << (i)) / 2;
420 iso_high = iso_div * (2 << i);
421 }
422 }
423 ratio = static_cast<float>(iso - iso_low) / (iso_high - iso_low);
424 if (iso_low == iso) {
425 iso_high = iso;
426 ratio = 0;
427 }
428 if (iso_high == iso) {
429 iso_low = iso;
430 ratio = 1;
431 }
432 gain_high = (int)(log(static_cast<float>(iso_high) / 50) / log(2.0));
433 gain_low = (int)(log(static_cast<float>(iso_low) / 50) / log(2.0));
434
435 gain_low = MIN(MAX(gain_low, 0), max_iso_step - 1);
436 gain_high = MIN(MAX(gain_high, 0), max_iso_step - 1);
437
438 XCAM_ASSERT(gain_low >= 0 && gain_low < max_iso_step);
439 XCAM_ASSERT(gain_high >= 0 && gain_high < max_iso_step);
440
441 #if RKAIQ_HAVE_CAC_V03
442 output->enable = attr_->enable;
443 output->config[0].center_en = 0;
444 output->config[0].center_width = 0;
445 output->config[0].center_height = 0;
446 output->config[0].psf_sft_bit = 2;
447 output->config[0].bypass_en = attr_->enable;
448 output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
449 output->config[0].buf_fd = current_lut_[0]->Fd;
450 output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
451 output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
452 if (config_->is_multi_isp) {
453 memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
454 if (current_lut_.size() > 1) {
455 output->config[1].buf_fd = current_lut_[1]->Fd;
456 }
457 }
458 #else
459
460 #if 0
461 output->config[0].strength[0] = 128;
462 output->config[0].strength[1] = 256;
463 output->config[0].strength[2] = 384;
464 output->config[0].strength[3] = 512;
465 output->config[0].strength[4] = 640;
466 output->config[0].strength[5] = 768;
467 output->config[0].strength[6] = 896;
468 output->config[0].strength[7] = 1024;
469 output->config[0].strength[8] = 1152;
470 output->config[0].strength[9] = 1280;
471 output->config[0].strength[10] = 1408;
472 output->config[0].strength[11] = 1536;
473 output->config[0].strength[12] = 1568;
474 output->config[0].strength[13] = 1600;
475 output->config[0].strength[14] = 1632;
476 output->config[0].strength[15] = 1664;
477 output->config[0].strength[16] = 1696;
478 output->config[0].strength[17] = 1728;
479 output->config[0].strength[18] = 1760;
480 output->config[0].strength[19] = 1792;
481 output->config[0].strength[20] = 1824;
482 output->config[0].strength[21] = 2047;
483 #endif
484 output->config[0].center_en = attr_->persist_params.center_en;
485 output->config[0].center_width = attr_->persist_params.center_x;
486 output->config[0].center_height = attr_->persist_params.center_y;
487 output->config[0].psf_sft_bit = attr_->persist_params.psf_shift_bits;
488 output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
489 output->config[0].buf_fd = current_lut_[0]->Fd;
490 output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
491 output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
492 #if (RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
493 memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
494 if (current_lut_.size() > 1) {
495 output->config[1].buf_fd = current_lut_[1]->Fd;
496 if (output->config[0].center_en) {
497 uint16_t w = config_->width / 4;
498 uint16_t e = config_->multi_isp_extended_pixel / 4;
499 uint16_t x = attr_->persist_params.center_x;
500 output->config[1].center_width = x - (w / 2 - e);
501 }
502 }
503 #endif
504
505 if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
506 for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
507 float strength = attr_->manual_param.global_strength > 0
508 ? attr_->manual_param.global_strength
509 : attr_->manual_param.strength_table[i];
510 output->config[0].strength[i] = ROUND_F(attr_->manual_param.strength_table[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
511 output->config[0].strength[i] =
512 output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
513 }
514 output->config[0].bypass_en = attr_->manual_param.bypass;
515 #if RKAIQ_HAVE_CAC_V11
516 output->config[0].clip_g_mode = attr_->manual_param.clip_g_mode;
517 output->config[0].neg_clip0_en = attr_->manual_param.neg_clip0_enable;
518 output->config[0].edge_detect_en = attr_->manual_param.edge_detect_en;
519 output->config[0].flat_thed_b = ROUND_F(attr_->manual_param.flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
520 output->config[0].flat_thed_r = ROUND_F(attr_->manual_param.flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
521 output->config[0].offset_r = CacClamp<uint32_t>(attr_->manual_param.offset_r, 0, 1 << 16);
522 //ROUND_F(attr_->manual_param.offset_r);
523 output->config[0].offset_b = CacClamp<uint32_t>(attr_->manual_param.offset_b, 0, 1 << 16);
524 //ROUND_F(attr_->manual_param.offset_b);
525 output->config[0].expo_thed_b =
526 (!attr_->manual_param.expo_det_b_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_b, 0, 0xfffff);
527 output->config[0].expo_thed_r =
528 (!attr_->manual_param.expo_det_r_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_r, 0, 0xfffff);
529 output->config[0].expo_adj_b = CacClamp<uint32_t>(attr_->manual_param.expo_adj_b, 0, 0xfffff);
530 output->config[0].expo_adj_r = CacClamp<uint32_t>(attr_->manual_param.expo_adj_r, 0, 0xfffff);
531 output->enable = attr_->enable;
532 #endif
533 } else if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
534 float strength[RKCAC_STRENGTH_TABLE_LEN] = {1.0f};
535 float strenth_low = 0.0;
536 float strenth_high = 0.0;
537 for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
538 strenth_low = attr_->auto_params[gain_low].global_strength > 0
539 ? attr_->auto_params[gain_low].global_strength
540 : attr_->auto_params[gain_low].strength_table[i];
541 strenth_high = attr_->auto_params[gain_high].global_strength > 0
542 ? attr_->auto_params[gain_high].global_strength
543 : attr_->auto_params[gain_high].strength_table[i];
544 strength[i] = INTERP_CAC(strenth_low,
545 strenth_high, ratio);
546 output->config[0].strength[i] = ROUND_F(strength[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
547 output->config[0].strength[i] =
548 output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
549 }
550 output->config[0].bypass_en = INTERP_CAC(attr_->auto_params[gain_low].bypass,
551 attr_->auto_params[gain_high].bypass, ratio);
552
553 #if RKAIQ_HAVE_CAC_V11
554 output->config[0].clip_g_mode =
555 INTERP_CAC((int)attr_->auto_params[gain_low].clip_g_mode,
556 (int)attr_->auto_params[gain_high].clip_g_mode, ratio);
557 output->config[0].neg_clip0_en =
558 INTERP_CAC((int)attr_->auto_params[gain_low].neg_clip0_enable,
559 (int)attr_->auto_params[gain_high].neg_clip0_enable, ratio);
560 output->config[0].edge_detect_en =
561 INTERP_CAC((int)attr_->auto_params[gain_low].edge_detect_en,
562 (int)attr_->auto_params[gain_high].edge_detect_en, ratio);
563
564 float flat_thed_b = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_b,
565 attr_->auto_params[gain_high].flat_thed_b, ratio);
566 output->config[0].flat_thed_b = ROUND_F(flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
567
568 float flat_thed_r = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_r,
569 attr_->auto_params[gain_high].flat_thed_r, ratio);
570 output->config[0].flat_thed_r = ROUND_F(flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
571
572 float offset_b = INTERP_CAC(attr_->auto_params[gain_low].offset_b,
573 attr_->auto_params[gain_high].offset_b, ratio);
574 output->config[0].offset_b = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_b), 0, 1 << 16);
575
576 float offset_r = INTERP_CAC(attr_->auto_params[gain_low].offset_r,
577 attr_->auto_params[gain_high].offset_r, ratio);
578 output->config[0].offset_r = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_r), 0, 1 << 16);
579
580 int exp_det_r_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_r_en,
581 attr_->auto_params[gain_high].expo_det_r_en, ratio);
582 int exp_det_b_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_b_en,
583 attr_->auto_params[gain_high].expo_det_b_en, ratio);
584
585 uint32_t expo_thed_b = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_b,
586 attr_->auto_params[gain_high].expo_thed_b, ratio);
587 uint32_t expo_thed_r = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_r,
588 attr_->auto_params[gain_high].expo_thed_r, ratio);
589 uint32_t expo_adj_b = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_b,
590 attr_->auto_params[gain_high].expo_adj_b, ratio);
591 uint32_t expo_adj_r = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_r,
592 attr_->auto_params[gain_high].expo_adj_r, ratio);
593 expo_thed_b = input->hdr_ratio * expo_thed_b;
594 expo_thed_r = input->hdr_ratio * expo_thed_r;
595 expo_adj_b = input->hdr_ratio * expo_adj_b;
596 expo_adj_r = input->hdr_ratio * expo_adj_r;
597 output->config[0].expo_thed_b =
598 (static_cast<int>(!exp_det_b_en) << 20) | CacClamp<uint32_t>(expo_thed_b, 0, 0xfffff);
599 output->config[0].expo_thed_r =
600 (static_cast<int>(!exp_det_r_en) << 20) | CacClamp<uint32_t>(expo_thed_r, 0, 0xfffff);
601 output->config[0].expo_adj_b = CacClamp<uint32_t>(expo_adj_b, 0, 0xfffff);
602 output->config[0].expo_adj_r = CacClamp<uint32_t>(expo_adj_r, 0, 0xfffff);
603 #endif
604 }
605 #endif
606 output->enable = attr_->enable;
607
608 #if 0
609 LOGD_ACAC("global en : %d", output->enable);
610 LOGD_ACAC("center en: %d", output->config[0].center_en);
611 LOGD_ACAC("center x: %u", output->config[0].center_width);
612 LOGD_ACAC("center y: %u", output->config[0].center_height);
613 LOGD_ACAC("psf shift bits: %u", output->config[0].psf_sft_bit);
614 LOGD_ACAC("psf cfg num: %u", output->config[0].cfg_num);
615 LOGD_ACAC("psf buf fd: %d", output->config[0].buf_fd);
616 #if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
617 if (current_lut_.size() > 1) {
618 LOGD_ACAC("psf buf fd right: %d", output->config[1].buf_fd);
619 LOGD_ACAC("center x right: %d", output->config[1].center_width);
620 LOGD_ACAC("center y right: %d", output->config[1].center_height);
621 }
622 #endif
623 LOGD_ACAC("psf hwsize: %u", output->config[0].hsize);
624 LOGD_ACAC("psf vsize: %u", output->config[0].vsize);
625 for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
626 LOGD_ACAC("strength %d: %u", i, output->config[0].strength[i]);
627 }
628 #if RKAIQ_HAVE_CAC_V11
629 LOGD_ACAC("clip_g_mode: %u", output->config[0].clip_g_mode);
630 LOGD_ACAC("edge_detect_en: %u", output->config[0].edge_detect_en);
631 LOGD_ACAC("neg_clip0_en: %u", output->config[0].neg_clip0_en);
632 LOGD_ACAC("expo_thed_b: %u", output->config[0].expo_thed_b);
633 LOGD_ACAC("expo_thed_r: %u", output->config[0].expo_thed_r);
634 LOGD_ACAC("expo_adj_b: %u", output->config[0].expo_adj_b);
635 LOGD_ACAC("expo_adj_r: %u", output->config[0].expo_adj_r);
636 LOGD_ACAC("flat_thed_b: %u", output->config[0].flat_thed_b);
637 LOGD_ACAC("flat_thed_r: %u", output->config[0].flat_thed_r);
638 #endif
639 #endif
640 }
641
642 } // namespace RkCam
643