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