android13/external/camera_engine_rkaiq/algos/acac/cac_adaptor.cpp

652 lines
27 KiB
C++

/*
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Cody Xie <cody.xie@rock-chips.com>
*/
#include "cac_adaptor.h"
#include <fcntl.h>
#include <fstream>
#include <iostream>
#define __STDC_FORMAT_MACROS
#include <cinttypes>
#include "algos/acac/lut_buffer.h"
#include "algos/acac/rk_aiq_types_acac_algo.h"
#include "common/rk_aiq_comm.h"
#include "common/rk_aiq_types_priv.h"
#include "xcore/base/xcam_log.h"
namespace RkCam {
#define RKCAC_STRENGTH_FIX_BITS 7
#define RKCAC_EDGE_DETECT_FIX_BITS 4
#define CAC_PSF_BUF_NUM 2
#define BITS_PER_BYTE 8
#define BYTES_PER_WORD 4
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
#define INTERP_CAC(x0, x1, ratio) ((ratio) * ((x1) - (x0)) + (x0))
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#if RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10
static const uint32_t IspBigModeWidthLimit = 2688;
static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 1536;
static const uint32_t CacPsfCountLimit = 1632;
static const uint8_t CacChannelCount = 2;
#else // RKAIQ_HAVE_CAC_V11
static const uint32_t IspBigModeWidthLimit = 1536;
static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 864;
static const uint32_t CacPsfCountLimit = 336;
static const uint8_t CacChannelCount = 2;
#endif
static const uint8_t CacScaleFactorDefault = 64;
static const uint8_t CacScaleFactorBigMode = 128;
static const uint8_t CacStrengthDistance = 128;
static const uint8_t CacPsfKernelSize = 7 * 5;
static const uint8_t CacPsfKernelWordSizeInMemory =
DIV_ROUND_UP((CacPsfKernelSize - 1) * BITS_PER_BYTE, BITS_PER_WORD);
static const uint8_t CacPsfBufferCount = CAC_PSF_BUF_NUM;
template<class T>
static constexpr const T& CacClamp( const T& v, const T& lo, const T& hi ) {
return v < lo ? lo : hi < v ? hi : v;
}
static inline bool IsIspBigMode(uint32_t width, uint32_t height, bool is_multi_sensor) {
if (is_multi_sensor || width > IspBigModeWidthLimit || width * height > IspBigModeSizeLimit) {
return true;
}
return false;
}
/**
* cac_wsize=bigmode_en ? (pic_width+126)>>7 : (pic_width+62)>>6;
* cac_hsize=bigmode_en ? (pic_height+126)>>7 : (pic_height+62)>>6;
* lut_h_wsize = cac_wsize*9
* lut_v_size = cac_hsize*2
*/
static inline void CalcCacLutConfig(uint32_t width, uint32_t height, bool is_big_mode,
LutBufferConfig& config) {
config.Width = width;
config.Height = height;
config.IsBigMode = is_big_mode;
if (config.IsBigMode) {
config.ScaleFactor = CacScaleFactorBigMode;
} else {
config.ScaleFactor = CacScaleFactorDefault;
}
/**
* CAC only processes R & B channels, that means for R or R channels,
* which have only half size of full picture, only need to div round up by 32(scale==64) or
* 64(scale==128). For calculate convinient, use full picture size to calculate
*/
config.LutHCount = is_big_mode ? (width + 126) >> 7 : (width + 62) >> 6;
config.LutVCount = is_big_mode ? (height + 126) >> 7 : (height + 62) >> 6;
config.PsfCfgCount = config.LutHCount * config.LutVCount;
XCAM_ASSERT(config.PsfCfgCount <= CacPsfCountLimit);
/**
* CAC stores one PSF point's kernel in 9 words, one kernel size is 8 bytes.
* (8bytes*8bits/byte + 32 - 1) / 32bits/word = 9 words.
*/
}
CacAlgoAdaptor::~CacAlgoAdaptor() {
current_lut_.clear();
lut_manger_ = nullptr;
};
#if RKAIQ_HAVE_CAC_V03
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v03_api_attr_t* attr) {
if (!attr_) {
attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
}
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
return XCAM_RETURN_ERROR_PARAM;
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
attr_->iso_cnt = attr->iso_cnt;
attr_->op_mode = attr->op_mode;
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
attr_->op_mode = attr->op_mode;
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
}
enable_ = attr_->enable = attr->enable;
isReCal_ = true;
return XCAM_RETURN_NO_ERROR;
}
#elif RKAIQ_HAVE_CAC_V10
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v10_api_attr_t* attr) {
if (!attr_) {
attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
}
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
return XCAM_RETURN_ERROR_PARAM;
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
attr_->iso_cnt = attr->iso_cnt;
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
}
attr_->op_mode = attr->op_mode;
enable_ = attr_->enable = attr->enable;
isReCal_ = true;
return XCAM_RETURN_NO_ERROR;
}
#elif RKAIQ_HAVE_CAC_V11
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v11_api_attr_t* attr) {
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
return XCAM_RETURN_ERROR_PARAM;
}
if (!attr_) {
attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
}
attr_->op_mode = attr->op_mode;
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
attr_->iso_cnt = attr->iso_cnt;
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
}
enable_ = attr_->enable = attr->enable;
isReCal_ = true;
return XCAM_RETURN_NO_ERROR;
}
#endif
#if RKAIQ_HAVE_CAC_V03
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v03_api_attr_t* attr) {
if (attr_ == nullptr) {
return XCAM_RETURN_ERROR_FAILED;
}
memcpy(attr, attr_.get(), sizeof(*attr));
return XCAM_RETURN_NO_ERROR;
}
#elif RKAIQ_HAVE_CAC_V10
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v10_api_attr_t* attr) {
if (attr_ == nullptr) {
return XCAM_RETURN_ERROR_FAILED;
}
memcpy(attr, attr_.get(), sizeof(*attr));
return XCAM_RETURN_NO_ERROR;
}
#elif RKAIQ_HAVE_CAC_V11
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v11_api_attr_t* attr) {
if (attr_ == nullptr) {
return XCAM_RETURN_ERROR_FAILED;
}
memcpy(attr, attr_.get(), sizeof(*attr));
return XCAM_RETURN_NO_ERROR;
}
#endif
#if RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10 || RKAIQ_HAVE_CAC_V11
#if RKAIQ_HAVE_CAC_V03
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
const CalibDbV2_Cac_V03_t* calib) {
#elif RKAIQ_HAVE_CAC_V10
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
const CalibDbV2_Cac_V10_t* calib) {
#elif RKAIQ_HAVE_CAC_V11
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
const CalibDbV2_Cac_V11_t* calib) {
#endif
(void)(config);
LOGD_ACAC("%s : Enter", __func__);
ctx_config_ = config;
enable_ = calib != nullptr ? calib->SettingPara.enable : false;
calib_ = calib;
if (attr_ == nullptr) {
#if RKAIQ_HAVE_CAC_V03
attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
#elif RKAIQ_HAVE_CAC_V10
attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
#elif RKAIQ_HAVE_CAC_V11
attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
#endif
}
attr_->op_mode = RKAIQ_CAC_API_OPMODE_AUTO;
attr_->iso_cnt = calib_->TuningPara.SettingByIso_len;
XCAM_ASSERT(attr_->iso_cnt <= RKAIQ_CAC_MAX_ISO_CNT);
memcpy(attr_->auto_params, calib_->TuningPara.SettingByIso,
sizeof(calib_->TuningPara.SettingByIso[0]) * attr_->iso_cnt);
memcpy(&attr_->manual_param, calib_->TuningPara.SettingByIso,
sizeof(calib_->TuningPara.SettingByIso[0]));
#if !RKAIQ_HAVE_CAC_V03
memcpy(&attr_->persist_params, &calib->SettingPara, sizeof(calib->SettingPara));
attr_->enable = attr_->persist_params.enable;
#else
attr_->enable = enable_;
#endif
if (!enable_) {
attr_->enable = false;
return XCAM_RETURN_BYPASS;
}
valid_ = true;
return XCAM_RETURN_NO_ERROR;
}
#endif
XCamReturn CacAlgoAdaptor::Prepare(const RkAiqAlgoConfigAcac* config) {
LutBufferConfig lut_config{};
LutBufferConfig full_lut_config{};
uint32_t width = config->width;
uint32_t height = config->height;
bool is_big_mode = IsIspBigMode(width, height, config->is_multi_sensor);
char cac_map_path[RKCAC_MAX_PATH_LEN] = {0};
LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
isReCal_ = true;
if (!enable_ || !valid_) {
return XCAM_RETURN_BYPASS;
}
config_ = config;
if (config->is_multi_isp) {
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
CalcCacLutConfig(width, height, is_big_mode, full_lut_config);
width = width / 2 + config->multi_isp_extended_pixel;
CalcCacLutConfig(width, height, is_big_mode, lut_config);
#endif
} else {
CalcCacLutConfig(width, height, is_big_mode, lut_config);
}
if (lut_manger_ == nullptr) {
lut_manger_ =
std::unique_ptr<LutBufferManager>(new LutBufferManager(lut_config, config->mem_ops));
lut_manger_->ImportHwBuffers(0);
if (config->is_multi_isp) {
lut_manger_->ImportHwBuffers(1);
}
}
auto* buf = lut_manger_->GetFreeHwBuffer(0);
if (buf == nullptr) {
LOGW_ACAC("No buffer available, maybe only one buffer ?!");
return XCAM_RETURN_NO_ERROR;
}
current_lut_.clear();
current_lut_.emplace_back(buf);
if (buf->State != LutBufferState::kInitial) {
LOGW_ACAC("Buffer in use, will not update lut!");
return XCAM_RETURN_NO_ERROR;
}
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
if (config->is_multi_isp) {
auto* buf = lut_manger_->GetFreeHwBuffer(1);
if (buf == nullptr) {
LOGW_ACAC("No buffer available, maybe only one buffer ?!");
return XCAM_RETURN_NO_ERROR;
}
current_lut_.emplace_back(buf);
}
#endif
XCAM_ASSERT(current_lut_.size() == (uint32_t)(config->is_multi_isp + 1));
#if !RKAIQ_HAVE_CAC_V03
if (attr_->persist_params.psf_path[0] != '/') {
strcpy(cac_map_path, config->iqpath);
strcat(cac_map_path, "/");
}
strcat(cac_map_path, attr_->persist_params.psf_path);
std::ifstream ifs(cac_map_path, std::ios::binary);
if (!ifs.is_open()) {
LOGE_ACAC("Failed to open PSF file %s", cac_map_path);
valid_ = false;
return XCAM_RETURN_ERROR_FILE;
}
if (!config->is_multi_isp) {
uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
uint32_t size = lut_config.LutHCount * lut_config.LutVCount * CacPsfKernelWordSizeInMemory *
BYTES_PER_WORD;
for (int ch = 0; ch < CacChannelCount; ch++) {
char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) + ch * size;
ifs.read(addr0, size);
}
} else {
#if RKAIQ_HAVE_CAC_V10 && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
XCAM_ASSERT(current_lut_.size() > 1);
// Read and Split Memory
// a == line_size - line_offset
// b == line_offset
// c == line_offset - a = 2 * line_offset - line_size
// For each line:
// read b size to left
// copy c from left to right
// read a' to right
// - +---------------------------+
// | |<---a---->| | |<---a'--->|
// | | |<-c->| |
// v |<---b---------->| |
// | | | | | |
// - +---------------------------+
// |<---------line_size------->|
//
uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
uint32_t line_size =
full_lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
for (int ch = 0; ch < CacChannelCount; ch++) {
char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) +
ch * line_offset * lut_config.LutVCount;
char* addr1 = reinterpret_cast<char*>(current_lut_[1]->Addr) +
ch * line_offset * lut_config.LutVCount;
for (uint32_t i = 0; i < full_lut_config.LutVCount; i++) {
ifs.read(addr0 + (i * line_offset), line_offset);
memcpy(addr1 + (i * line_offset),
addr0 + (i * line_offset) + line_size - line_offset,
2 * line_offset - line_size);
ifs.read(addr1 + (i * line_size) + line_offset, line_size - line_offset);
}
}
#endif
}
#endif
return XCAM_RETURN_NO_ERROR;
}
void CacAlgoAdaptor::OnFrameEvent(const RkAiqAlgoProcAcac* input, RkAiqAlgoProcResAcac* output) {
int i;
int iso_low = 50;
int iso_high = 50;
int gain_high, gain_low;
float ratio = 1.0;
int iso_div = 50;
int max_iso_step = attr_->iso_cnt;
int iso = input->iso;
LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
if (current_lut_.empty()) {
valid_ = false;
} else {
valid_ = true;
}
if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO &&
lastIso_ != input->iso)
isReCal_ = true;
lastIso_ = input->iso;
if (!isReCal_) {
output->res_com.cfg_update = false;
LOGD_ACAC("skip cac reCalc");
return ;
}
output->res_com.cfg_update = true;
isReCal_ = false;
if (!enable_ || !valid_) {
output->config[0].bypass_en = 1;
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)|| RKAIQ_HAVE_CAC_V11
output->config[1].bypass_en = 1;
#endif
output->enable = false;
return;
}
for (i = max_iso_step - 1; i >= 0; i--) {
if (iso < iso_div * (2 << i)) {
iso_low = iso_div * (2 << (i)) / 2;
iso_high = iso_div * (2 << i);
}
}
ratio = static_cast<float>(iso - iso_low) / (iso_high - iso_low);
if (iso_low == iso) {
iso_high = iso;
ratio = 0;
}
if (iso_high == iso) {
iso_low = iso;
ratio = 1;
}
gain_high = (int)(log(static_cast<float>(iso_high) / 50) / log(2.0));
gain_low = (int)(log(static_cast<float>(iso_low) / 50) / log(2.0));
gain_low = MIN(MAX(gain_low, 0), max_iso_step - 1);
gain_high = MIN(MAX(gain_high, 0), max_iso_step - 1);
XCAM_ASSERT(gain_low >= 0 && gain_low < max_iso_step);
XCAM_ASSERT(gain_high >= 0 && gain_high < max_iso_step);
#if RKAIQ_HAVE_CAC_V03
output->enable = attr_->enable;
output->config[0].center_en = 0;
output->config[0].center_width = 0;
output->config[0].center_height = 0;
output->config[0].psf_sft_bit = 2;
output->config[0].bypass_en = attr_->enable;
output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
output->config[0].buf_fd = current_lut_[0]->Fd;
output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
if (config_->is_multi_isp) {
memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
if (current_lut_.size() > 1) {
output->config[1].buf_fd = current_lut_[1]->Fd;
}
}
#else //not RKAIQ_HAVE_CAC_V03
#if 0
output->config[0].strength[0] = 128;
output->config[0].strength[1] = 256;
output->config[0].strength[2] = 384;
output->config[0].strength[3] = 512;
output->config[0].strength[4] = 640;
output->config[0].strength[5] = 768;
output->config[0].strength[6] = 896;
output->config[0].strength[7] = 1024;
output->config[0].strength[8] = 1152;
output->config[0].strength[9] = 1280;
output->config[0].strength[10] = 1408;
output->config[0].strength[11] = 1536;
output->config[0].strength[12] = 1568;
output->config[0].strength[13] = 1600;
output->config[0].strength[14] = 1632;
output->config[0].strength[15] = 1664;
output->config[0].strength[16] = 1696;
output->config[0].strength[17] = 1728;
output->config[0].strength[18] = 1760;
output->config[0].strength[19] = 1792;
output->config[0].strength[20] = 1824;
output->config[0].strength[21] = 2047;
#endif
output->config[0].center_en = attr_->persist_params.center_en;
output->config[0].center_width = attr_->persist_params.center_x;
output->config[0].center_height = attr_->persist_params.center_y;
output->config[0].psf_sft_bit = attr_->persist_params.psf_shift_bits;
output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
output->config[0].buf_fd = current_lut_[0]->Fd;
output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
float strength = attr_->manual_param.global_strength > 0
? attr_->manual_param.global_strength
: attr_->manual_param.strength_table[i];
output->config[0].strength[i] = ROUND_F(attr_->manual_param.strength_table[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
output->config[0].strength[i] =
output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
}
output->config[0].bypass_en = attr_->manual_param.bypass;
#if RKAIQ_HAVE_CAC_V11
output->config[0].clip_g_mode = attr_->manual_param.clip_g_mode;
output->config[0].neg_clip0_en = attr_->manual_param.neg_clip0_enable;
output->config[0].edge_detect_en = attr_->manual_param.edge_detect_en;
output->config[0].flat_thed_b = ROUND_F(attr_->manual_param.flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
output->config[0].flat_thed_r = ROUND_F(attr_->manual_param.flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
output->config[0].offset_r = CacClamp<uint32_t>(attr_->manual_param.offset_r, 0, 1 << 16);
//ROUND_F(attr_->manual_param.offset_r);
output->config[0].offset_b = CacClamp<uint32_t>(attr_->manual_param.offset_b, 0, 1 << 16);
//ROUND_F(attr_->manual_param.offset_b);
output->config[0].expo_thed_b =
(!attr_->manual_param.expo_det_b_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_b, 0, 0xfffff);
output->config[0].expo_thed_r =
(!attr_->manual_param.expo_det_r_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_r, 0, 0xfffff);
output->config[0].expo_adj_b = CacClamp<uint32_t>(attr_->manual_param.expo_adj_b, 0, 0xfffff);
output->config[0].expo_adj_r = CacClamp<uint32_t>(attr_->manual_param.expo_adj_r, 0, 0xfffff);
output->enable = attr_->enable;
#endif
} else if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
float strength[RKCAC_STRENGTH_TABLE_LEN] = {1.0f};
float strenth_low = 0.0;
float strenth_high = 0.0;
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
strenth_low = attr_->auto_params[gain_low].global_strength > 0
? attr_->auto_params[gain_low].global_strength
: attr_->auto_params[gain_low].strength_table[i];
strenth_high = attr_->auto_params[gain_high].global_strength > 0
? attr_->auto_params[gain_high].global_strength
: attr_->auto_params[gain_high].strength_table[i];
strength[i] = INTERP_CAC(strenth_low,
strenth_high, ratio);
output->config[0].strength[i] = ROUND_F(strength[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
output->config[0].strength[i] =
output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
}
output->config[0].bypass_en = INTERP_CAC(attr_->auto_params[gain_low].bypass,
attr_->auto_params[gain_high].bypass, ratio);
#if RKAIQ_HAVE_CAC_V11
output->config[0].clip_g_mode =
INTERP_CAC((int)attr_->auto_params[gain_low].clip_g_mode,
(int)attr_->auto_params[gain_high].clip_g_mode, ratio);
output->config[0].neg_clip0_en =
INTERP_CAC((int)attr_->auto_params[gain_low].neg_clip0_enable,
(int)attr_->auto_params[gain_high].neg_clip0_enable, ratio);
output->config[0].edge_detect_en =
INTERP_CAC((int)attr_->auto_params[gain_low].edge_detect_en,
(int)attr_->auto_params[gain_high].edge_detect_en, ratio);
float flat_thed_b = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_b,
attr_->auto_params[gain_high].flat_thed_b, ratio);
output->config[0].flat_thed_b = ROUND_F(flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
float flat_thed_r = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_r,
attr_->auto_params[gain_high].flat_thed_r, ratio);
output->config[0].flat_thed_r = ROUND_F(flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
float offset_b = INTERP_CAC(attr_->auto_params[gain_low].offset_b,
attr_->auto_params[gain_high].offset_b, ratio);
output->config[0].offset_b = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_b), 0, 1 << 16);
float offset_r = INTERP_CAC(attr_->auto_params[gain_low].offset_r,
attr_->auto_params[gain_high].offset_r, ratio);
output->config[0].offset_r = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_r), 0, 1 << 16);
int exp_det_r_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_r_en,
attr_->auto_params[gain_high].expo_det_r_en, ratio);
int exp_det_b_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_b_en,
attr_->auto_params[gain_high].expo_det_b_en, ratio);
uint32_t expo_thed_b = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_b,
attr_->auto_params[gain_high].expo_thed_b, ratio);
uint32_t expo_thed_r = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_r,
attr_->auto_params[gain_high].expo_thed_r, ratio);
uint32_t expo_adj_b = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_b,
attr_->auto_params[gain_high].expo_adj_b, ratio);
uint32_t expo_adj_r = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_r,
attr_->auto_params[gain_high].expo_adj_r, ratio);
expo_thed_b = input->hdr_ratio * expo_thed_b;
expo_thed_r = input->hdr_ratio * expo_thed_r;
expo_adj_b = input->hdr_ratio * expo_adj_b;
expo_adj_r = input->hdr_ratio * expo_adj_r;
output->config[0].expo_thed_b =
(static_cast<int>(!exp_det_b_en) << 20) | CacClamp<uint32_t>(expo_thed_b, 0, 0xfffff);
output->config[0].expo_thed_r =
(static_cast<int>(!exp_det_r_en) << 20) | CacClamp<uint32_t>(expo_thed_r, 0, 0xfffff);
output->config[0].expo_adj_b = CacClamp<uint32_t>(expo_adj_b, 0, 0xfffff);
output->config[0].expo_adj_r = CacClamp<uint32_t>(expo_adj_r, 0, 0xfffff);
#endif
#if (RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
if (current_lut_.size() > 1) {
output->config[1].buf_fd = current_lut_[1]->Fd;
if (output->config[0].center_en) {
uint16_t w = config_->width / 4;
uint16_t e = config_->multi_isp_extended_pixel / 4;
uint16_t x = attr_->persist_params.center_x;
output->config[1].center_width = x - (w / 2 - e);
}
}
#endif
}
#endif
output->enable = attr_->enable;
#if 0
LOGD_ACAC("global en : %d", output->enable);
LOGD_ACAC("center en: %d", output->config[0].center_en);
LOGD_ACAC("center x: %u", output->config[0].center_width);
LOGD_ACAC("center y: %u", output->config[0].center_height);
LOGD_ACAC("psf shift bits: %u", output->config[0].psf_sft_bit);
LOGD_ACAC("psf cfg num: %u", output->config[0].cfg_num);
LOGD_ACAC("psf buf fd: %d", output->config[0].buf_fd);
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
if (current_lut_.size() > 1) {
LOGD_ACAC("psf buf fd right: %d", output->config[1].buf_fd);
LOGD_ACAC("center x right: %d", output->config[1].center_width);
LOGD_ACAC("center y right: %d", output->config[1].center_height);
}
#endif
LOGD_ACAC("psf hwsize: %u", output->config[0].hsize);
LOGD_ACAC("psf vsize: %u", output->config[0].vsize);
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
LOGD_ACAC("strength %d: %u", i, output->config[0].strength[i]);
}
#if RKAIQ_HAVE_CAC_V11
LOGD_ACAC("clip_g_mode: %u", output->config[0].clip_g_mode);
LOGD_ACAC("edge_detect_en: %u", output->config[0].edge_detect_en);
LOGD_ACAC("neg_clip0_en: %u", output->config[0].neg_clip0_en);
LOGD_ACAC("expo_thed_b: %u", output->config[0].expo_thed_b);
LOGD_ACAC("expo_thed_r: %u", output->config[0].expo_thed_r);
LOGD_ACAC("expo_adj_b: %u", output->config[0].expo_adj_b);
LOGD_ACAC("expo_adj_r: %u", output->config[0].expo_adj_r);
LOGD_ACAC("flat_thed_b: %u", output->config[0].flat_thed_b);
LOGD_ACAC("flat_thed_r: %u", output->config[0].flat_thed_r);
#endif
#endif
}
} // namespace RkCam