diff --git a/middleware/v2/component/isp/sensor.mk b/middleware/v2/component/isp/sensor.mk index fda412aa9..f2778bdce 100644 --- a/middleware/v2/component/isp/sensor.mk +++ b/middleware/v2/component/isp/sensor.mk @@ -108,6 +108,7 @@ sensor-$(CONFIG_SENSOR_SMS_SC531AI_2L) += sms_sc531ai_2L sensor-$(CONFIG_SENSOR_SMS_SC3332) += sms_sc3332 sensor-$(CONFIG_SENSOR_SMS_SC3335) += sms_sc3335 sensor-$(CONFIG_SENSOR_SMS_SC3336) += sms_sc3336 +sensor-$(CONFIG_SENSOR_SMS_SC3336_1L) += sms_sc3336_1L sensor-$(CONFIG_SENSOR_SMS_SC3336P) += sms_sc3336p sensor-$(CONFIG_SENSOR_SMS_SC2331_1L) += sms_sc2331_1L sensor-$(CONFIG_SENSOR_SMS_SC2331_1L_SLAVE) += sms_sc2331_1L_slave diff --git a/middleware/v2/component/isp/sensor/cv182x/Makefile b/middleware/v2/component/isp/sensor/cv182x/Makefile index 5b865b7e9..c11102548 100644 --- a/middleware/v2/component/isp/sensor/cv182x/Makefile +++ b/middleware/v2/component/isp/sensor/cv182x/Makefile @@ -191,6 +191,9 @@ sms_sc3335: sms_sc3336: $(call MAKE_SENSOR, ${@}) +sms_sc3336_1L: + $(call MAKE_SENSOR, ${@}) + sms_sc3336p: $(call MAKE_SENSOR, ${@}) diff --git a/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/Makefile b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/Makefile new file mode 100644 index 000000000..1ec6701d0 --- /dev/null +++ b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/Makefile @@ -0,0 +1,36 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE=../../../../../../$(shell echo $(MW_VER))/Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD) +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I$(MW_INC) -I$(ISP_INC) -I$(KERNEL_INC) -I./include +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libsns_sc3336_1l.a +TARGET_SO = $(MW_LIB)/libsns_sc3336_1l.so + +EXTRA_CFLAGS = $(INCS) +EXTRA_LDFLAGS = + +.PHONY : clean all +all : $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@ + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $@ $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos.c b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos.c new file mode 100644 index 000000000..9f8116411 --- /dev/null +++ b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos.c @@ -0,0 +1,946 @@ +#include +#include +#include +#include +#include +#include +#ifdef ARCH_CV182X +#include "cvi_type.h" +#include "cvi_comm_video.h" +#include +#else +#include +#include +#include +#endif +#include "cvi_debug.h" +#include "cvi_comm_sns.h" +#include "cvi_sns_ctrl.h" +#include "cvi_ae_comm.h" +#include "cvi_awb_comm.h" +#include "cvi_ae.h" +#include "cvi_awb.h" +#include "cvi_isp.h" + +#include "sc3336_1L_cmos_ex.h" +#include "sc3336_1L_cmos_param.h" + +#define DIV_0_TO_1(a) ((0 == (a)) ? 1 : (a)) +#define DIV_0_TO_1_FLOAT(a) ((((a) < 1E-10) && ((a) > -1E-10)) ? 1 : (a)) +#define SC3336_1L_ID 3336 +#define SC3336_1L_I2C_ADDR_1 0x30 +#define SC3336_1L_I2C_ADDR_2 0x32 +#define SC3336_1L_I2C_ADDR_IS_VALID(addr) ((addr) == SC3336_1L_I2C_ADDR_1 || (addr) == SC3336_1L_I2C_ADDR_2) + +/**************************************************************************** + * global variables * + ****************************************************************************/ + +ISP_SNS_STATE_S *g_pastSC3336_1L[VI_MAX_PIPE_NUM] = {CVI_NULL}; + +#define SC3336_1L_SENSOR_GET_CTX(dev, pstCtx) (pstCtx = g_pastSC3336_1L[dev]) +#define SC3336_1L_SENSOR_SET_CTX(dev, pstCtx) (g_pastSC3336_1L[dev] = pstCtx) +#define SC3336_1L_SENSOR_RESET_CTX(dev) (g_pastSC3336_1L[dev] = CVI_NULL) + +ISP_SNS_COMMBUS_U g_aunSC3336_1L_BusInfo[VI_MAX_PIPE_NUM] = { + [0] = { .s8I2cDev = 2}, + [1 ... VI_MAX_PIPE_NUM - 1] = { .s8I2cDev = -1} +}; + +CVI_U16 g_au16SC3336_1L_GainMode[VI_MAX_PIPE_NUM] = {0}; +CVI_U16 g_au16SC3336_1L_L2SMode[VI_MAX_PIPE_NUM] = {0}; + +ISP_SNS_MIRRORFLIP_TYPE_E g_aeSC3336_1L_MirrorFip[VI_MAX_PIPE_NUM] = {0}; + +/**************************************************************************** + * local variables and functions * + ****************************************************************************/ +static CVI_U32 g_au32InitExposure[VI_MAX_PIPE_NUM] = {0}; +static CVI_U32 g_au32LinesPer500ms[VI_MAX_PIPE_NUM] = {0}; +static CVI_U16 g_au16InitWBGain[VI_MAX_PIPE_NUM][3] = {{0} }; +static CVI_U16 g_au16SampleRgain[VI_MAX_PIPE_NUM] = {0}; +static CVI_U16 g_au16SampleBgain[VI_MAX_PIPE_NUM] = {0}; +static CVI_S32 cmos_get_wdr_size(VI_PIPE ViPipe, ISP_SNS_ISP_INFO_S *pstIspCfg); +/*****SC3336_1L Lines Range*****/ +#define SC3336_1L_FULL_LINES_MAX (0x7FFF) + +/*****SC3336_1L Register Address*****/ +#define SC3336_1L_EXP_H_ADDR (0x3e00) +#define SC3336_1L_EXP_M_ADDR (0x3e01) +#define SC3336_1L_EXP_L_ADDR (0x3e02) + +#define SC3336_1L_AGAIN_ADDR (0x3e09) + +#define SC3336_1L_DGAIN_H_ADDR (0x3e06) +#define SC3336_1L_DGAIN_L_ADDR (0x3e07) + +#define SC3336_1L_VMAX_H_ADDR (0x320e) +#define SC3336_1L_VMAX_L_ADDR (0x320f) + +#define SC3336_1L_RES_IS_1296P(w, h) ((w) == 2304 && (h) == 1296) + +#define SC3336_1L_EXPACCURACY (1) + +static CVI_S32 cmos_get_ae_default(VI_PIPE ViPipe, AE_SENSOR_DEFAULT_S *pstAeSnsDft) +{ + const SC3336_1L_MODE_S *pstMode; + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + CMOS_CHECK_POINTER(pstAeSnsDft); + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + + pstMode = &g_astSC3336_1L_mode[pstSnsState->u8ImgMode]; +#if 0 + memset(&pstAeSnsDft->stAERouteAttr, 0, sizeof(ISP_AE_ROUTE_S)); +#endif + pstAeSnsDft->u32FullLinesStd = pstSnsState->u32FLStd; + pstAeSnsDft->u32FlickerFreq = 50 * 256; + pstAeSnsDft->u32FullLinesMax = SC3336_1L_FULL_LINES_MAX; + pstAeSnsDft->u32HmaxTimes = (1000000) / (pstSnsState->u32FLStd * 20); + + pstAeSnsDft->stIntTimeAccu.enAccuType = AE_ACCURACY_LINEAR; + pstAeSnsDft->stIntTimeAccu.f32Accuracy = SC3336_1L_EXPACCURACY; + pstAeSnsDft->stIntTimeAccu.f32Offset = 0; + + pstAeSnsDft->stAgainAccu.enAccuType = AE_ACCURACY_TABLE; + pstAeSnsDft->stAgainAccu.f32Accuracy = 1; + + pstAeSnsDft->stDgainAccu.enAccuType = AE_ACCURACY_TABLE; + pstAeSnsDft->stDgainAccu.f32Accuracy = 1; + + pstAeSnsDft->u32ISPDgainShift = 8; + pstAeSnsDft->u32MinISPDgainTarget = 1 << pstAeSnsDft->u32ISPDgainShift; + pstAeSnsDft->u32MaxISPDgainTarget = 2 << pstAeSnsDft->u32ISPDgainShift; + + if (g_au32LinesPer500ms[ViPipe] == 0) + pstAeSnsDft->u32LinesPer500ms = pstSnsState->u32FLStd * 20 / 2; + else + pstAeSnsDft->u32LinesPer500ms = g_au32LinesPer500ms[ViPipe]; + pstAeSnsDft->u32SnsStableFrame = 0; +#if 0 + pstAeSnsDft->enMaxIrisFNO = ISP_IRIS_F_NO_1_0; + pstAeSnsDft->enMinIrisFNO = ISP_IRIS_F_NO_32_0; + + pstAeSnsDft->bAERouteExValid = CVI_FALSE; + pstAeSnsDft->stAERouteAttr.u32TotalNum = 0; + pstAeSnsDft->stAERouteAttrEx.u32TotalNum = 0; +#endif + switch (pstSnsState->enWDRMode) { + case WDR_MODE_NONE: /*linear mode*/ + pstAeSnsDft->f32Fps = pstMode->f32MaxFps; + pstAeSnsDft->f32MinFps = pstMode->f32MinFps; + pstAeSnsDft->au8HistThresh[0] = 0xd; + pstAeSnsDft->au8HistThresh[1] = 0x28; + pstAeSnsDft->au8HistThresh[2] = 0x60; + pstAeSnsDft->au8HistThresh[3] = 0x80; + + pstAeSnsDft->u32MaxAgain = pstMode->stAgain[0].u16Max; + pstAeSnsDft->u32MinAgain = pstMode->stAgain[0].u16Min; + pstAeSnsDft->u32MaxAgainTarget = pstAeSnsDft->u32MaxAgain; + pstAeSnsDft->u32MinAgainTarget = pstAeSnsDft->u32MinAgain; + + pstAeSnsDft->u32MaxDgain = pstMode->stDgain[0].u16Max; + pstAeSnsDft->u32MinDgain = pstMode->stDgain[0].u16Min; + pstAeSnsDft->u32MaxDgainTarget = pstAeSnsDft->u32MaxDgain; + pstAeSnsDft->u32MinDgainTarget = pstAeSnsDft->u32MinDgain; + + pstAeSnsDft->u8AeCompensation = 40; + pstAeSnsDft->u32InitAESpeed = 64; + pstAeSnsDft->u32InitAETolerance = 5; + pstAeSnsDft->u32AEResponseFrame = 4; + pstAeSnsDft->enAeExpMode = AE_EXP_HIGHLIGHT_PRIOR; + pstAeSnsDft->u32InitExposure = g_au32InitExposure[ViPipe] ? g_au32InitExposure[ViPipe] : 76151; + + pstAeSnsDft->u32MaxIntTime = pstMode->stExp[0].u16Max; + pstAeSnsDft->u32MinIntTime = pstMode->stExp[0].u16Min; + pstAeSnsDft->u32MaxIntTimeTarget = pstAeSnsDft->u32MaxIntTime; + pstAeSnsDft->u32MinIntTimeTarget = pstAeSnsDft->u32MinIntTime; + break; + default: + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support WDR: %d\n", pstSnsState->enWDRMode); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +/* the function of sensor set fps */ +static CVI_S32 cmos_fps_set(VI_PIPE ViPipe, CVI_FLOAT f32Fps, AE_SENSOR_DEFAULT_S *pstAeSnsDft) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + CVI_U32 u32VMAX; + CVI_FLOAT f32MaxFps = 0; + CVI_FLOAT f32MinFps = 0; + CVI_U32 u32Vts = 0; + ISP_SNS_REGS_INFO_S *pstSnsRegsInfo = CVI_NULL; + + CMOS_CHECK_POINTER(pstAeSnsDft); + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + + u32Vts = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].u32VtsDef; + pstSnsRegsInfo = &pstSnsState->astSyncInfo[0].snsCfg; + f32MaxFps = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].f32MaxFps; + f32MinFps = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].f32MinFps; + + switch (pstSnsState->u8ImgMode) { + case SC3336_1L_MODE_2304X1296P20: + if ((f32Fps <= f32MaxFps) && (f32Fps >= f32MinFps)) { + u32VMAX = u32Vts * f32MaxFps / DIV_0_TO_1_FLOAT(f32Fps); + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support Fps: %f\n", f32Fps); + return CVI_FAILURE; + } + u32VMAX = (u32VMAX > SC3336_1L_FULL_LINES_MAX) ? SC3336_1L_FULL_LINES_MAX : u32VMAX; + break; + default: + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support sensor mode: %d\n", pstSnsState->u8ImgMode); + return CVI_FAILURE; + } + + pstSnsState->u32FLStd = u32VMAX; + + if (pstSnsState->enWDRMode == WDR_MODE_NONE) { + pstSnsRegsInfo->astI2cData[LINEAR_VMAX_H_ADDR].u32Data = ((u32VMAX & 0xFF00) >> 8); + pstSnsRegsInfo->astI2cData[LINEAR_VMAX_L_ADDR].u32Data = (u32VMAX & 0xFF); + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support WDR: %d\n", pstSnsState->enWDRMode); + return CVI_FAILURE; + } + + pstAeSnsDft->f32Fps = f32Fps; + pstAeSnsDft->u32LinesPer500ms = pstSnsState->u32FLStd * f32Fps / 2; + pstAeSnsDft->u32FullLinesStd = pstSnsState->u32FLStd; + pstAeSnsDft->u32MaxIntTime = pstSnsState->u32FLStd - 10; + pstSnsState->au32FL[0] = pstSnsState->u32FLStd; + pstAeSnsDft->u32FullLines = pstSnsState->au32FL[0]; + pstAeSnsDft->u32HmaxTimes = (1000000) / (pstSnsState->u32FLStd * DIV_0_TO_1_FLOAT(f32Fps)); + + return CVI_SUCCESS; +} + +/* while isp notify ae to update sensor regs, ae call these funcs. */ +static CVI_S32 cmos_inttime_update(VI_PIPE ViPipe, CVI_U32 *u32IntTime) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + ISP_SNS_REGS_INFO_S *pstSnsRegsInfo = CVI_NULL; + CVI_U32 u32TmpIntTime, u32MinTime, u32MaxTime; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + CMOS_CHECK_POINTER(u32IntTime); + pstSnsRegsInfo = &pstSnsState->astSyncInfo[0].snsCfg; + + if (pstSnsState->enWDRMode == WDR_MODE_NONE) { + /* linear exposure reg range: + * min : 0 + * max : vts - 10 + * step : 1 + */ + u32MinTime = 0; + u32MaxTime = pstSnsState->au32FL[0] - 10; + u32TmpIntTime = (u32IntTime[0] > u32MaxTime) ? u32MaxTime : u32IntTime[0]; + u32TmpIntTime = (u32TmpIntTime < u32MinTime) ? u32MinTime : u32TmpIntTime; + + pstSnsRegsInfo->astI2cData[LINEAR_EXP_H_ADDR].u32Data = ((u32TmpIntTime & 0xF000) >> 12); + pstSnsRegsInfo->astI2cData[LINEAR_EXP_M_ADDR].u32Data = ((u32TmpIntTime & 0x0FF0) >> 4); + pstSnsRegsInfo->astI2cData[LINEAR_EXP_L_ADDR].u32Data = ((u32TmpIntTime & 0x000F) << 4); + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support WDR: %d\n", pstSnsState->enWDRMode); + return CVI_FAILURE; + } + + return CVI_SUCCESS; + +} + +typedef struct gain_tbl_info_s { + CVI_U16 gainMax; + CVI_U16 idxBase; + CVI_U8 regGain; + CVI_U8 regGainFineBase; + CVI_U8 regGainFineStep; +} gain_tbl_info_s; + +static struct gain_tbl_info_s DgainInfo[4] = { + { + .gainMax = 2016, + .idxBase = 0, + .regGain = 0x00, + .regGainFineBase = 0x80, + .regGainFineStep = 4, + }, + { + .gainMax = 4032, + .idxBase = 32, + .regGain = 0x01, + .regGainFineBase = 0x80, + .regGainFineStep = 4, + }, + { + .gainMax = 8064, + .idxBase = 64, + .regGain = 0x03, + .regGainFineBase = 0x80, + .regGainFineStep = 4, + }, + { + .gainMax = 16128, + .idxBase = 96, + .regGain = 0x07, + .regGainFineBase = 0x80, + .regGainFineStep = 4, + }, +}; + +static CVI_U32 Dgain_table[128] = { + 1024, 1055, 1088, 1120, 1152, 1183, 1216, 1248, 1280, 1311, 1344, 1376, + 1408, 1439, 1472, 1504, 1536, 1567, 1600, 1632, 1664, 1695, 1728, 1760, + 1792, 1823, 1856, 1888, 1920, 1951, 1984, 2016, 2048, 2112, 2176, 2240, + 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, + 3072, 3136, 3200, 3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, + 3840, 3904, 3968, 4032, 4096, 4224, 4352, 4480, 4608, 4736, 4864, 4992, + 5120, 5248, 5376, 5504, 5632, 5760, 5888, 6016, 6144, 6272, 6400, 6528, + 6656, 6784, 6912, 7040, 7168, 7296, 7424, 7552, 7680, 7808, 7936, 8064, + 8192, 8448, 8704, 8960, 9216, 9472, 9728, 9984, 10240, 10496, 10752, 11008, + 11264, 11520, 11776, 12032, 12288, 12544, 12800, 13056, 13312, 13568, 13824, + 14080, 14336, 14592, 14848, 15104, 15360, 15616, 15872, 16128 +}; + +static CVI_S32 cmos_again_calc_table(VI_PIPE ViPipe, CVI_U32 *pu32AgainLin, CVI_U32 *pu32AgainDb) +{ + CVI_U32 again = *pu32AgainLin; + + (void) ViPipe; + + CMOS_CHECK_POINTER(pu32AgainLin); + CMOS_CHECK_POINTER(pu32AgainDb); + + if (again < 1556) { + *pu32AgainDb = 0x00; + *pu32AgainLin = 1024; + } else if (again < 3122) { + *pu32AgainDb = 0x40; + *pu32AgainLin = 1556; + } else if (again < 6225) { + *pu32AgainDb = 0x48; + *pu32AgainLin = 3122; + } else if (again < 12451) { + *pu32AgainDb = 0x49; + *pu32AgainLin = 6225; + } else if (again < 24903) { + *pu32AgainDb = 0x4b; + *pu32AgainLin = 12451; + } else if (again < 49807) { + *pu32AgainDb = 0x4f; + *pu32AgainLin = 24903; + } else { + *pu32AgainDb = 0x5f; + *pu32AgainLin = 49807; + } + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_dgain_calc_table(VI_PIPE ViPipe, CVI_U32 *pu32DgainLin, CVI_U32 *pu32DgainDb) +{ + int i; + + (void) ViPipe; + + CMOS_CHECK_POINTER(pu32DgainLin); + CMOS_CHECK_POINTER(pu32DgainDb); + + if (*pu32DgainLin >= Dgain_table[127]) { + *pu32DgainLin = Dgain_table[127]; + *pu32DgainDb = 127; + return CVI_SUCCESS; + } + + for (i = 1; i < 128; i++) { + if (*pu32DgainLin < Dgain_table[i]) { + *pu32DgainLin = Dgain_table[i - 1]; + *pu32DgainDb = i - 1; + break; + } + } + return CVI_SUCCESS; +} + +static CVI_S32 cmos_gains_update(VI_PIPE ViPipe, CVI_U32 *pu32Again, CVI_U32 *pu32Dgain) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + ISP_SNS_REGS_INFO_S *pstSnsRegsInfo = CVI_NULL; + CVI_U32 u32Again; + CVI_U32 u32Dgain; + struct gain_tbl_info_s *info; + int i, tbl_num; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + CMOS_CHECK_POINTER(pu32Again); + CMOS_CHECK_POINTER(pu32Dgain); + pstSnsRegsInfo = &pstSnsState->astSyncInfo[0].snsCfg; + + u32Again = pu32Again[0]; + u32Dgain = pu32Dgain[0]; + + if (pstSnsState->enWDRMode == WDR_MODE_NONE) { + /* linear mode */ + + /* find Again register setting. */ + pstSnsRegsInfo->astI2cData[LINEAR_AGAIN_ADDR].u32Data = (u32Again & 0xFF); + + /* find Dgain register setting. */ + tbl_num = sizeof(DgainInfo)/sizeof(struct gain_tbl_info_s); + for (i = tbl_num - 1; i >= 0; i--) { + info = &DgainInfo[i]; + + if (u32Dgain >= info->idxBase) + break; + } + + pstSnsRegsInfo->astI2cData[LINEAR_DGAIN_H_ADDR].u32Data = (info->regGain & 0xFF); + u32Dgain = info->regGainFineBase + (u32Dgain - info->idxBase) * info->regGainFineStep; + pstSnsRegsInfo->astI2cData[LINEAR_DGAIN_L_ADDR].u32Data = (u32Dgain & 0xFF); + + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support WDR: %d\n", pstSnsState->enWDRMode); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_init_ae_exp_function(AE_SENSOR_EXP_FUNC_S *pstExpFuncs) +{ + CMOS_CHECK_POINTER(pstExpFuncs); + + memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S)); + + pstExpFuncs->pfn_cmos_get_ae_default = cmos_get_ae_default; + pstExpFuncs->pfn_cmos_fps_set = cmos_fps_set; + //pstExpFuncs->pfn_cmos_slow_framerate_set = cmos_slow_framerate_set; + pstExpFuncs->pfn_cmos_inttime_update = cmos_inttime_update; + pstExpFuncs->pfn_cmos_gains_update = cmos_gains_update; + pstExpFuncs->pfn_cmos_again_calc_table = cmos_again_calc_table; + pstExpFuncs->pfn_cmos_dgain_calc_table = cmos_dgain_calc_table; + //pstExpFuncs->pfn_cmos_get_inttime_max = cmos_get_inttime_max; + //pstExpFuncs->pfn_cmos_ae_fswdr_attr_set = cmos_ae_fswdr_attr_set; + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_get_awb_default(VI_PIPE ViPipe, AWB_SENSOR_DEFAULT_S *pstAwbSnsDft) +{ + (void) ViPipe; + + CMOS_CHECK_POINTER(pstAwbSnsDft); + + memset(pstAwbSnsDft, 0, sizeof(AWB_SENSOR_DEFAULT_S)); + + pstAwbSnsDft->u16InitGgain = 1024; + pstAwbSnsDft->u8AWBRunInterval = 1; + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_init_awb_exp_function(AWB_SENSOR_EXP_FUNC_S *pstExpFuncs) +{ + CMOS_CHECK_POINTER(pstExpFuncs); + + memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S)); + + pstExpFuncs->pfn_cmos_get_awb_default = cmos_get_awb_default; + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_get_isp_default(VI_PIPE ViPipe, ISP_CMOS_DEFAULT_S *pstDef) +{ + (void) ViPipe; + + memset(pstDef, 0, sizeof(ISP_CMOS_DEFAULT_S)); + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_get_blc_default(VI_PIPE ViPipe, ISP_CMOS_BLACK_LEVEL_S *pstBlc) +{ + (void) ViPipe; + + CMOS_CHECK_POINTER(pstBlc); + + memset(pstBlc, 0, sizeof(ISP_CMOS_BLACK_LEVEL_S)); + + memcpy(pstBlc, &g_stIspBlcCalibratio, sizeof(ISP_CMOS_BLACK_LEVEL_S)); + return CVI_SUCCESS; +} + +static CVI_S32 cmos_get_wdr_size(VI_PIPE ViPipe, ISP_SNS_ISP_INFO_S *pstIspCfg) +{ + const SC3336_1L_MODE_S *pstMode = CVI_NULL; + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + pstMode = &g_astSC3336_1L_mode[pstSnsState->u8ImgMode]; + + pstIspCfg->frm_num = 1; + memcpy(&pstIspCfg->img_size[0], &pstMode->astImg[0], sizeof(ISP_WDR_SIZE_S)); + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_set_wdr_mode(VI_PIPE ViPipe, CVI_U8 u8Mode) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + + pstSnsState->bSyncInit = CVI_FALSE; + + switch (u8Mode) { + case WDR_MODE_NONE: + pstSnsState->u8ImgMode = SC3336_1L_MODE_2304X1296P20; + pstSnsState->enWDRMode = WDR_MODE_NONE; + pstSnsState->u32FLStd = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].u32VtsDef; + syslog(LOG_INFO, "linear mode\n"); + break; + default: + CVI_TRACE_SNS(CVI_DBG_ERR, "NOT support this mode!\n"); + return CVI_FAILURE; + } + + pstSnsState->au32FL[0] = pstSnsState->u32FLStd; + pstSnsState->au32FL[1] = pstSnsState->au32FL[0]; + memset(pstSnsState->au32WDRIntTime, 0, sizeof(pstSnsState->au32WDRIntTime)); + + return CVI_SUCCESS; +} + +static CVI_U32 sensor_cmp_wdr_size(ISP_SNS_ISP_INFO_S *pstWdr1, ISP_SNS_ISP_INFO_S *pstWdr2) +{ + CVI_U32 i; + + if (pstWdr1->frm_num != pstWdr2->frm_num) + goto _mismatch; + for (i = 0; i < 2; i++) { + if (pstWdr1->img_size[i].stSnsSize.u32Width != pstWdr2->img_size[i].stSnsSize.u32Width) + goto _mismatch; + if (pstWdr1->img_size[i].stSnsSize.u32Height != pstWdr2->img_size[i].stSnsSize.u32Height) + goto _mismatch; + if (pstWdr1->img_size[i].stWndRect.s32X != pstWdr2->img_size[i].stWndRect.s32X) + goto _mismatch; + if (pstWdr1->img_size[i].stWndRect.s32Y != pstWdr2->img_size[i].stWndRect.s32Y) + goto _mismatch; + if (pstWdr1->img_size[i].stWndRect.u32Width != pstWdr2->img_size[i].stWndRect.u32Width) + goto _mismatch; + if (pstWdr1->img_size[i].stWndRect.u32Height != pstWdr2->img_size[i].stWndRect.u32Height) + goto _mismatch; + } + + return 0; +_mismatch: + return 1; +} + +static CVI_U32 sensor_cmp_cif_wdr(ISP_SNS_CIF_INFO_S *pstWdr1, ISP_SNS_CIF_INFO_S *pstWdr2) +{ + if (pstWdr1->wdr_manual.l2s_distance != pstWdr2->wdr_manual.l2s_distance) + goto _mismatch; + if (pstWdr1->wdr_manual.lsef_length != pstWdr2->wdr_manual.lsef_length) + goto _mismatch; + + return 0; +_mismatch: + return 1; +} + +static CVI_S32 cmos_get_sns_regs_info(VI_PIPE ViPipe, ISP_SNS_SYNC_INFO_S *pstSnsSyncInfo) +{ + CVI_U32 i; + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + ISP_SNS_REGS_INFO_S *pstSnsRegsInfo = CVI_NULL; + ISP_SNS_SYNC_INFO_S *pstCfg0 = CVI_NULL; + ISP_SNS_SYNC_INFO_S *pstCfg1 = CVI_NULL; + ISP_I2C_DATA_S *pstI2c_data = CVI_NULL; + + CMOS_CHECK_POINTER(pstSnsSyncInfo); + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + pstSnsRegsInfo = &pstSnsSyncInfo->snsCfg; + pstCfg0 = &pstSnsState->astSyncInfo[0]; + pstCfg1 = &pstSnsState->astSyncInfo[1]; + pstI2c_data = pstCfg0->snsCfg.astI2cData; + + if ((pstSnsState->bSyncInit == CVI_FALSE) || (pstSnsRegsInfo->bConfig == CVI_FALSE)) { + pstCfg0->snsCfg.enSnsType = SNS_I2C_TYPE; + pstCfg0->snsCfg.unComBus.s8I2cDev = g_aunSC3336_1L_BusInfo[ViPipe].s8I2cDev; + pstCfg0->snsCfg.u8Cfg2ValidDelayMax = 0; + pstCfg0->snsCfg.use_snsr_sram = CVI_TRUE; + pstCfg0->snsCfg.u32RegNum = LINEAR_REGS_NUM; + + for (i = 0; i < pstCfg0->snsCfg.u32RegNum; i++) { + pstI2c_data[i].bUpdate = CVI_TRUE; + pstI2c_data[i].u8DevAddr = sc3336_1l_i2c_addr; + pstI2c_data[i].u32AddrByteNum = sc3336_1l_addr_byte; + pstI2c_data[i].u32DataByteNum = sc3336_1l_data_byte; + } + + switch (pstSnsState->enWDRMode) { + case WDR_MODE_NONE: + //Linear Mode Regs + pstI2c_data[LINEAR_EXP_H_ADDR].u32RegAddr = SC3336_1L_EXP_H_ADDR; + pstI2c_data[LINEAR_EXP_M_ADDR].u32RegAddr = SC3336_1L_EXP_M_ADDR; + pstI2c_data[LINEAR_EXP_L_ADDR].u32RegAddr = SC3336_1L_EXP_L_ADDR; + pstI2c_data[LINEAR_AGAIN_ADDR].u32RegAddr = SC3336_1L_AGAIN_ADDR; + pstI2c_data[LINEAR_DGAIN_H_ADDR].u32RegAddr = SC3336_1L_DGAIN_H_ADDR; + pstI2c_data[LINEAR_DGAIN_L_ADDR].u32RegAddr = SC3336_1L_DGAIN_L_ADDR; + pstI2c_data[LINEAR_VMAX_H_ADDR].u32RegAddr = SC3336_1L_VMAX_H_ADDR; + pstI2c_data[LINEAR_VMAX_L_ADDR].u32RegAddr = SC3336_1L_VMAX_L_ADDR; + break; + default: + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support WDR: %d\n", pstSnsState->enWDRMode); + return CVI_FAILURE; + } + pstSnsState->bSyncInit = CVI_TRUE; + pstCfg0->snsCfg.need_update = CVI_TRUE; + /* recalcualte WDR size */ + cmos_get_wdr_size(ViPipe, &pstCfg0->ispCfg); + pstCfg0->ispCfg.need_update = CVI_TRUE; + } else { + pstCfg0->snsCfg.need_update = CVI_FALSE; + for (i = 0; i < pstCfg0->snsCfg.u32RegNum; i++) { + if (pstCfg0->snsCfg.astI2cData[i].u32Data == pstCfg1->snsCfg.astI2cData[i].u32Data) { + pstCfg0->snsCfg.astI2cData[i].bUpdate = CVI_FALSE; + } else { + pstCfg0->snsCfg.astI2cData[i].bUpdate = CVI_TRUE; + pstCfg0->snsCfg.need_update = CVI_TRUE; + } + } + + /* check update isp crop or not */ + pstCfg0->ispCfg.need_update = (sensor_cmp_wdr_size(&pstCfg0->ispCfg, &pstCfg1->ispCfg) ? + CVI_TRUE : CVI_FALSE); + + /* check update cif wdr manual or not */ + pstCfg0->cifCfg.need_update = (sensor_cmp_cif_wdr(&pstCfg0->cifCfg, &pstCfg1->cifCfg) ? + CVI_TRUE : CVI_FALSE); + } + + pstSnsRegsInfo->bConfig = CVI_FALSE; + memcpy(pstSnsSyncInfo, &pstSnsState->astSyncInfo[0], sizeof(ISP_SNS_SYNC_INFO_S)); + memcpy(&pstSnsState->astSyncInfo[1], &pstSnsState->astSyncInfo[0], sizeof(ISP_SNS_SYNC_INFO_S)); + pstSnsState->au32FL[1] = pstSnsState->au32FL[0]; + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_set_image_mode(VI_PIPE ViPipe, ISP_CMOS_SENSOR_IMAGE_MODE_S *pstSensorImageMode) +{ + CVI_U8 u8SensorImageMode = 0; + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + CMOS_CHECK_POINTER(pstSensorImageMode); + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + + u8SensorImageMode = pstSnsState->u8ImgMode; + pstSnsState->bSyncInit = CVI_FALSE; + + if (pstSensorImageMode->f32Fps <= 20) { + if (pstSnsState->enWDRMode == WDR_MODE_NONE) { + if (SC3336_1L_RES_IS_1296P(pstSensorImageMode->u16Width, pstSensorImageMode->u16Height)) { + u8SensorImageMode = SC3336_1L_MODE_2304X1296P20; + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support! Width:%d, Height:%d, Fps:%f, WDRMode:%d\n", + pstSensorImageMode->u16Width, + pstSensorImageMode->u16Height, + pstSensorImageMode->f32Fps, + pstSnsState->enWDRMode); + return CVI_FAILURE; + } + } else { + CVI_TRACE_SNS(CVI_DBG_ERR, "Not support! Width:%d, Height:%d, Fps:%f, WDRMode:%d\n", + pstSensorImageMode->u16Width, + pstSensorImageMode->u16Height, + pstSensorImageMode->f32Fps, + pstSnsState->enWDRMode); + return CVI_FAILURE; + } + } + + if ((pstSnsState->bInit == CVI_TRUE) && (u8SensorImageMode == pstSnsState->u8ImgMode)) { + /* Don't need to switch SensorImageMode */ + return CVI_FAILURE; + } + + pstSnsState->u8ImgMode = u8SensorImageMode; + + return CVI_SUCCESS; +} + +static CVI_VOID sensor_mirror_flip(VI_PIPE ViPipe, ISP_SNS_MIRRORFLIP_TYPE_E eSnsMirrorFlip) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER_VOID(pstSnsState); + if (pstSnsState->bInit == CVI_TRUE && g_aeSC3336_1L_MirrorFip[ViPipe] != eSnsMirrorFlip) { + sc3336_1l_mirror_flip(ViPipe, eSnsMirrorFlip); + g_aeSC3336_1L_MirrorFip[ViPipe] = eSnsMirrorFlip; + } +} + +static CVI_VOID sensor_global_init(VI_PIPE ViPipe) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + const SC3336_1L_MODE_S *pstMode = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER_VOID(pstSnsState); + + pstSnsState->bInit = CVI_FALSE; + pstSnsState->bSyncInit = CVI_FALSE; + pstSnsState->u8ImgMode = SC3336_1L_MODE_2304X1296P20; + pstSnsState->enWDRMode = WDR_MODE_NONE; + pstMode = &g_astSC3336_1L_mode[pstSnsState->u8ImgMode]; + pstSnsState->u32FLStd = pstMode->u32VtsDef; + pstSnsState->au32FL[0] = pstMode->u32VtsDef; + pstSnsState->au32FL[1] = pstMode->u32VtsDef; + + memset(&pstSnsState->astSyncInfo[0], 0, sizeof(ISP_SNS_SYNC_INFO_S)); + memset(&pstSnsState->astSyncInfo[1], 0, sizeof(ISP_SNS_SYNC_INFO_S)); +} + +static CVI_S32 sensor_rx_attr(VI_PIPE ViPipe, SNS_COMBO_DEV_ATTR_S *pstRxAttr) +{ + ISP_SNS_STATE_S *pstSnsState = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pstSnsState); + CMOS_CHECK_POINTER(pstSnsState); + CMOS_CHECK_POINTER(pstRxAttr); + + memcpy(pstRxAttr, &sc3336_1l_rx_attr, sizeof(*pstRxAttr)); + + pstRxAttr->img_size.width = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].astImg[0].stSnsSize.u32Width; + pstRxAttr->img_size.height = g_astSC3336_1L_mode[pstSnsState->u8ImgMode].astImg[0].stSnsSize.u32Height; + if (pstSnsState->enWDRMode == WDR_MODE_NONE) { + pstRxAttr->mipi_attr.wdr_mode = CVI_MIPI_WDR_MODE_NONE; + } + + return CVI_SUCCESS; +} + +static CVI_S32 sensor_patch_rx_attr(RX_INIT_ATTR_S *pstRxInitAttr) +{ + SNS_COMBO_DEV_ATTR_S *pstRxAttr = &sc3336_1l_rx_attr; + int i; + + CMOS_CHECK_POINTER(pstRxInitAttr); + + if (pstRxInitAttr->stMclkAttr.bMclkEn) + pstRxAttr->mclk.cam = pstRxInitAttr->stMclkAttr.u8Mclk; + + if (pstRxInitAttr->MipiDev >= VI_MAX_DEV_NUM) + return CVI_SUCCESS; + + pstRxAttr->devno = pstRxInitAttr->MipiDev; + + if (pstRxAttr->input_mode == INPUT_MODE_MIPI) { + struct mipi_dev_attr_s *attr = &pstRxAttr->mipi_attr; + + for (i = 0; i < MIPI_LANE_NUM + 1; i++) { + attr->lane_id[i] = pstRxInitAttr->as16LaneId[i]; + attr->pn_swap[i] = pstRxInitAttr->as8PNSwap[i]; + } + } else { + struct lvds_dev_attr_s *attr = &pstRxAttr->lvds_attr; + + for (i = 0; i < MIPI_LANE_NUM + 1; i++) { + attr->lane_id[i] = pstRxInitAttr->as16LaneId[i]; + attr->pn_swap[i] = pstRxInitAttr->as8PNSwap[i]; + } + } + + return CVI_SUCCESS; +} + +static CVI_S32 cmos_init_sensor_exp_function(ISP_SENSOR_EXP_FUNC_S *pstSensorExpFunc) +{ + CMOS_CHECK_POINTER(pstSensorExpFunc); + + memset(pstSensorExpFunc, 0, sizeof(ISP_SENSOR_EXP_FUNC_S)); + + pstSensorExpFunc->pfn_cmos_sensor_init = sc3336_1l_init; + pstSensorExpFunc->pfn_cmos_sensor_exit = sc3336_1l_exit; + pstSensorExpFunc->pfn_cmos_sensor_global_init = sensor_global_init; + pstSensorExpFunc->pfn_cmos_set_image_mode = cmos_set_image_mode; + pstSensorExpFunc->pfn_cmos_set_wdr_mode = cmos_set_wdr_mode; + + pstSensorExpFunc->pfn_cmos_get_isp_default = cmos_get_isp_default; + pstSensorExpFunc->pfn_cmos_get_isp_black_level = cmos_get_blc_default; + pstSensorExpFunc->pfn_cmos_get_sns_reg_info = cmos_get_sns_regs_info; + + return CVI_SUCCESS; +} + +/**************************************************************************** + * callback structure * + ****************************************************************************/ +static CVI_VOID sensor_patch_i2c_addr(CVI_S32 s32I2cAddr) +{ + if (SC3336_1L_I2C_ADDR_IS_VALID(s32I2cAddr)) + sc3336_1l_i2c_addr = s32I2cAddr; +} + +static CVI_S32 sc3336_1l_set_bus_info(VI_PIPE ViPipe, ISP_SNS_COMMBUS_U unSNSBusInfo) +{ + g_aunSC3336_1L_BusInfo[ViPipe].s8I2cDev = unSNSBusInfo.s8I2cDev; + + return CVI_SUCCESS; +} + +static CVI_S32 sensor_ctx_init(VI_PIPE ViPipe) +{ + ISP_SNS_STATE_S *pastSnsStateCtx = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pastSnsStateCtx); + + if (pastSnsStateCtx == CVI_NULL) { + pastSnsStateCtx = (ISP_SNS_STATE_S *)malloc(sizeof(ISP_SNS_STATE_S)); + if (pastSnsStateCtx == CVI_NULL) { + CVI_TRACE_SNS(CVI_DBG_ERR, "Isp[%d] SnsCtx malloc memory failed!\n", ViPipe); + return -ENOMEM; + } + } + + memset(pastSnsStateCtx, 0, sizeof(ISP_SNS_STATE_S)); + + SC3336_1L_SENSOR_SET_CTX(ViPipe, pastSnsStateCtx); + + return CVI_SUCCESS; +} + +static CVI_VOID sensor_ctx_exit(VI_PIPE ViPipe) +{ + ISP_SNS_STATE_S *pastSnsStateCtx = CVI_NULL; + + SC3336_1L_SENSOR_GET_CTX(ViPipe, pastSnsStateCtx); + SENSOR_FREE(pastSnsStateCtx); + SC3336_1L_SENSOR_RESET_CTX(ViPipe); +} + +static CVI_S32 sensor_register_callback(VI_PIPE ViPipe, ALG_LIB_S *pstAeLib, ALG_LIB_S *pstAwbLib) +{ + CVI_S32 s32Ret; + ISP_SENSOR_REGISTER_S stIspRegister; + AE_SENSOR_REGISTER_S stAeRegister; + AWB_SENSOR_REGISTER_S stAwbRegister; + ISP_SNS_ATTR_INFO_S stSnsAttrInfo; + + CMOS_CHECK_POINTER(pstAeLib); + CMOS_CHECK_POINTER(pstAwbLib); + + s32Ret = sensor_ctx_init(ViPipe); + + if (s32Ret != CVI_SUCCESS) + return CVI_FAILURE; + + stSnsAttrInfo.eSensorId = SC3336_1L_ID; + + s32Ret = cmos_init_sensor_exp_function(&stIspRegister.stSnsExp); + s32Ret |= CVI_ISP_SensorRegCallBack(ViPipe, &stSnsAttrInfo, &stIspRegister); + + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor register callback function failed!\n"); + return s32Ret; + } + + s32Ret = cmos_init_ae_exp_function(&stAeRegister.stAeExp); + s32Ret |= CVI_AE_SensorRegCallBack(ViPipe, pstAeLib, &stSnsAttrInfo, &stAeRegister); + + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor register callback function to ae lib failed!\n"); + return s32Ret; + } + + s32Ret = cmos_init_awb_exp_function(&stAwbRegister.stAwbExp); + s32Ret |= CVI_AWB_SensorRegCallBack(ViPipe, pstAwbLib, &stSnsAttrInfo, &stAwbRegister); + + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor register callback function to awb lib failed!\n"); + return s32Ret; + } + + return CVI_SUCCESS; +} + +static CVI_S32 sensor_unregister_callback(VI_PIPE ViPipe, ALG_LIB_S *pstAeLib, ALG_LIB_S *pstAwbLib) +{ + CVI_S32 s32Ret; + + CMOS_CHECK_POINTER(pstAeLib); + CMOS_CHECK_POINTER(pstAwbLib); + + s32Ret = CVI_ISP_SensorUnRegCallBack(ViPipe, SC3336_1L_ID); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor unregister callback function failed!\n"); + return s32Ret; + } + + s32Ret = CVI_AE_SensorUnRegCallBack(ViPipe, pstAeLib, SC3336_1L_ID); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor unregister callback function to ae lib failed!\n"); + return s32Ret; + } + + s32Ret = CVI_AWB_SensorUnRegCallBack(ViPipe, pstAwbLib, SC3336_1L_ID); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_SNS(CVI_DBG_ERR, "sensor unregister callback function to awb lib failed!\n"); + return s32Ret; + } + + sensor_ctx_exit(ViPipe); + + return CVI_SUCCESS; +} + +static CVI_S32 sensor_set_init(VI_PIPE ViPipe, ISP_INIT_ATTR_S *pstInitAttr) +{ + CMOS_CHECK_POINTER(pstInitAttr); + + g_au32InitExposure[ViPipe] = pstInitAttr->u32Exposure; + g_au32LinesPer500ms[ViPipe] = pstInitAttr->u32LinesPer500ms; + g_au16InitWBGain[ViPipe][0] = pstInitAttr->u16WBRgain; + g_au16InitWBGain[ViPipe][1] = pstInitAttr->u16WBGgain; + g_au16InitWBGain[ViPipe][2] = pstInitAttr->u16WBBgain; + g_au16SampleRgain[ViPipe] = pstInitAttr->u16SampleRgain; + g_au16SampleBgain[ViPipe] = pstInitAttr->u16SampleBgain; + g_au16SC3336_1L_GainMode[ViPipe] = pstInitAttr->enGainMode; + g_au16SC3336_1L_L2SMode[ViPipe] = pstInitAttr->enL2SMode; + + return CVI_SUCCESS; +} + +ISP_SNS_OBJ_S stSnsSC3336_1L_Obj = { + .pfnRegisterCallback = sensor_register_callback, + .pfnUnRegisterCallback = sensor_unregister_callback, + .pfnStandby = sc3336_1l_standby, + .pfnRestart = sc3336_1l_restart, + .pfnMirrorFlip = sensor_mirror_flip, + .pfnWriteReg = sc3336_1l_write_register, + .pfnReadReg = sc3336_1l_read_register, + .pfnSetBusInfo = sc3336_1l_set_bus_info, + .pfnSetInit = sensor_set_init, + .pfnPatchRxAttr = sensor_patch_rx_attr, + .pfnPatchI2cAddr = sensor_patch_i2c_addr, + .pfnGetRxAttr = sensor_rx_attr, + .pfnExpSensorCb = cmos_init_sensor_exp_function, + .pfnExpAeCb = cmos_init_ae_exp_function, + .pfnSnsProbe = sc3336_1l_probe, +}; + diff --git a/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_ex.h b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_ex.h new file mode 100644 index 000000000..0115669a8 --- /dev/null +++ b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_ex.h @@ -0,0 +1,80 @@ +#ifndef __SC3336_1L_CMOS_EX_H_ +#define __SC3336_1L_CMOS_EX_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef ARCH_CV182X +#include +#include +#include "cvi_type.h" +#else +#include +#include +#include +#endif +#include "cvi_sns_ctrl.h" + + +enum sc3336_1l_linear_regs_e { + LINEAR_EXP_H_ADDR, + LINEAR_EXP_M_ADDR, + LINEAR_EXP_L_ADDR, + LINEAR_AGAIN_ADDR, + LINEAR_DGAIN_H_ADDR, + LINEAR_DGAIN_L_ADDR, + LINEAR_VMAX_H_ADDR, + LINEAR_VMAX_L_ADDR, + LINEAR_REGS_NUM +}; + +typedef enum _SC3336_1L_MODE_E { + SC3336_1L_MODE_2304X1296P20 = 0, + SC3336_1L_MODE_LINEAR_NUM, + SC3336_1L_MODE_2304X1296P20_WDR = SC3336_1L_MODE_LINEAR_NUM, + SC3336_1L_MODE_NUM +} SC3336_1L_MODE_E; + +typedef struct _SC3336_1L_MODE_S { + ISP_WDR_SIZE_S astImg[2]; + CVI_FLOAT f32MaxFps; + CVI_FLOAT f32MinFps; + CVI_U32 u32HtsDef; + CVI_U32 u32VtsDef; + SNS_ATTR_S stExp[2]; + SNS_ATTR_S stAgain[2]; + SNS_ATTR_S stDgain[2]; + char name[64]; +} SC3336_1L_MODE_S; + +/**************************************************************************** + * external variables and functions * + ****************************************************************************/ + +extern ISP_SNS_STATE_S *g_pastSC3336_1L[VI_MAX_PIPE_NUM]; +extern ISP_SNS_COMMBUS_U g_aunSC3336_1L_BusInfo[]; +extern CVI_U16 g_au16SC3336_1L_GainMode[]; +extern CVI_U16 g_au16SC3336_1L_L2SMode[]; +extern CVI_U8 sc3336_1l_i2c_addr; +extern const CVI_U32 sc3336_1l_addr_byte; +extern const CVI_U32 sc3336_1l_data_byte; +extern void sc3336_1l_mirror_flip(VI_PIPE ViPipe, ISP_SNS_MIRRORFLIP_TYPE_E eSnsMirrorFlip); +extern void sc3336_1l_init(VI_PIPE ViPipe); +extern void sc3336_1l_exit(VI_PIPE ViPipe); +extern void sc3336_1l_standby(VI_PIPE ViPipe); +extern void sc3336_1l_restart(VI_PIPE ViPipe); +extern int sc3336_1l_write_register(VI_PIPE ViPipe, int addr, int data); +extern int sc3336_1l_read_register(VI_PIPE ViPipe, int addr); +extern int sc3336_1l_probe(VI_PIPE ViPipe); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + + +#endif /* __SC3336_1L_CMOS_EX_H_ */ diff --git a/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_param.h b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_param.h new file mode 100644 index 000000000..ff3e7c323 --- /dev/null +++ b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_cmos_param.h @@ -0,0 +1,121 @@ +#ifndef __SC3336_1L_CMOS_PARAM_H_ +#define __SC3336_1L_CMOS_PARAM_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef ARCH_CV182X +#include +#include +#include "cvi_type.h" +#else +#include +#include +#include +#endif +#include "cvi_sns_ctrl.h" +#include "sc3336_1L_cmos_ex.h" + +static const SC3336_1L_MODE_S g_astSC3336_1L_mode[SC3336_1L_MODE_NUM] = { + [SC3336_1L_MODE_2304X1296P20] = { + .name = "1296p20", + .astImg[0] = { + .stSnsSize = { + .u32Width = 2304, + .u32Height = 1296, + }, + .stWndRect = { + .s32X = 0, + .s32Y = 0, + .u32Width = 2304, + .u32Height = 1296, + }, + .stMaxSize = { + .u32Width = 2304, + .u32Height = 1296, + }, + }, + .f32MaxFps = 20, + .f32MinFps = 0.82, /* 1350 * 20 / 0x7FFF */ + .u32HtsDef = 4938, + .u32VtsDef = 1350, + .stExp[0] = { + .u16Min = 0, + .u16Max = 1340,//vts - 10 + .u16Def = 400, + .u16Step = 1, + }, + .stAgain[0] = { + .u16Min = 1024, + .u16Max = 49807, + .u16Def = 1024, + .u16Step = 1, + }, + .stDgain[0] = { + .u16Min = 1024, + .u16Max = 16128, + .u16Def = 1024, + .u16Step = 1, + }, + }, +}; + +static ISP_CMOS_BLACK_LEVEL_S g_stIspBlcCalibratio = { + .bUpdate = CVI_TRUE, + .blcAttr = { + .Enable = 1, + .enOpType = OP_TYPE_AUTO, + .stManual = {260, 260, 260, 260, 0, 0, 0, 0 +#ifdef ARCH_CV182X + , 1093, 1093, 1093, 1093 +#endif + }, + .stAuto = { + {260, 260, 260, 260, 260, 260, 260, 260, /*8*/260, 260, 260, 260, 260, 260, 260, 260}, + {260, 260, 260, 260, 260, 260, 260, 260, /*8*/260, 260, 260, 260, 260, 260, 260, 260}, + {260, 260, 260, 260, 260, 260, 260, 260, /*8*/260, 260, 260, 260, 260, 260, 260, 260}, + {260, 260, 260, 260, 260, 260, 260, 260, /*8*/260, 260, 260, 260, 260, 260, 260, 260}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +#ifdef ARCH_CV182X + {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /*8*/1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093}, + {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /*8*/1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093}, + {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /*8*/1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093}, + {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /*8*/1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093}, +#endif + }, + }, +}; + +struct combo_dev_attr_s sc3336_1l_rx_attr = { + .input_mode = INPUT_MODE_MIPI, + .mac_clk = RX_MAC_CLK_200M, + .mipi_attr = { + .raw_data_type = RAW_DATA_10BIT, + .lane_id = {0, 1, 2, -1, -1}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, + }, + .mclk = { + .cam = 0, + .freq = CAMPLL_FREQ_27M, + }, + .devno = 0, +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + + +#endif /* __SC3336_1L_CMOS_PARAM_H_ */ diff --git a/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_sensor_ctl.c b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_sensor_ctl.c new file mode 100644 index 000000000..4368570f3 --- /dev/null +++ b/middleware/v2/component/isp/sensor/cv182x/sms_sc3336_1L/sc3336_1L_sensor_ctl.c @@ -0,0 +1,397 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ARCH_CV182X +#include +#include "cvi_comm_video.h" +#else +#include +#include +#endif +#include "cvi_sns_ctrl.h" +#include "sc3336_1L_cmos_ex.h" + +#define SC3336_1L_CHIP_ID_HI_ADDR 0x3107 +#define SC3336_1L_CHIP_ID_LO_ADDR 0x3108 +#define SC3336_1L_CHIP_ID 0xcc41 + +static void sc3336_1l_linear_1296P20_init(VI_PIPE ViPipe); + +CVI_U8 sc3336_1l_i2c_addr = 0x30; /* I2C Address of SC3336_1L */ +const CVI_U32 sc3336_1l_addr_byte = 2; +const CVI_U32 sc3336_1l_data_byte = 1; +static int g_fd[VI_MAX_PIPE_NUM] = {[0 ... (VI_MAX_PIPE_NUM - 1)] = -1}; + +int sc3336_1l_i2c_init(VI_PIPE ViPipe) +{ + char acDevFile[16] = {0}; + CVI_U8 u8DevNum; + + if (g_fd[ViPipe] >= 0) + return CVI_SUCCESS; + int ret; + + u8DevNum = g_aunSC3336_1L_BusInfo[ViPipe].s8I2cDev; + snprintf(acDevFile, sizeof(acDevFile), "/dev/i2c-%u", u8DevNum); + + g_fd[ViPipe] = open(acDevFile, O_RDWR, 0600); + + if (g_fd[ViPipe] < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "Open /dev/cvi_i2c_drv-%u error!\n", u8DevNum); + return CVI_FAILURE; + } + + ret = ioctl(g_fd[ViPipe], I2C_SLAVE_FORCE, sc3336_1l_i2c_addr); + if (ret < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_SLAVE_FORCE error!\n"); + close(g_fd[ViPipe]); + g_fd[ViPipe] = -1; + return ret; + } + + return CVI_SUCCESS; +} + +int sc3336_1l_i2c_exit(VI_PIPE ViPipe) +{ + if (g_fd[ViPipe] >= 0) { + close(g_fd[ViPipe]); + g_fd[ViPipe] = -1; + return CVI_SUCCESS; + } + return CVI_FAILURE; +} + +int sc3336_1l_read_register(VI_PIPE ViPipe, int addr) +{ + int ret, data; + CVI_U8 buf[8]; + CVI_U8 idx = 0; + + if (g_fd[ViPipe] < 0) + return CVI_FAILURE; + + if (sc3336_1l_addr_byte == 2) + buf[idx++] = (addr >> 8) & 0xff; + + // add address byte 0 + buf[idx++] = addr & 0xff; + + ret = write(g_fd[ViPipe], buf, sc3336_1l_addr_byte); + if (ret < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_WRITE error!\n"); + return ret; + } + + buf[0] = 0; + buf[1] = 0; + ret = read(g_fd[ViPipe], buf, sc3336_1l_data_byte); + if (ret < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_READ error!\n"); + return ret; + } + + // pack read back data + data = 0; + if (sc3336_1l_data_byte == 2) { + data = buf[0] << 8; + data += buf[1]; + } else { + data = buf[0]; + } + + syslog(LOG_DEBUG, "i2c r 0x%x = 0x%x\n", addr, data); + return data; +} + +int sc3336_1l_write_register(VI_PIPE ViPipe, int addr, int data) +{ + CVI_U8 idx = 0; + int ret; + CVI_U8 buf[8]; + + if (g_fd[ViPipe] < 0) + return CVI_SUCCESS; + + if (sc3336_1l_addr_byte == 2) { + buf[idx] = (addr >> 8) & 0xff; + idx++; + buf[idx] = addr & 0xff; + idx++; + } + + if (sc3336_1l_data_byte == 1) { + buf[idx] = data & 0xff; + idx++; + } + + ret = write(g_fd[ViPipe], buf, sc3336_1l_addr_byte + sc3336_1l_data_byte); + if (ret < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_WRITE error!\n"); + return CVI_FAILURE; + } + syslog(LOG_DEBUG, "i2c w 0x%x 0x%x\n", addr, data); + return CVI_SUCCESS; +} + +static void delay_ms(int ms) +{ + usleep(ms * 1000); +} + +void sc3336_1l_standby(VI_PIPE ViPipe) +{ + sc3336_1l_write_register(ViPipe, 0x0100, 0x00); +} + +void sc3336_1l_restart(VI_PIPE ViPipe) +{ + sc3336_1l_write_register(ViPipe, 0x0100, 0x00); + delay_ms(20); + sc3336_1l_write_register(ViPipe, 0x0100, 0x01); +} + +void sc3336_1l_default_reg_init(VI_PIPE ViPipe) +{ + CVI_U32 i; + + for (i = 0; i < g_pastSC3336_1L[ViPipe]->astSyncInfo[0].snsCfg.u32RegNum; i++) { + if (g_pastSC3336_1L[ViPipe]->astSyncInfo[0].snsCfg.astI2cData[i].bUpdate == CVI_TRUE) { + sc3336_1l_write_register(ViPipe, + g_pastSC3336_1L[ViPipe]->astSyncInfo[0].snsCfg.astI2cData[i].u32RegAddr, + g_pastSC3336_1L[ViPipe]->astSyncInfo[0].snsCfg.astI2cData[i].u32Data); + } + } +} + +void sc3336_1l_mirror_flip(VI_PIPE ViPipe, ISP_SNS_MIRRORFLIP_TYPE_E eSnsMirrorFlip) +{ + CVI_U8 val = 0; + + switch (eSnsMirrorFlip) { + case ISP_SNS_NORMAL: + break; + case ISP_SNS_MIRROR: + val |= 0x6; + break; + case ISP_SNS_FLIP: + val |= 0x60; + break; + case ISP_SNS_MIRROR_FLIP: + val |= 0x66; + break; + default: + return; + } + + sc3336_1l_write_register(ViPipe, 0x3221, val); +} + +int sc3336_1l_probe(VI_PIPE ViPipe) +{ + int nVal; + CVI_U16 chip_id; + + delay_ms(4); + if (sc3336_1l_i2c_init(ViPipe) != CVI_SUCCESS) + return CVI_FAILURE; + + nVal = sc3336_1l_read_register(ViPipe, SC3336_1L_CHIP_ID_HI_ADDR); + if (nVal < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "read sensor id error.\n"); + return nVal; + } + chip_id = (nVal & 0xFF) << 8; + nVal = sc3336_1l_read_register(ViPipe, SC3336_1L_CHIP_ID_LO_ADDR); + if (nVal < 0) { + CVI_TRACE_SNS(CVI_DBG_ERR, "read sensor id error.\n"); + return nVal; + } + chip_id |= (nVal & 0xFF); + + if (chip_id != SC3336_1L_CHIP_ID) { + CVI_TRACE_SNS(CVI_DBG_ERR, "Sensor ID Mismatch! Use the wrong sensor??\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +void sc3336_1l_init(VI_PIPE ViPipe) +{ + sc3336_1l_i2c_init(ViPipe); + + //linear mode only + sc3336_1l_linear_1296P20_init(ViPipe); + + g_pastSC3336_1L[ViPipe]->bInit = CVI_TRUE; +} + +void sc3336_1l_exit(VI_PIPE ViPipe) +{ + sc3336_1l_i2c_exit(ViPipe); +} + +/* 1296P20 and 1296P25 */ +static void sc3336_1l_linear_1296P20_init(VI_PIPE ViPipe) +{ + sc3336_1l_write_register(ViPipe, 0x0103, 0x01); + sc3336_1l_write_register(ViPipe, 0x36e9, 0x80); + sc3336_1l_write_register(ViPipe, 0x37f9, 0x80); + sc3336_1l_write_register(ViPipe, 0x3018, 0x1a); + sc3336_1l_write_register(ViPipe, 0x3019, 0x0e); + sc3336_1l_write_register(ViPipe, 0x301f, 0x14); + sc3336_1l_write_register(ViPipe, 0x30b8, 0x33); + sc3336_1l_write_register(ViPipe, 0x3253, 0x10); + sc3336_1l_write_register(ViPipe, 0x325f, 0x20); + sc3336_1l_write_register(ViPipe, 0x3301, 0x04); + sc3336_1l_write_register(ViPipe, 0x3306, 0x50); + sc3336_1l_write_register(ViPipe, 0x3309, 0xa8); + sc3336_1l_write_register(ViPipe, 0x330a, 0x00); + sc3336_1l_write_register(ViPipe, 0x330b, 0xd8); + sc3336_1l_write_register(ViPipe, 0x3314, 0x13); + sc3336_1l_write_register(ViPipe, 0x331f, 0x99); + sc3336_1l_write_register(ViPipe, 0x3333, 0x10); + sc3336_1l_write_register(ViPipe, 0x3334, 0x40); + sc3336_1l_write_register(ViPipe, 0x335e, 0x06); + sc3336_1l_write_register(ViPipe, 0x335f, 0x0a); + sc3336_1l_write_register(ViPipe, 0x3364, 0x5e); + sc3336_1l_write_register(ViPipe, 0x337c, 0x02); + sc3336_1l_write_register(ViPipe, 0x337d, 0x0e); + sc3336_1l_write_register(ViPipe, 0x3390, 0x01); + sc3336_1l_write_register(ViPipe, 0x3391, 0x03); + sc3336_1l_write_register(ViPipe, 0x3392, 0x07); + sc3336_1l_write_register(ViPipe, 0x3393, 0x04); + sc3336_1l_write_register(ViPipe, 0x3394, 0x04); + sc3336_1l_write_register(ViPipe, 0x3395, 0x04); + sc3336_1l_write_register(ViPipe, 0x3396, 0x08); + sc3336_1l_write_register(ViPipe, 0x3397, 0x0b); + sc3336_1l_write_register(ViPipe, 0x3398, 0x1f); + sc3336_1l_write_register(ViPipe, 0x3399, 0x04); + sc3336_1l_write_register(ViPipe, 0x339a, 0x0a); + sc3336_1l_write_register(ViPipe, 0x339b, 0x3a); + sc3336_1l_write_register(ViPipe, 0x339c, 0xa0); + sc3336_1l_write_register(ViPipe, 0x33a2, 0x04); + sc3336_1l_write_register(ViPipe, 0x33ac, 0x08); + sc3336_1l_write_register(ViPipe, 0x33ad, 0x1c); + sc3336_1l_write_register(ViPipe, 0x33ae, 0x10); + sc3336_1l_write_register(ViPipe, 0x33af, 0x30); + sc3336_1l_write_register(ViPipe, 0x33b1, 0x80); + sc3336_1l_write_register(ViPipe, 0x33b3, 0x48); + sc3336_1l_write_register(ViPipe, 0x33f9, 0x60); + sc3336_1l_write_register(ViPipe, 0x33fb, 0x74); + sc3336_1l_write_register(ViPipe, 0x33fc, 0x4b); + sc3336_1l_write_register(ViPipe, 0x33fd, 0x5f); + sc3336_1l_write_register(ViPipe, 0x349f, 0x03); + sc3336_1l_write_register(ViPipe, 0x34a6, 0x4b); + sc3336_1l_write_register(ViPipe, 0x34a7, 0x5f); + sc3336_1l_write_register(ViPipe, 0x34a8, 0x20); + sc3336_1l_write_register(ViPipe, 0x34a9, 0x18); + sc3336_1l_write_register(ViPipe, 0x34ab, 0xe8); + sc3336_1l_write_register(ViPipe, 0x34ac, 0x01); + sc3336_1l_write_register(ViPipe, 0x34ad, 0x00); + sc3336_1l_write_register(ViPipe, 0x34f8, 0x5f); + sc3336_1l_write_register(ViPipe, 0x34f9, 0x18); + sc3336_1l_write_register(ViPipe, 0x3630, 0xc0); + sc3336_1l_write_register(ViPipe, 0x3631, 0x84); + sc3336_1l_write_register(ViPipe, 0x3632, 0x64); + sc3336_1l_write_register(ViPipe, 0x3633, 0x32); + sc3336_1l_write_register(ViPipe, 0x363b, 0x03); + sc3336_1l_write_register(ViPipe, 0x363c, 0x08); + sc3336_1l_write_register(ViPipe, 0x3641, 0x38); + sc3336_1l_write_register(ViPipe, 0x3670, 0x4e); + sc3336_1l_write_register(ViPipe, 0x3674, 0xc0); + sc3336_1l_write_register(ViPipe, 0x3675, 0xc0); + sc3336_1l_write_register(ViPipe, 0x3676, 0xc0); + sc3336_1l_write_register(ViPipe, 0x3677, 0x86); + sc3336_1l_write_register(ViPipe, 0x3678, 0x86); + sc3336_1l_write_register(ViPipe, 0x3679, 0x86); + sc3336_1l_write_register(ViPipe, 0x367c, 0x48); + sc3336_1l_write_register(ViPipe, 0x367d, 0x49); + sc3336_1l_write_register(ViPipe, 0x367e, 0x4b); + sc3336_1l_write_register(ViPipe, 0x367f, 0x5f); + sc3336_1l_write_register(ViPipe, 0x3690, 0x32); + sc3336_1l_write_register(ViPipe, 0x3691, 0x32); + sc3336_1l_write_register(ViPipe, 0x3692, 0x42); + sc3336_1l_write_register(ViPipe, 0x369c, 0x4b); + sc3336_1l_write_register(ViPipe, 0x369d, 0x5f); + sc3336_1l_write_register(ViPipe, 0x36b0, 0x87); + sc3336_1l_write_register(ViPipe, 0x36b1, 0x90); + sc3336_1l_write_register(ViPipe, 0x36b2, 0xa1); + sc3336_1l_write_register(ViPipe, 0x36b3, 0xd8); + sc3336_1l_write_register(ViPipe, 0x36b4, 0x49); + sc3336_1l_write_register(ViPipe, 0x36b5, 0x4b); + sc3336_1l_write_register(ViPipe, 0x36b6, 0x4f); + sc3336_1l_write_register(ViPipe, 0x36ea, 0x0a); + sc3336_1l_write_register(ViPipe, 0x36eb, 0x0d); + sc3336_1l_write_register(ViPipe, 0x36ec, 0x0c); + sc3336_1l_write_register(ViPipe, 0x36ed, 0x26); + sc3336_1l_write_register(ViPipe, 0x370f, 0x01); + sc3336_1l_write_register(ViPipe, 0x3722, 0x09); + sc3336_1l_write_register(ViPipe, 0x3724, 0x41); + sc3336_1l_write_register(ViPipe, 0x3725, 0xc1); + sc3336_1l_write_register(ViPipe, 0x3771, 0x09); + sc3336_1l_write_register(ViPipe, 0x3772, 0x09); + sc3336_1l_write_register(ViPipe, 0x3773, 0x05); + sc3336_1l_write_register(ViPipe, 0x377a, 0x48); + sc3336_1l_write_register(ViPipe, 0x377b, 0x5f); + sc3336_1l_write_register(ViPipe, 0x37fa, 0x0a); + sc3336_1l_write_register(ViPipe, 0x37fb, 0x33); + sc3336_1l_write_register(ViPipe, 0x37fc, 0x11); + sc3336_1l_write_register(ViPipe, 0x37fd, 0x18); + sc3336_1l_write_register(ViPipe, 0x3904, 0x04); + sc3336_1l_write_register(ViPipe, 0x3905, 0x8c); + sc3336_1l_write_register(ViPipe, 0x391d, 0x04); + sc3336_1l_write_register(ViPipe, 0x3921, 0x20); + sc3336_1l_write_register(ViPipe, 0x3926, 0x21); + sc3336_1l_write_register(ViPipe, 0x3933, 0x80); + sc3336_1l_write_register(ViPipe, 0x3934, 0x0a); + sc3336_1l_write_register(ViPipe, 0x3935, 0x00); + sc3336_1l_write_register(ViPipe, 0x3936, 0x2a); + sc3336_1l_write_register(ViPipe, 0x3937, 0x6a); + sc3336_1l_write_register(ViPipe, 0x3938, 0x6a); + sc3336_1l_write_register(ViPipe, 0x39dc, 0x02); + sc3336_1l_write_register(ViPipe, 0x3e01, 0x53); + sc3336_1l_write_register(ViPipe, 0x3e02, 0xe0); + sc3336_1l_write_register(ViPipe, 0x3e09, 0x00); + sc3336_1l_write_register(ViPipe, 0x440d, 0x10); + sc3336_1l_write_register(ViPipe, 0x440e, 0x01); + sc3336_1l_write_register(ViPipe, 0x4509, 0x20); + sc3336_1l_write_register(ViPipe, 0x4819, 0x09); + sc3336_1l_write_register(ViPipe, 0x481b, 0x05); + sc3336_1l_write_register(ViPipe, 0x481d, 0x12); + sc3336_1l_write_register(ViPipe, 0x481f, 0x04); + sc3336_1l_write_register(ViPipe, 0x4821, 0x0a); + sc3336_1l_write_register(ViPipe, 0x4823, 0x05); + sc3336_1l_write_register(ViPipe, 0x4825, 0x04); + sc3336_1l_write_register(ViPipe, 0x4827, 0x04); + sc3336_1l_write_register(ViPipe, 0x4829, 0x07); + sc3336_1l_write_register(ViPipe, 0x5ae0, 0xfe); + sc3336_1l_write_register(ViPipe, 0x5ae1, 0x40); + sc3336_1l_write_register(ViPipe, 0x5ae2, 0x38); + sc3336_1l_write_register(ViPipe, 0x5ae3, 0x30); + sc3336_1l_write_register(ViPipe, 0x5ae4, 0x28); + sc3336_1l_write_register(ViPipe, 0x5ae5, 0x38); + sc3336_1l_write_register(ViPipe, 0x5ae6, 0x30); + sc3336_1l_write_register(ViPipe, 0x5ae7, 0x28); + sc3336_1l_write_register(ViPipe, 0x5ae8, 0x3f); + sc3336_1l_write_register(ViPipe, 0x5ae9, 0x34); + sc3336_1l_write_register(ViPipe, 0x5aea, 0x2c); + sc3336_1l_write_register(ViPipe, 0x5aeb, 0x3f); + sc3336_1l_write_register(ViPipe, 0x5aec, 0x34); + sc3336_1l_write_register(ViPipe, 0x5aed, 0x2c); + sc3336_1l_write_register(ViPipe, 0x36e9, 0x20); + sc3336_1l_write_register(ViPipe, 0x37f9, 0x20); + + sc3336_1l_default_reg_init(ViPipe); + + sc3336_1l_write_register(ViPipe, 0x0100, 0x01); + + printf("ViPipe:%d,===SC3336_1L 1296P 20fps 10bit LINE Init OK!===\n", ViPipe); +}