826 lines
25 KiB
C
Executable File
826 lines
25 KiB
C
Executable File
#include "config.h"
|
|
#include "string.h"
|
|
#include "stdlib.h"
|
|
#include "stdio.h"
|
|
#include "xmedia_type.h"
|
|
#include "xmedia_isp.h"
|
|
#include "xmedia_errcode.h"
|
|
#include "isp_def.h"
|
|
#include "hal_isp.h"
|
|
#include "drv_isp.h"
|
|
#include "platform.h"
|
|
#include "timer.h"
|
|
|
|
#define CCM_MINUS_PARAM_TH 32768
|
|
|
|
typedef struct {
|
|
xmedia_bool ae_lib;
|
|
xmedia_bool awb_lib;
|
|
xmedia_bool sensor_lib;
|
|
xmedia_isp_ae_register_info ae_info;
|
|
xmedia_isp_awb_register_info awb_info;
|
|
xmedia_sensor_register_info sensor_info;
|
|
} isp_lib_info;
|
|
|
|
typedef struct {
|
|
xmedia_isp_config isp_config;
|
|
xmedia_u32 isp_frame_cnt;
|
|
xmedia_void *firmware_info;
|
|
isp_lib_info *lib_info;
|
|
|
|
xmedia_sensor_init_param *result;
|
|
} isp_context;
|
|
|
|
STAGE1_GLOBAL static isp_context *g_isp_ctx[ISP_PIPE_MAX_NUM] = { 0 };
|
|
STAGE1_GLOBAL static isp_lib_info g_isp_lib[ISP_PIPE_MAX_NUM] = { 0 };
|
|
STAGE1_GLOBAL static xmedia_u8 g_sensor_clk_ch[ISP_PIPE_MAX_NUM] = { 0 };
|
|
STAGE1_GLOBAL static xmedia_u8 g_sensor_rst_ch[ISP_PIPE_MAX_NUM] = { 0 };
|
|
|
|
#define ISP_GET_CTX(pipe, ctx) ctx = g_isp_ctx[pipe]
|
|
#define ISP_GET_LIB(pipe, ptr) ptr = &g_isp_lib[pipe]
|
|
|
|
#define TIMER_CLOCK_FRQ 24000000
|
|
|
|
xmedia_u32 isp_get_time_stamp(xmedia_void)
|
|
{
|
|
return (xmedia_u32)timer_get_val() / 24; // = timer_value * 10000000 / 24000000
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 xmedia_isp_register_sensor(xmedia_u32 pipe, const xmedia_sensor_register_info *info)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || info == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->sensor_lib == XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_EXIST;
|
|
}
|
|
|
|
// sensor需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
memcpy(&lib->sensor_info, info, sizeof(xmedia_sensor_register_info));
|
|
lib->sensor_lib = XMEDIA_TRUE;
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_isp_unregister_sensor(xmedia_u32 pipe, xmedia_u32 dev_id)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->sensor_lib == XMEDIA_FALSE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
// sensor需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
if (lib->sensor_info.dev_id != dev_id) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
lib->sensor_lib = XMEDIA_FALSE;
|
|
memset(&lib->sensor_info, 0, sizeof(xmedia_sensor_register_info));
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_isp_register_ae_lib(xmedia_u32 pipe, const xmedia_isp_ae_register_info *ae_info,
|
|
xmedia_sensor_register_ae_info *sensor_func)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || ae_info == XMEDIA_NULL || sensor_func == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->ae_lib == XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_EXIST;
|
|
}
|
|
|
|
// 3a需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
memcpy(&sensor_func->func, &lib->sensor_info.ae_func, sizeof(xmedia_sensor_register_ae_func));
|
|
sensor_func->dev_id = lib->sensor_info.dev_id;
|
|
|
|
memcpy(&lib->ae_info, ae_info, sizeof(xmedia_isp_ae_register_info));
|
|
lib->ae_lib = XMEDIA_TRUE;
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_isp_unregister_ae_lib(xmedia_u32 pipe, xmedia_char name[XMEDIA_ISP_ALG_NAME_MAX_SIZE], xmedia_s32 id)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || name == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->ae_lib == XMEDIA_FALSE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
// 3a需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
if (lib->ae_info.alg_id == id && strncmp(lib->ae_info.alg_name, name, XMEDIA_ISP_ALG_NAME_MAX_SIZE) == 0) {
|
|
memset(&lib->ae_info, 0, sizeof(xmedia_isp_ae_register_info));
|
|
lib->ae_lib = XMEDIA_FALSE;
|
|
} else {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_isp_register_awb_lib(xmedia_u32 pipe, const xmedia_isp_awb_register_info *awb_info,
|
|
xmedia_sensor_register_awb_info *sensor_func)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || awb_info == XMEDIA_NULL || sensor_func == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->awb_lib == XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_EXIST;
|
|
}
|
|
|
|
// 3a需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
memcpy(&sensor_func->func, &lib->sensor_info.awb_func, sizeof(xmedia_sensor_register_awb_func));
|
|
sensor_func->dev_id = lib->sensor_info.dev_id;
|
|
|
|
memcpy(&lib->awb_info, awb_info, sizeof(xmedia_isp_awb_register_info));
|
|
lib->awb_lib = XMEDIA_TRUE;
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_isp_unregister_awb_lib(xmedia_u32 pipe, xmedia_char name[XMEDIA_ISP_ALG_NAME_MAX_SIZE], xmedia_s32 id)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || name == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
ISP_GET_LIB(pipe, lib);
|
|
|
|
if (lib->awb_lib == XMEDIA_FALSE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
// 3a需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
|
|
if (ctx != XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_PERMITTED;
|
|
}
|
|
|
|
if (lib->awb_info.alg_id == id && strncmp(lib->awb_info.alg_name, name, XMEDIA_ISP_ALG_NAME_MAX_SIZE) == 0) {
|
|
memset(&lib->awb_info, 0, sizeof(xmedia_isp_awb_register_info));
|
|
lib->awb_lib = XMEDIA_FALSE;
|
|
} else {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 drv_sensor_init(xmedia_u32 pipe, xmedia_sensor_config *cfg)
|
|
{
|
|
xmedia_s32 ret = 0;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
xmedia_sensor_capability capability;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || cfg == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_init == XMEDIA_NULL ||
|
|
lib->sensor_info.isp_func.pfn_sensor_set_bus_info == XMEDIA_NULL ||
|
|
lib->sensor_info.isp_func.pfn_sensor_get_capability == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
g_sensor_clk_ch[pipe] = cfg->ctrl_sig.clk_ch;
|
|
g_sensor_rst_ch[pipe] = cfg->ctrl_sig.rst_ch;
|
|
|
|
ret = lib->sensor_info.isp_func.pfn_sensor_set_bus_info(lib->sensor_info.dev_id, &cfg->comm_bus);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
ret = lib->sensor_info.isp_func.pfn_sensor_get_capability(&capability);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
if (capability.reset_time <= 0) {
|
|
capability.reset_time = 100;
|
|
}
|
|
|
|
hal_sensor_set_mclk(g_sensor_clk_ch[pipe], capability.init_mclk);
|
|
|
|
//sensor cold start use normal, hot start use skip
|
|
if (cfg->init_mode != XMEDIA_SENSOR_INIT_MODE_SKIP) {
|
|
hal_sensor_reset(g_sensor_rst_ch[pipe], XMEDIA_TRUE);
|
|
udelay(capability.reset_time);
|
|
hal_sensor_reset(g_sensor_rst_ch[pipe], XMEDIA_FALSE);
|
|
}
|
|
|
|
udelay(1000*4);
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_init(lib->sensor_info.dev_id, cfg->init_mode);
|
|
}
|
|
|
|
xmedia_s32 drv_sensor_exit(xmedia_u32 pipe)
|
|
{
|
|
xmedia_s32 ret = 0;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_exit == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
ret = lib->sensor_info.isp_func.pfn_sensor_exit(lib->sensor_info.dev_id);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 drv_sensor_resume(xmedia_u32 pipe)
|
|
{
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("pipe error \n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
puts("sensor lib error\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_resume == XMEDIA_NULL) {
|
|
puts("sensor resume none\n");
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_resume(lib->sensor_info.dev_id);
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 drv_sensor_start(xmedia_u32 pipe)
|
|
{
|
|
xmedia_s32 ret = 0;
|
|
xmedia_u32 mclk = 0;
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
xmedia_sensor_property property;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_start == XMEDIA_NULL ||
|
|
lib->sensor_info.isp_func.pfn_sensor_get_property == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
ret = lib->sensor_info.isp_func.pfn_sensor_get_property(lib->sensor_info.dev_id, &property);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
hal_sensor_read_mclk(g_sensor_clk_ch[pipe], &mclk);
|
|
if (property.input_clock != mclk) {
|
|
hal_sensor_set_mclk(g_sensor_clk_ch[pipe], property.input_clock);
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_start(lib->sensor_info.dev_id);
|
|
}
|
|
|
|
xmedia_s32 drv_sensor_stop(xmedia_u32 pipe)
|
|
{
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_stop == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_stop(lib->sensor_info.dev_id);
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 drv_sensor_set_mipi_lanes(xmedia_u32 pipe, const xmedia_sensor_mipi_lanes mipi_lanes)
|
|
{
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_set_mipi_lanes == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_set_mipi_lanes(lib->sensor_info.dev_id, mipi_lanes);
|
|
}
|
|
|
|
STAGE1_FUNC xmedia_s32 drv_sensor_set_attr(xmedia_u32 pipe, const xmedia_sensor_attr *sns_attr)
|
|
{
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_set_attr == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_set_attr(lib->sensor_info.dev_id, sns_attr);
|
|
}
|
|
|
|
xmedia_s32 drv_sensor_set_init_param(xmedia_u32 pipe, const xmedia_sensor_init_param *init_param)
|
|
{
|
|
isp_lib_info *lib = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || init_param == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_LIB(pipe, lib);
|
|
if (lib->sensor_lib != XMEDIA_TRUE) {
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (lib->sensor_info.isp_func.pfn_sensor_set_init_param == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
return lib->sensor_info.isp_func.pfn_sensor_set_init_param(lib->sensor_info.dev_id, init_param);
|
|
}
|
|
|
|
xmedia_s32 drv_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
xmedia_sensor_black_level blc;
|
|
xmedia_s32 ret;
|
|
xmedia_isp_ae_param ae_param;
|
|
xmedia_isp_awb_param awb_param;
|
|
xmedia_sensor_isp_default isp_default;
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
xmedia_u32 start, end;
|
|
|
|
start = isp_get_time_stamp();
|
|
#endif
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM || cfg == XMEDIA_NULL) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx != XMEDIA_NULL) {
|
|
puts("isp ctx already exist!\n");
|
|
return XMEDIA_ERRCODE_EXIST;
|
|
}
|
|
|
|
if (g_isp_lib[pipe].ae_lib == XMEDIA_FALSE) {
|
|
puts("isp not register ae lib!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (g_isp_lib[pipe].awb_lib == XMEDIA_FALSE) {
|
|
puts("isp not register awb lib!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
ctx = malloc(sizeof(isp_context));
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp malloc ctx failed!\n");
|
|
return XMEDIA_ERRCODE_NO_BUFFER_FREE;
|
|
}
|
|
g_isp_ctx[pipe] = ctx;
|
|
g_isp_ctx[pipe]->lib_info = &g_isp_lib[pipe];
|
|
|
|
g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_black_level(
|
|
g_isp_ctx[pipe]->lib_info->sensor_info.dev_id, &blc);
|
|
|
|
ae_param.balck_level[0] = blc.black_level[0];
|
|
ae_param.balck_level[1] = blc.black_level[1];
|
|
ae_param.balck_level[2] = blc.black_level[2];
|
|
ae_param.balck_level[3] = blc.black_level[3];
|
|
ae_param.sensor_id = 0;
|
|
ae_param.wdr_mode = cfg->wdr_mode;
|
|
ae_param.hdr_mode = cfg->wdr_mode;
|
|
ae_param.fps = cfg->fps;
|
|
ae_param.bayer_format = cfg->bayer_fmt;
|
|
ae_param.blend_config.blend_en = XMEDIA_FALSE;
|
|
ae_param.blend_config.blend_num = 0;
|
|
if (cfg->mode_config.work_mode == XMEDIA_ISP_WORK_MODE_MASTER) {
|
|
ae_param.blend_config.blend_en = cfg->mode_config.master_mode.blend_stat_enable;
|
|
ae_param.blend_config.blend_num = cfg->mode_config.master_mode.slave_num + 1;
|
|
}
|
|
g_isp_ctx[pipe]->lib_info->ae_info.pfn_ae_init(g_isp_ctx[pipe]->lib_info->ae_info.alg_id, &ae_param);
|
|
|
|
awb_param.wdr_mode = cfg->wdr_mode;
|
|
awb_param.init_iso = 100;
|
|
if (cfg->mode_config.work_mode == XMEDIA_ISP_WORK_MODE_MASTER) {
|
|
awb_param.blend_config.blend_en = cfg->mode_config.master_mode.blend_stat_enable;
|
|
awb_param.blend_config.blend_num = cfg->mode_config.master_mode.slave_num + 1;
|
|
}
|
|
g_isp_ctx[pipe]->lib_info->awb_info.pfn_awb_init(g_isp_ctx[pipe]->lib_info->awb_info.alg_id, &awb_param);
|
|
|
|
ctx->result = (xmedia_sensor_init_param *)CONFIG_PARAM_MEM_START;
|
|
memset(ctx->result, 0, sizeof(xmedia_sensor_init_param));
|
|
|
|
ret = hal_isp_init(pipe, cfg, &blc);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_init failed.\n");
|
|
return ret;
|
|
}
|
|
|
|
if (cfg->wdr_mode == XMEDIA_VIDEO_WDR_MODE_BUILT_IN ) {
|
|
if (g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_default == XMEDIA_NULL ) {
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_default(
|
|
g_isp_ctx[pipe]->lib_info->sensor_info.dev_id, &isp_default);
|
|
ret = hal_isp_init_expander(pipe, isp_default.expander);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_init_expander failed.\n");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
end = isp_get_time_stamp();
|
|
puts("isp init cost time: ");
|
|
putdec(end - start);
|
|
puts(" us\n");
|
|
#endif
|
|
|
|
#if ISP_COUNT_SIZE_DEBUG
|
|
puts("isp_context size = ");
|
|
putdec(sizeof(isp_context));
|
|
puts("\n");
|
|
puts("g_isp_ctx size = ");
|
|
putdec(sizeof(g_isp_ctx));
|
|
puts("\n");
|
|
puts("g_isp_lib size = ");
|
|
putdec(sizeof(g_isp_lib));
|
|
puts("\n");
|
|
puts("g_sensor_clk_ch size = ");
|
|
putdec(sizeof(g_sensor_clk_ch));
|
|
puts("\n");
|
|
puts("g_sensor_rst_ch size = ");
|
|
putdec(sizeof(g_sensor_rst_ch));
|
|
puts("\n");
|
|
#endif
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 drv_isp_exit(xmedia_u32 pipe)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp ctx not exist!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
g_isp_ctx[pipe]->lib_info->ae_info.pfn_ae_exit(g_isp_ctx[pipe]->lib_info->ae_info.alg_id);
|
|
g_isp_ctx[pipe]->lib_info->awb_info.pfn_awb_exit(g_isp_ctx[pipe]->lib_info->awb_info.alg_id);
|
|
|
|
free(ctx);
|
|
g_isp_ctx[pipe] = XMEDIA_NULL;
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 drv_isp_start(xmedia_u32 pipe)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp ctx not exist!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 drv_isp_stop(xmedia_u32 pipe)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp ctx not exist!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 drv_isp_notifier(xmedia_u32 pipe, isp_irq_type irq_type)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
xmedia_s32 ret;
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
xmedia_u32 start, end;
|
|
|
|
start = isp_get_time_stamp();
|
|
#endif
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp ctx not exist!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
if (irq_type == ISP_IRQ_TYPE_BE_FRAME_END) {
|
|
ret = hal_isp_format_statistics(pipe);
|
|
#if ISP_COST_TIME_DEBUG
|
|
end = isp_get_time_stamp();
|
|
puts("isp ISP_IRQ_TYPE_BE_FRAME_END cost time: ");
|
|
putdec(end - start);
|
|
puts(" us\n");
|
|
#endif
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_format_statistics failed!\n");
|
|
return ret;
|
|
}
|
|
} else if (irq_type == ISP_IRQ_TYPE_FE_FRAME_START) {
|
|
ret = hal_isp_sync(pipe);
|
|
#if ISP_COST_TIME_DEBUG
|
|
end = isp_get_time_stamp();
|
|
puts("isp ISP_IRQ_TYPE_FE_FRAME_START cost time: ");
|
|
putdec(end - start);
|
|
puts(" us\n");
|
|
#endif
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_sync failed!\n");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
// TODO: 统计耗时
|
|
xmedia_s32 drv_isp_process(xmedia_u32 pipe)
|
|
{
|
|
isp_context *ctx = XMEDIA_NULL;
|
|
xmedia_s32 ret;
|
|
xmedia_isp_statistics isp_stat = { 0 };
|
|
xmedia_isp_ae_info ae_info = { 0 };
|
|
xmedia_isp_awb_info awb_info = { 0 };
|
|
xmedia_isp_result isp_result = { 0 };
|
|
xmedia_sensor_regs_info reg_info = { 0 };
|
|
static xmedia_u64 last_frame_cnt = -1;
|
|
xmedia_u64 sys_gain;
|
|
xmedia_s32 i;
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
xmedia_u32 start, end;
|
|
|
|
start = isp_get_time_stamp();
|
|
#endif
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ISP_GET_CTX(pipe, ctx);
|
|
if (ctx == XMEDIA_NULL) {
|
|
puts("isp ctx not exist!\n");
|
|
return XMEDIA_ERRCODE_NOT_EXIST;
|
|
}
|
|
|
|
ret = hal_isp_stat(pipe, &isp_stat);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_stat failed!\n");
|
|
return ret;
|
|
}
|
|
|
|
if (last_frame_cnt == isp_stat.ae_stat.frame_cnt) {
|
|
return XMEDIA_ERRCODE_NOT_READY;
|
|
}
|
|
last_frame_cnt = isp_stat.ae_stat.frame_cnt;
|
|
|
|
ae_info.frame_cnt = isp_stat.ae_stat.frame_cnt;
|
|
ae_info.be_ae_stat_global_avg = &isp_stat.ae_stat.ae_stat_global_avg;
|
|
ae_info.be_ae_stat_hist = isp_stat.ae_stat.ae_stat_hist;
|
|
ctx->lib_info->ae_info.pfn_ae_run(ctx->lib_info->ae_info.alg_id, &ae_info, &isp_result.ae_result);
|
|
|
|
// awb分块统计信息是紧凑排布的,即行与行之间没有空白内存
|
|
awb_info.frame_cnt = isp_stat.awb_stat.frame_cnt;
|
|
awb_info.awb_zone_row = isp_stat.awb_stat.awb_zone_row_num;
|
|
awb_info.awb_zone_col = isp_stat.awb_stat.awb_zone_col_num;
|
|
awb_info.awb_width = isp_stat.awb_stat.awb_width;
|
|
awb_info.awb_height = isp_stat.awb_stat.awb_height;
|
|
awb_info.awb_stat_switch = XMEDIA_ISP_AE_SWITCH_AFTER_DGN2;
|
|
awb_info.awb_stat_local_avg_r = (xmedia_isp_awb_stat_local_avg_r *)isp_stat.awb_stat.awb_zone_avg_r;
|
|
awb_info.awb_stat_local_avg_g = (xmedia_isp_awb_stat_local_avg_g *)isp_stat.awb_stat.awb_zone_avg_g;
|
|
awb_info.awb_stat_local_avg_b = (xmedia_isp_awb_stat_local_avg_b *)isp_stat.awb_stat.awb_zone_avg_b;
|
|
awb_info.stat_local_valid_count = (xmedia_isp_awb_stat_local_valid_count *)isp_stat.awb_stat.awb_zone_valid_count;
|
|
ctx->lib_info->awb_info.pfn_awb_run(ctx->lib_info->awb_info.alg_id, &awb_info, &isp_result.awb_result);
|
|
|
|
sys_gain = (xmedia_u64)isp_result.ae_result.again * isp_result.ae_result.dgain * isp_result.ae_result.isp_dgain /
|
|
(1024 * 1024 * 256 / 64);
|
|
ctx->result->exp_time = isp_result.ae_result.int_time[0];
|
|
ctx->result->again = isp_result.ae_result.again;
|
|
ctx->result->dgain = isp_result.ae_result.dgain;
|
|
ctx->result->ispdgain = isp_result.ae_result.isp_dgain;
|
|
ctx->result->init_iso = isp_result.ae_result.iso;
|
|
ctx->result->exposure = (xmedia_u64)isp_result.ae_result.int_time[0] * sys_gain;
|
|
ctx->result->wb_rgain = isp_result.awb_result.white_balance_gain[0];
|
|
ctx->result->wb_ggain = isp_result.awb_result.white_balance_gain[1];
|
|
ctx->result->wb_bgain = isp_result.awb_result.white_balance_gain[3];
|
|
for (i = 0; i < XMEDIA_SENSOR_CCM_MATRIX_SIZE; i++) {
|
|
if (isp_result.awb_result.color_matrix[i] < 0) {
|
|
ctx->result->ccm[i] = CCM_MINUS_PARAM_TH - isp_result.awb_result.color_matrix[i];
|
|
} else {
|
|
ctx->result->ccm[i] = isp_result.awb_result.color_matrix[i];
|
|
}
|
|
}
|
|
ctx->lib_info->sensor_info.isp_func.pfn_sensor_get_reg_info(ctx->lib_info->sensor_info.dev_id, ®_info);
|
|
|
|
ret = hal_isp_update(pipe, &isp_result, ®_info);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_update failed!\n");
|
|
return ret;
|
|
}
|
|
|
|
#if 0
|
|
puts("debug dudu r");
|
|
puthex(ctx->result->wb_rgain);
|
|
puts(" g");
|
|
puthex(ctx->result->wb_ggain);
|
|
puts(" b");
|
|
puthex(ctx->result->wb_bgain);
|
|
puts("\n");
|
|
puts("isp process frame count [");
|
|
putdec(isp_stat.ae_stat.frame_cnt);
|
|
puts("]\n");
|
|
#endif
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
end = isp_get_time_stamp();
|
|
puts("isp process cost time: ");
|
|
putdec(end - start);
|
|
puts(" us\n");
|
|
#endif
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 drv_isp_config(xmedia_u32 pipe)
|
|
{
|
|
xmedia_s32 ret;
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
xmedia_u32 start, end;
|
|
|
|
start = isp_get_time_stamp();
|
|
#endif
|
|
|
|
if (pipe >= ISP_PIPE_MAX_NUM) {
|
|
puts("isp invalid param!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
ret = hal_isp_config(pipe);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
puts("isp hal_isp_config failed!\n");
|
|
return ret;
|
|
}
|
|
|
|
#if ISP_COST_TIME_DEBUG
|
|
end = isp_get_time_stamp();
|
|
puts("isp config cost time: ");
|
|
putdec(end - start);
|
|
puts(" us\n");
|
|
#endif
|
|
|
|
return XMEDIA_SUCCESS;
|
|
} |