You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
21 KiB
557 lines
21 KiB
#include "rk_aiq_isp39_modules.h"
|
|
#include "xcore/xcam_obj_debug.h"
|
|
#ifdef ANDROID_OS
|
|
#include <cutils/properties.h>
|
|
#endif
|
|
|
|
#define c_lsc_ram_d_bw 26 // double correction factor, must be even numbers
|
|
|
|
#define c_lsc_sample_bw (c_lsc_ram_d_bw/2) // bit width of the correction factor values stored in RAM
|
|
|
|
#define c_lsc_corr_bw 15 // bit width of the correction factor values used internal.
|
|
|
|
#define c_lsc_grad_exp 15 // fixed exponent for the x and y gradients
|
|
#define c_lsc_corr_extend 10 // extended fractal part of dx,dy of internal correction factor
|
|
// constraint : c_lsc_corr_extend <= c_lsc_grad_exp
|
|
#define c_extend_round (1 << (c_lsc_corr_extend - 1))
|
|
|
|
// bit width difference of correction factor values between used internal and stored in RAM
|
|
#define c_corr_diff (c_lsc_corr_bw - c_lsc_sample_bw)
|
|
|
|
#define c_dx_shift (c_lsc_grad_exp - c_lsc_corr_extend)
|
|
#define c_dx_round (1 << (c_dx_shift - 1))
|
|
#define c_dy_shift (c_lsc_grad_exp - c_lsc_corr_extend - c_corr_diff)
|
|
#define c_dy_round (1 << (c_dy_shift - 1))
|
|
|
|
static float _sampPos[17] = {
|
|
0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375, 0.5,
|
|
0.5625, 0.625, 0.6875, 0.75, 0.8125, 0.875, 0.9375, 1};
|
|
|
|
// #define WRITE_OTP_TABLE
|
|
|
|
static uint8_t g_cam_otp_lsc_bypass = 0;
|
|
|
|
static void computeSamplingPoint(int size, int* pos, float* pos_f)
|
|
{
|
|
if (pos_f == NULL) {
|
|
LOGW_ALSC("wrong position percent, set to equalSector!\n");
|
|
pos_f = _sampPos;
|
|
}
|
|
pos[0] = 0;
|
|
for (int i = 1; i < 17; i++)
|
|
{
|
|
pos[i] = (int)(pos_f[i] * size) - 1;
|
|
}
|
|
|
|
}
|
|
|
|
static void computeSamplingInterval(int width, int height, int *xInterval, int *yInterval)
|
|
{
|
|
int xpos[17];
|
|
int ypos[17];
|
|
|
|
computeSamplingPoint(width, xpos, NULL);
|
|
computeSamplingPoint(height, ypos, NULL);
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
xInterval[i] = xpos[i + 1] - xpos[i];
|
|
yInterval[i] = ypos[i + 1] - ypos[i];
|
|
}
|
|
|
|
xInterval[0] = xInterval[0] + 1;
|
|
yInterval[0] = yInterval[0] + 1;
|
|
}
|
|
|
|
static void computeGradient(int *xInterval, int *yInterval, int *xGradient, int *yGradient)
|
|
{
|
|
// gradient N = INT(2^15 / SizeN + 0.5)
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
xGradient[i] = (int)(32768.0 / (double)xInterval[i] + 0.5);
|
|
if (xGradient[i] > 8191)
|
|
{
|
|
xGradient[i] = 8191;
|
|
}
|
|
|
|
yGradient[i] = (int)(32768.0 / (double)yInterval[i] + 0.5);
|
|
if (yGradient[i] > 8191)
|
|
{
|
|
yGradient[i] = 8191;
|
|
}
|
|
}
|
|
}
|
|
|
|
void calculateCorrectFactor(uint16_t *table, uint16_t *correctTable, int width, int height, int *xInterval, int *yInterval)
|
|
{
|
|
int xGrad[16], yGrad[16];
|
|
int xblk, yblk;
|
|
uint16_t xbase, ybase, xoffset, yoffset;
|
|
uint16_t curSizeX, curSizeY, curGradX, curGradY;
|
|
uint16_t luCoeff, ldCoeff, ruCoeff, rdCoeff;
|
|
uint32_t lCoeff, rCoeff, coeff;
|
|
uint32_t tmp, tmp2;
|
|
|
|
computeGradient(xInterval, yInterval, xGrad, yGrad);
|
|
|
|
for (ybase = 0, yblk = 0; yblk < 16; yblk++)
|
|
{
|
|
curSizeY = yInterval[yblk];
|
|
curGradY = yGrad[yblk];
|
|
for (xbase = 0, xblk = 0; xblk < 16; xblk++)
|
|
{
|
|
curSizeX = xInterval[xblk];
|
|
curGradX = xGrad[xblk];
|
|
luCoeff = table[yblk * 17 + xblk];
|
|
ldCoeff = table[(yblk + 1) * 17 + xblk];
|
|
ruCoeff = table[yblk * 17 + xblk + 1];
|
|
rdCoeff = table[(yblk + 1) * 17 + xblk + 1];
|
|
for (yoffset = 0; yoffset < curSizeY; yoffset++)
|
|
{
|
|
tmp = abs(luCoeff - ldCoeff);
|
|
tmp = tmp * curGradY;
|
|
tmp = (tmp + c_dy_round) >> c_dy_shift;
|
|
tmp = tmp * yoffset;
|
|
tmp = (tmp + c_extend_round) >> c_lsc_corr_extend;
|
|
tmp = (tmp << (32 - c_lsc_corr_bw)) >> (32 - c_lsc_corr_bw);
|
|
lCoeff = luCoeff << c_corr_diff;
|
|
lCoeff = (luCoeff > ldCoeff) ? (lCoeff - tmp) : (lCoeff + tmp);
|
|
|
|
tmp = abs(ruCoeff - rdCoeff);
|
|
tmp = tmp * curGradY;
|
|
tmp = (tmp + c_dy_round) >> c_dy_shift;
|
|
tmp = tmp * yoffset;
|
|
tmp = (tmp + c_extend_round) >> c_lsc_corr_extend;
|
|
tmp = (tmp << (32 - c_lsc_corr_bw)) >> (32 - c_lsc_corr_bw);
|
|
rCoeff = ruCoeff << c_corr_diff;
|
|
rCoeff = (ruCoeff > rdCoeff) ? (rCoeff - tmp) : (rCoeff + tmp);
|
|
|
|
coeff = lCoeff << c_lsc_corr_extend;
|
|
tmp = abs((int)(rCoeff - lCoeff));
|
|
tmp = tmp * curGradX;
|
|
tmp = (tmp + c_dx_round) >> c_dx_shift;
|
|
for (xoffset = 0; xoffset < curSizeX; xoffset++)
|
|
{
|
|
tmp2 = (coeff + c_extend_round) >> c_lsc_corr_extend;
|
|
tmp2 = (tmp2 > ((1 << c_lsc_corr_bw) - 1)) ? ((1 << c_lsc_corr_bw) - 1) : tmp2;
|
|
*(correctTable + (ybase + yoffset) * width + (xbase + xoffset)) = (uint16_t)tmp2 >> c_corr_diff;
|
|
coeff = (lCoeff > rCoeff) ? (coeff - tmp) : (coeff + tmp);
|
|
}
|
|
}
|
|
xbase += curSizeX;
|
|
}
|
|
ybase += curSizeY;
|
|
}
|
|
}
|
|
|
|
static int getBayerIndex(uint8_t pattern, int row, int col)
|
|
{
|
|
int index = 0;
|
|
int x, y;
|
|
int tmp = 0;
|
|
|
|
x = row % 2;
|
|
y = col % 2;
|
|
tmp = (x << 1) + y;
|
|
|
|
if (pattern == 0)
|
|
{
|
|
index = tmp;
|
|
} else if (pattern == 1) {
|
|
switch (tmp)
|
|
{
|
|
case 0:
|
|
index = 1;
|
|
break;
|
|
case 1:
|
|
index = 0;
|
|
break;
|
|
case 2:
|
|
index = 3;
|
|
break;
|
|
case 3:
|
|
index = 2;
|
|
break;
|
|
}
|
|
} else if (pattern == 2) {
|
|
switch (tmp)
|
|
{
|
|
case 0:
|
|
index = 2;
|
|
break;
|
|
case 1:
|
|
index = 3;
|
|
break;
|
|
case 2:
|
|
index = 0;
|
|
break;
|
|
case 3:
|
|
index = 1;
|
|
break;
|
|
}
|
|
} else if (pattern == 3) {
|
|
index = 3 - tmp;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
static void getLscParameter(uint16_t *r, uint16_t *gr, uint16_t *gb, uint16_t *b, uint16_t *table, int width, int height, uint8_t bayer)
|
|
{
|
|
int bayerIdx;
|
|
int idx;
|
|
|
|
for (int i = 0; i < height; i++)
|
|
{
|
|
for (int j = 0; j < width; j++)
|
|
{
|
|
idx = i * width + j;
|
|
bayerIdx = getBayerIndex(bayer, i, j);
|
|
switch (bayerIdx)
|
|
{
|
|
case 0:
|
|
table[idx] = r[idx];
|
|
break;
|
|
case 1:
|
|
table[idx] = gr[idx];
|
|
break;
|
|
case 2:
|
|
table[idx] = gb[idx];
|
|
break;
|
|
case 3:
|
|
table[idx] = b[idx];
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void separateBayerChannel(uint16_t* src, uint16_t* disR, uint16_t* disGr, uint16_t* disGb, uint16_t* disB, int width, int height, uint8_t bayer)
|
|
{
|
|
int index = 0;
|
|
int bayerIdx = 0;
|
|
|
|
for (int i = 0; i < height; i++)
|
|
{
|
|
for (int j = 0; j < width; j++)
|
|
{
|
|
index = i * width + j;
|
|
bayerIdx = getBayerIndex(bayer, i, j);
|
|
switch (bayerIdx)
|
|
{
|
|
case 0:
|
|
*(disR++) = *(src + index);
|
|
break;
|
|
case 1:
|
|
*(disGr++) = *(src + index);
|
|
break;
|
|
case 2:
|
|
*(disGb++) = *(src + index);
|
|
break;
|
|
case 3:
|
|
*(disB++) = *(src + index);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void writeFile(char *fileName, uint16_t *buf)
|
|
{
|
|
FILE *fd = fopen(fileName, "wb");
|
|
if (fd == NULL)
|
|
printf("%s: open failed: %s\n", __func__, fileName);
|
|
else {
|
|
fwrite(buf, 1, LSC_DATA_TBL_SIZE * sizeof(uint16_t), fd);
|
|
fclose(fd);
|
|
}
|
|
}
|
|
|
|
static int lsc_meshgain_otp_resize(uint16_t width, uint16_t height, otplsc_res_cvt_t* otp_lsc,
|
|
uint8_t bayer_fmt, float* xPos_f, float* yPos_f)
|
|
{
|
|
XCAM_STATIC_PROFILING_START(lsc_meshgain_otp_resize);
|
|
|
|
int32_t srcLscWidth = otp_lsc->width;
|
|
int32_t srcLscHeight = otp_lsc->height;
|
|
int32_t dstWidth = width;
|
|
int32_t dstHeight = height;
|
|
|
|
if (dstWidth == srcLscWidth && height == srcLscHeight) {
|
|
return 1;
|
|
}
|
|
|
|
LOGD_ALSC("res for otp param (%dx%d) mismatch raw res (%dx%d)\n",
|
|
srcLscWidth, srcLscHeight, dstWidth, dstHeight);
|
|
|
|
if (dstWidth > srcLscWidth && dstHeight > srcLscHeight)
|
|
{
|
|
if ((dstWidth / 2 <= srcLscWidth) && (dstHeight / 2 <= srcLscHeight))
|
|
{
|
|
dstWidth = dstWidth / 2;
|
|
dstHeight = dstHeight / 2;
|
|
} else {
|
|
LOGE_ALSC("Failed to handle: the raw resolution exceeds!\n");
|
|
return 0;
|
|
}
|
|
} else if (dstWidth < srcLscWidth && dstHeight < srcLscHeight) {
|
|
if ((dstWidth <= srcLscWidth / 2) && (dstHeight <= srcLscHeight / 2))
|
|
{
|
|
srcLscWidth = srcLscWidth / 2;
|
|
srcLscHeight = srcLscHeight / 2;
|
|
}
|
|
}
|
|
|
|
uint32_t maxSize = srcLscWidth > srcLscHeight ? srcLscWidth : srcLscHeight;
|
|
uint32_t ratio = maxSize > 3200 ? 8 : (maxSize > 1600 ? 4 : (maxSize > 800 ? 2 : 1));
|
|
srcLscWidth = 2 * (int32_t)(srcLscWidth / (ratio * 2));
|
|
srcLscHeight = 2 * (int32_t)(srcLscHeight / (ratio * 2));
|
|
dstWidth = 2 * (int32_t)(dstWidth / (ratio * 2));
|
|
dstHeight = 2 * (int32_t)(dstHeight / (ratio * 2));
|
|
|
|
uint16_t *rTable = aiq_mallocz(sizeof(uint16_t) * srcLscWidth * srcLscHeight);
|
|
uint16_t *grTable = aiq_mallocz(sizeof(uint16_t) * srcLscWidth * srcLscHeight);
|
|
uint16_t *gbTable = aiq_mallocz(sizeof(uint16_t) * srcLscWidth * srcLscHeight);
|
|
uint16_t *bTable = aiq_mallocz(sizeof(uint16_t) * srcLscWidth * srcLscHeight);
|
|
uint16_t *corTable = aiq_mallocz(sizeof(uint16_t) * srcLscWidth * srcLscHeight);
|
|
uint16_t *corTable_crop = aiq_mallocz(sizeof(uint16_t) *dstWidth * dstHeight);
|
|
|
|
#ifdef WRITE_OTP_TABLE
|
|
char fileName[32] = {0};
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_r.bin");
|
|
writeFile(fileName, otp_lsc->lsc_r);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_b.bin");
|
|
writeFile(fileName, otp_lsc->lsc_b);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_gr.bin");
|
|
writeFile(fileName, otp_lsc->lsc_gr);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_gb.bin");
|
|
writeFile(fileName, otp_lsc->lsc_gb);
|
|
#endif
|
|
|
|
// Interpolate gain table back to full size
|
|
int sizeX[16];
|
|
int sizeY[16];
|
|
computeSamplingInterval(srcLscWidth, srcLscHeight, sizeX, sizeY);
|
|
calculateCorrectFactor(otp_lsc->lsc_r, rTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
|
|
calculateCorrectFactor(otp_lsc->lsc_gr, grTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
|
|
calculateCorrectFactor(otp_lsc->lsc_gb, gbTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
|
|
calculateCorrectFactor(otp_lsc->lsc_b, bTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
|
|
getLscParameter(rTable, grTable, gbTable, bTable, corTable,
|
|
srcLscWidth, srcLscHeight, bayer_fmt);
|
|
|
|
// Clipping a Gain table is centered by default
|
|
int cropoffsetx = srcLscWidth / 2 - dstWidth / 2;
|
|
int cropoffsety = srcLscHeight / 2 - dstHeight / 2;
|
|
|
|
if (cropoffsetx % 2 != 0)
|
|
cropoffsetx = cropoffsetx - 1;
|
|
if (cropoffsety % 2 != 0)
|
|
cropoffsety = cropoffsety -1;
|
|
|
|
for (int i = 0; i < dstHeight; i++)
|
|
{
|
|
memcpy(corTable_crop + i * dstWidth,
|
|
corTable + (cropoffsety + i)*srcLscWidth + cropoffsetx, dstWidth * 2);
|
|
}
|
|
|
|
aiq_free(rTable);
|
|
aiq_free(grTable);
|
|
aiq_free(gbTable);
|
|
aiq_free(bTable);
|
|
aiq_free(corTable);
|
|
|
|
// down-sampling again according to crop size
|
|
uint16_t *plscdataR = aiq_mallocz(sizeof(uint16_t) *dstWidth / 2 * dstHeight / 2);
|
|
uint16_t *plscdataGr = aiq_mallocz(sizeof(uint16_t) *dstWidth / 2 * dstHeight / 2);
|
|
uint16_t *plscdataGb = aiq_mallocz(sizeof(uint16_t) *dstWidth / 2 * dstHeight / 2);
|
|
uint16_t *plscdataB = aiq_mallocz(sizeof(uint16_t) *dstWidth / 2 * dstHeight / 2);
|
|
memset(plscdataR, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
|
|
memset(plscdataGr, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
|
|
memset(plscdataGb, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
|
|
memset(plscdataB, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
|
|
separateBayerChannel(corTable_crop, plscdataR, plscdataGr, plscdataGb, plscdataB, dstWidth, dstHeight, bayer_fmt);
|
|
|
|
int cPos[17]; // col sampling
|
|
int rPos[17]; // row sampling
|
|
computeSamplingPoint(dstWidth / 2, cPos, xPos_f);
|
|
computeSamplingPoint(dstHeight / 2, rPos, yPos_f);
|
|
int r, c;
|
|
for (int i = 0; i < 17; i++)
|
|
{
|
|
for (int j = 0; j < 17; j++)
|
|
{
|
|
r = rPos[i];
|
|
c = cPos[j];
|
|
*(otp_lsc->lsc_r + i * 17 + j) = plscdataR[r * dstWidth / 2 + c];
|
|
*(otp_lsc->lsc_gr + i * 17 + j) = plscdataGr[r * dstWidth / 2 + c];
|
|
*(otp_lsc->lsc_gb + i * 17 + j) = plscdataGb[r * dstWidth / 2 + c];
|
|
*(otp_lsc->lsc_b + i * 17 + j) = plscdataB[r * dstWidth / 2 + c];
|
|
}
|
|
}
|
|
|
|
otp_lsc->width = width;
|
|
otp_lsc->height = height;
|
|
|
|
#ifdef WRITE_OTP_TABLE
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_r.bin");
|
|
writeFile(fileName, otp_lsc->lsc_r);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_b.bin");
|
|
writeFile(fileName, otp_lsc->lsc_b);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_gr.bin");
|
|
writeFile(fileName, otp_lsc->lsc_gr);
|
|
snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_gb.bin");
|
|
writeFile(fileName, otp_lsc->lsc_gb);
|
|
#endif
|
|
|
|
aiq_free(plscdataR);
|
|
aiq_free(plscdataGr);
|
|
aiq_free(plscdataGb);
|
|
aiq_free(plscdataB);
|
|
aiq_free(corTable_crop);
|
|
|
|
LOGD_ALSC("crop otp LscMatrix r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n",
|
|
otp_lsc->lsc_r[0], otp_lsc->lsc_r[1], otp_lsc->lsc_r[2], otp_lsc->lsc_r[3],
|
|
otp_lsc->lsc_gr[0], otp_lsc->lsc_gr[1], otp_lsc->lsc_gr[2], otp_lsc->lsc_gr[3],
|
|
otp_lsc->lsc_gb[0], otp_lsc->lsc_gb[1], otp_lsc->lsc_gb[2], otp_lsc->lsc_gb[3],
|
|
otp_lsc->lsc_b[0], otp_lsc->lsc_b[1], otp_lsc->lsc_b[2], otp_lsc->lsc_b[3]);
|
|
|
|
XCAM_STATIC_PROFILING_END(lsc_meshgain_otp_resize, 0);
|
|
return 1;
|
|
}
|
|
|
|
bool rk_aiq_lsc21_params_check(void* attr, common_cvt_info_t *cvtinfo)
|
|
{
|
|
//TODO: check if sum of x_size_tbl == raw width
|
|
//TODO: check if sum of y_size_tbl == raw height
|
|
|
|
return true;
|
|
}
|
|
|
|
static void lsc_meshgain_otp_cvt(uint16_t* meshGain_in, uint16_t* meshGain_otp, uint16_t* meshGain_out)
|
|
{
|
|
if (!meshGain_in || !meshGain_otp) {
|
|
LOGE_ALSC("%s: input params is error!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
for (int32_t i = 0; i < LSC_DATA_TBL_SIZE; i++) {
|
|
meshGain_out[i] = CLIPBIT(((int)meshGain_in[i] * (int)meshGain_otp[i] + 512) >> 10, 13);
|
|
}
|
|
}
|
|
|
|
void rk_aiq_lsc21_params_cvt(void* attr, isp_params_t* isp_params, common_cvt_info_t *cvtinfo)
|
|
{
|
|
int i;
|
|
struct isp3x_lsc_cfg * pFix = &isp_params->isp_cfg->others.lsc_cfg;
|
|
lsc_param_t *lsc_param = (lsc_param_t *) attr;
|
|
lsc_param_dyn_t * pdyn = &lsc_param->dyn;
|
|
lsc_param_static_t * psta = &lsc_param->sta;
|
|
|
|
pFix->sector_16x16 = 1;
|
|
|
|
switch (psta->sw_lscT_meshGrid_mode) {
|
|
case lsc_usrConfig_mode: {
|
|
uint16_t x0, x1, y0, y1;
|
|
x0 = (uint16_t)(psta->meshGrid.posX_f[0] * (float)cvtinfo->rawWidth);
|
|
y0 = (uint16_t)(psta->meshGrid.posY_f[0] * (float)cvtinfo->rawHeight);
|
|
for (i=0; i<LSC_MESHGRID_SIZE; i++) {
|
|
x1 = (uint16_t)(psta->meshGrid.posX_f[i+1] * (float)cvtinfo->rawWidth);
|
|
y1 = (uint16_t)(psta->meshGrid.posY_f[i+1] * (float)cvtinfo->rawHeight);
|
|
pFix->x_size_tbl[i] = x1 - x0;
|
|
pFix->y_size_tbl[i] = y1 - y0;
|
|
x0 = x1;
|
|
y0 = y1;
|
|
|
|
pFix->x_grad_tbl[i] = (uint16_t)((double)(1UL << 15) / pFix->x_size_tbl[i] + 0.5);
|
|
pFix->y_grad_tbl[i] = (uint16_t)((double)(1UL << 15) / pFix->y_size_tbl[i] + 0.5);
|
|
}
|
|
} break;
|
|
case lsc_vendorDefault_mode:
|
|
case lsc_equalSector_mode: {
|
|
for (i=0; i<LSC_MESHGRID_SIZE; i++) {
|
|
pFix->x_size_tbl[i] = (uint16_t)(_sampPos[i+1] * (float)cvtinfo->rawWidth) - (uint16_t)(_sampPos[i] * (float)cvtinfo->rawWidth);
|
|
pFix->y_size_tbl[i] = (uint16_t)(_sampPos[i+1] * (float)cvtinfo->rawHeight) - (uint16_t)(_sampPos[i] * (float)cvtinfo->rawHeight);
|
|
pFix->x_grad_tbl[i] = (uint16_t)((double)(1UL << 15) / pFix->x_size_tbl[i] + 0.5);
|
|
pFix->y_grad_tbl[i] = (uint16_t)((double)(1UL << 15) / pFix->y_size_tbl[i] + 0.5);
|
|
}
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// if x/y_size_tbl changed, otp_lsc.flag should be false
|
|
if (cvtinfo->otp_lsc.flag) {
|
|
if (0 != memcmp(cvtinfo->otplsc_res.x_size_tbl, pFix->x_size_tbl, sizeof(pFix->x_size_tbl)))
|
|
{
|
|
memcpy(cvtinfo->otplsc_res.x_size_tbl, pFix->x_size_tbl, sizeof(pFix->x_size_tbl));
|
|
cvtinfo->otplsc_res.flag = false;
|
|
}
|
|
if (0 != memcmp(cvtinfo->otplsc_res.y_size_tbl, pFix->y_size_tbl, sizeof(pFix->y_size_tbl)))
|
|
{
|
|
memcpy(cvtinfo->otplsc_res.y_size_tbl, pFix->y_size_tbl, sizeof(pFix->y_size_tbl));
|
|
cvtinfo->otplsc_res.flag = false;
|
|
}
|
|
}
|
|
|
|
if (cvtinfo->otp_lsc.flag && !cvtinfo->otplsc_res.flag) {
|
|
cvtinfo->otplsc_res.width = cvtinfo->otp_lsc.width;
|
|
cvtinfo->otplsc_res.height = cvtinfo->otp_lsc.height;
|
|
memcpy(cvtinfo->otplsc_res.lsc_r, cvtinfo->otp_lsc.lsc_r, sizeof(cvtinfo->otplsc_res.lsc_r));
|
|
memcpy(cvtinfo->otplsc_res.lsc_gr, cvtinfo->otp_lsc.lsc_gr, sizeof(cvtinfo->otplsc_res.lsc_gr));
|
|
memcpy(cvtinfo->otplsc_res.lsc_gb, cvtinfo->otp_lsc.lsc_gb, sizeof(cvtinfo->otplsc_res.lsc_gb));
|
|
memcpy(cvtinfo->otplsc_res.lsc_b, cvtinfo->otp_lsc.lsc_b, sizeof(cvtinfo->otplsc_res.lsc_b));
|
|
int ret = 0;
|
|
if (psta->sw_lscT_meshGrid_mode == lsc_usrConfig_mode) {
|
|
ret = lsc_meshgain_otp_resize(cvtinfo->rawWidth, cvtinfo->rawHeight,
|
|
&cvtinfo->otplsc_res, cvtinfo->bayer_fmt,
|
|
psta->meshGrid.posX_f, psta->meshGrid.posY_f);
|
|
} else {
|
|
ret = lsc_meshgain_otp_resize(cvtinfo->rawWidth, cvtinfo->rawHeight, &cvtinfo->otplsc_res,
|
|
cvtinfo->bayer_fmt, NULL, NULL);
|
|
}
|
|
cvtinfo->otplsc_res.flag = ret;
|
|
}
|
|
|
|
#ifdef ANDROID_OS
|
|
char property_value[PROPERTY_VALUE_MAX] = {0};
|
|
char property_value_default[PROPERTY_VALUE_MAX] = {0};
|
|
sprintf(property_value_default, "%d", g_cam_otp_lsc_bypass);
|
|
property_get("persist.vendor.rkisp.otplsc.bypass", property_value, property_value_default);
|
|
g_cam_otp_lsc_bypass = strtoull(property_value, NULL, 0);
|
|
#else
|
|
char* valueStr = getenv("persist_camera_otp_lsc_bypass");
|
|
if (valueStr) {
|
|
g_cam_otp_lsc_bypass = strtoull(valueStr, NULL, 0);
|
|
}
|
|
#endif
|
|
|
|
if (!g_cam_otp_lsc_bypass && cvtinfo->otplsc_res.flag) {
|
|
lsc_meshgain_otp_cvt(pdyn->meshGain.hw_lscC_gainR_val, cvtinfo->otplsc_res.lsc_r, pFix->r_data_tbl);
|
|
lsc_meshgain_otp_cvt(pdyn->meshGain.hw_lscC_gainGr_val, cvtinfo->otplsc_res.lsc_gr, pFix->gr_data_tbl);
|
|
lsc_meshgain_otp_cvt(pdyn->meshGain.hw_lscC_gainGb_val, cvtinfo->otplsc_res.lsc_gb, pFix->gb_data_tbl);
|
|
lsc_meshgain_otp_cvt(pdyn->meshGain.hw_lscC_gainB_val, cvtinfo->otplsc_res.lsc_b, pFix->b_data_tbl);
|
|
|
|
LOGD_ALSC("hwi otp r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n",
|
|
pFix->r_data_tbl[0], pFix->r_data_tbl[1], pFix->r_data_tbl[2], pFix->r_data_tbl[3],
|
|
pFix->gr_data_tbl[0], pFix->gr_data_tbl[1], pFix->gr_data_tbl[2], pFix->gr_data_tbl[3],
|
|
pFix->gb_data_tbl[0], pFix->gb_data_tbl[1], pFix->gb_data_tbl[2], pFix->gb_data_tbl[3],
|
|
pFix->b_data_tbl[0], pFix->b_data_tbl[1], pFix->b_data_tbl[2], pFix->b_data_tbl[3]);
|
|
} else {
|
|
if (cvtinfo->otplsc_res.flag) {
|
|
LOGK_ALSC("lsc otp disable by g_cam_otp_lsc_bypass! \n");
|
|
}
|
|
for (i=0; i<LSC_LSCTABLE_SIZE; i++) {
|
|
pFix->r_data_tbl[i] = CLIPBIT(pdyn->meshGain.hw_lscC_gainR_val[i], 13);
|
|
pFix->gr_data_tbl[i] = CLIPBIT(pdyn->meshGain.hw_lscC_gainGr_val[i], 13);
|
|
pFix->gb_data_tbl[i] = CLIPBIT(pdyn->meshGain.hw_lscC_gainGb_val[i], 13);
|
|
pFix->b_data_tbl[i] = CLIPBIT(pdyn->meshGain.hw_lscC_gainB_val[i], 13);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|