GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += drivers/
SRCS-y += devices/
SRCS-y += sensors/
SRCS-y += sample/
+1
View File
@@ -0,0 +1 @@
../../source/gmp/usr/isp/libs/riscv
+3
View File
@@ -0,0 +1,3 @@
SRCS-y += i2c_dev.c
+30
View File
@@ -0,0 +1,30 @@
#include"xmedia_type.h"
#include"xmedia_errcode.h"
#include"i2c.h"
#include "compile.h"
#define REG_ADDR_MAX_WIDTH 2//16BIT
STAGE1_FUNC xmedia_s32 i2c_read(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u32 read_addr,
xmedia_u8 addr_width, xmedia_u8 *buff, xmedia_u32 length)
{
struct i2c_client client;
if(addr_width > REG_ADDR_MAX_WIDTH){
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
client.i2c_num = fd;
client.dev_addr = slave_addr >> 1;
client.reg_addr = read_addr;
client.reg_width = addr_width;
return i2c_recv(&client, buff, length);
}
STAGE1_FUNC xmedia_s32 i2c_write(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u8 *buff, xmedia_u32 length)
{
return i2c_send(fd, slave_addr >> 1, (xmedia_void *)buff, length);
}
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += hal_isp.c
SRCS-y += drv_isp.c
SRCS-y += hal_vi.c
SRCS-y += drv_vi.c
+826
View File
@@ -0,0 +1,826 @@
#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, &reg_info);
ret = hal_isp_update(pipe, &isp_result, &reg_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;
}
+241
View File
@@ -0,0 +1,241 @@
#include "stdio.h"
#include "defines.h"
#include "interrupt.h"
#include "drv_vi.h"
#include "drv_isp.h"
#include "hal_vi.h"
#include <timer.h>
#define VICAP_IRQ_DEBUG 0
#define VIPROC_IRQ_DEBUG 0
static xmedia_bool vi_vicap_is_report_int(xmedia_u32 fe_id, xmedia_u32 int_status)
{
xmedia_u32 fe_int_mask[VI_MAX_PHY_PIPE_NUM] = { 0x1 << 5, 0x1 << 6, 0x1 << 7, 0x1 << 8 };
if (int_status & fe_int_mask[fe_id]) {
return XMEDIA_TRUE;
}
return XMEDIA_FALSE;
}
static xmedia_void vi_vicap_irq_callback_proc(xmedia_u32 vicap_wch, xmedia_u32 irq_status)
{
if (irq_status & VI_CAP_FRAME_START_INT) {
drv_isp_notifier(vicap_wch, ISP_IRQ_TYPE_FE_FRAME_START);
}
if (irq_status & VI_CAP_FRAME_EARLY_INT) {
// vicap reg newer
hal_vi_vicap_reg_newer(vicap_wch);
}
if (irq_status & VI_CAP_FRAME_LOWDELAY_INT) {
}
if (irq_status & VI_CAP_FRAME_END_INT) {
drv_isp_notifier(vicap_wch, ISP_IRQ_TYPE_FE_FRAME_END);
}
if (irq_status & VI_CAP_FRAME_TIMEOUT_INT) {
puts("vicap timeout int!\n");
}
if (irq_status & VI_CAP_FRAME_ERR_INT) {
puthex(irq_status);
puts("vicap err int!\n");
}
}
ATTRIBUTE_ISR xmedia_void vi_vicap_irq_route(xmedia_void)
{
xmedia_s32 vicap_wch;
xmedia_u32 vicap_int_status;
xmedia_u32 vicap_int_mask;
xmedia_u32 irq_status;
vicap_int_status = hal_vi_vicap_get_top_int_status(0);
vicap_int_mask = hal_vi_vicap_get_top_int_mask(0);
vicap_int_status &= (~vicap_int_mask);
for (vicap_wch = VI_MAX_PHY_PIPE_NUM - 1; vicap_wch >= 0; vicap_wch--) {
if (vi_vicap_is_report_int(vicap_wch, vicap_int_status) == XMEDIA_FALSE) {
continue;
}
irq_status = hal_vi_vicap_get_chn_int_status(vicap_wch);
hal_vi_vicap_clear_int(vicap_wch, irq_status);
#if VICAP_IRQ_DEBUG
puts("vicap irq_status 0x");
puthex(irq_status);
puts("\n");
#endif
vi_vicap_irq_callback_proc(vicap_wch, irq_status);
}
}
static xmedia_void vi_viproc_irq_callback_proc(xmedia_u32 pipe, xmedia_u32 irq_status)
{
if (irq_status & VI_PROC_FRAME_START_INT) {
}
if (irq_status & VI_PROC_FRAME_EARLY_INT) {
drv_isp_config(pipe); // 配置isp be算法寄存器
hal_vi_viproc_reg_start(0);
}
if (irq_status & VI_PROC_FRAME_END_INT || irq_status & VI_PROC_FRAME_LIST_INT) {
drv_isp_notifier(pipe, ISP_IRQ_TYPE_BE_FRAME_END);
}
if (irq_status & VI_PROC_LOWDELAY_INT) {
}
if (irq_status & VI_PROC_FRAME_ERR_INT) {
puts("viproc err int!\n");
}
if (irq_status & VI_PROC_FRAME_TIMEOUT_INT) {
puts("viproc timeout int!\n");
}
if (irq_status & VI_PROC_FRAME_ERR_IGNORE_INT) {
puts("viproc err ignore int!\n");
}
}
ATTRIBUTE_ISR xmedia_void vi_viproc_irq_route(xmedia_void)
{
xmedia_u32 pipe = 0; // 对外暂时仅支持pipe 0
xmedia_u32 cl_irq_status;
xmedia_u32 irq_status;
xmedia_u32 irq_mask;
xmedia_u32 early_mask;
irq_status = hal_viproc_get_reg_public_int_status(0); // viproc irq status
irq_mask = hal_viproc_get_reg_public_int_mask(0); // irq mask
early_mask = hal_viproc_common_get_reg_early_mask(0); // early irq mask
cl_irq_status = irq_status;
irq_status &= (~(irq_mask | early_mask));
hal_viproc_clr_reg_int(0, cl_irq_status); // clear int
#if VIPROC_IRQ_DEBUG
puts("viproc irq_status 0x");
puthex(irq_status);
puts("\n");
#endif
vi_viproc_irq_callback_proc(pipe, irq_status);
}
STAGE1_FUNC xmedia_void drv_mipi_init(xmedia_void)
{
hal_mipi_init();
}
STAGE1_FUNC xmedia_s32 drv_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
return hal_mipi_enable(dev, dev_config);
}
xmedia_s32 drv_vi_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_u32 vicap_irq_num;
xmedia_u32 viproc_irq_num;
// 注册vicap中断、viproc中断
vicap_irq_num = hal_vi_get_vicap_irq_num(0);
viproc_irq_num = hal_vi_get_viproc_irq_num(0);
ret = drv_irq_register(vicap_irq_num, vi_vicap_irq_route);
if (ret < 0) {
puts("Fail to register vicap irq!\n");
return ret;
}
ret = drv_irq_register(viproc_irq_num, vi_viproc_irq_route);
if (ret < 0) {
puts("Fail to register viproc irq!\n");
drv_irq_unregister(vicap_irq_num);
return ret;
}
hal_vi_init();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_exit(xmedia_void)
{
xmedia_u32 vicap_irq_num;
xmedia_u32 viproc_irq_num;
// 反注册中断
vicap_irq_num = hal_vi_get_vicap_irq_num(0);
viproc_irq_num = hal_vi_get_viproc_irq_num(0);
drv_irq_unregister(vicap_irq_num);
drv_irq_unregister(viproc_irq_num);
hal_vi_exit();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_enable_dev(xmedia_s32 dev)
{
return hal_vi_enable_dev(dev);
}
xmedia_s32 drv_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
hal_vi_disable_dev(dev, dev_config);
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 pipe)
{
return hal_vi_set_dev_bind_pipe(dev, pipe);
}
xmedia_s32 drv_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 pipe)
{
hal_vi_set_dev_unbind_pipe(dev, pipe);
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_start_pipe(xmedia_s32 pipe, xmedia_vi_pipe_config *pipe_config)
{
xmedia_s32 ret;
ret = hal_vi_start_vicap(pipe, pipe_config);
if (ret != XMEDIA_SUCCESS) {
puts("start vicap failed\n");
return ret;
}
// 调用isp update be接口,配置第一帧算法参数
drv_isp_config(pipe);
ret = hal_vi_start_viproc(pipe, pipe_config);
if (ret != XMEDIA_SUCCESS) {
puts("start viproc failed\n");
hal_vi_stop_vicap(pipe);
return ret;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_stop_pipe(xmedia_s32 pipe)
{
hal_vi_stop_viproc(pipe);
hal_vi_stop_vicap(pipe);
return XMEDIA_SUCCESS;
}
+2065
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
#ifndef _HAL_ISP_H_
#define _HAL_ISP_H_
xmedia_void delay(xmedia_u32 us);
xmedia_s32 hal_sensor_reset(xmedia_u32 ch, xmedia_bool enable);
xmedia_s32 hal_sensor_read_mclk(xmedia_u32 ch, xmedia_u32 *clk);
xmedia_s32 hal_sensor_set_mclk(xmedia_u32 ch, xmedia_u32 clk);
xmedia_s32 hal_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg, xmedia_sensor_black_level *blc);
xmedia_s32 hal_isp_init_expander(xmedia_u32 pipe, const xmedia_isp_expander_attr *attr);
xmedia_s32 hal_isp_stat(xmedia_u32 pipe, xmedia_isp_statistics *stat);
xmedia_s32 hal_isp_update(xmedia_u32 pipe, xmedia_isp_result *result, xmedia_sensor_regs_info *reg_info);
xmedia_s32 hal_isp_format_statistics(xmedia_u32 pipe);
xmedia_s32 hal_isp_config(xmedia_u32 pipe);
xmedia_s32 hal_isp_sync(xmedia_u32 pipe);
#endif
+933
View File
@@ -0,0 +1,933 @@
#include "stdio.h"
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "defines.h"
#include "hal_vi.h"
/*
* 系统控制寄存器,MISC_CTRL81
* BIT [0] :
* 0:MIPI_RX_PHY1连接MIPI_2L_RX0控制器
* 1:MIPI_RX_PHY1连接MIPI_4L_RX0控制器
* BIT [1] :
* 0:MIPI_RX_PHY3连接MIPI_2L_RX1控制器
* 1:MIPI_RX_PHY3连接MIPI_4L_RX1控制器
* */
#define MIPI_MISC_CTRL 0x12028900
#define VIPROC_EXTERNAL_TIMING_EN_ADDR 0x1202899C
#define CRG_REGS_ADDR 0x12010000
#define VICAP_IRQ_NUM 66
#define VIPROC0_IRQ_NUM 63
#define VI_RESET_WAIT_CNT 100
typedef struct {
xmedia_u32 phy0_data_lane0;
xmedia_u32 phy0_data_lane1;
xmedia_u32 phy1_data_lane0;
xmedia_u32 phy1_data_lane1;
xmedia_u32 phy0_clk_sel;
xmedia_u32 phy1_clk_sel;
} mipi_lane_swap_attr;
volatile xmedia_u32 g_vicap_all_reg[VICAP_IP_NUM] = { 0x11000000 };
volatile xmedia_u32 g_viproc_all_reg[VIPROC_IP_NUM] = { 0x11200000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_rx_reg[VI_MIPI_RX_NUM] = { 0x10fe0000, 0x11010000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_phy_reg_addr = 0x12028900;
STAGE1_FUNC static xmedia_u32 vi_read_reg(volatile xmedia_uintptr_t addr)
{
return *(volatile xmedia_u32 *)(addr);
}
STAGE1_FUNC static xmedia_void vi_write_reg(volatile xmedia_uintptr_t addr, xmedia_u32 val)
{
*(volatile xmedia_u32 *)(addr) = val;
}
STAGE1_FUNC xmedia_void vi_reg_write_bit(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos)
{
xmedia_u32 t, mask;
mask = 1 << bit_pos;
t = vi_read_reg(addr);
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
STAGE1_FUNC xmedia_void vi_reg_write_32(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos, xmedia_u32 bit_count)
{
xmedia_u32 t;
xmedia_u32 mask;
t = vi_read_reg(addr);
mask = ((1U << bit_count) - 1) << bit_pos;
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
static xmedia_s32 vi_dev_reset(xmedia_s32 dev, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 4 + dev); // 4 : pt0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("dev reset err\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_fe_reset(xmedia_s32 fe_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 9 + fe_id); // 9 : fe0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_viproc_reset_set(xmedia_u32 proc_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, reset, 4); // 4 : viproc reset offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("viproc reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_all_reset(xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 17); // [17] : vicap总软复位请求
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_clk_reset_init(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, XMEDIA_TRUE, 0); // enable vicap clk
sleep_us(5); // 等待时钟稳定
if (vi_vicap_all_reset(XMEDIA_FALSE) != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_vicap_clk_reset_deinit(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
vi_dev_reset(dev, XMEDIA_TRUE);
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
vi_vicap_fe_reset(fe, XMEDIA_TRUE);
}
vi_vicap_all_reset(XMEDIA_TRUE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, 0, 0);
}
static xmedia_s32 vi_viproc_clk_reset_init(xmedia_u32 proc_id)
{
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_TRUE, 0);
sleep_us(5); // 等待时钟稳定
if (vi_viproc_reset_set(proc_id, XMEDIA_FALSE) != 0) {
puts("viproc clk reset false failed\n");
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_viproc_clk_reset_deinit(xmedia_u32 proc_id)
{
vi_viproc_reset_set(proc_id, XMEDIA_TRUE);
vi_viproc_reset_set(proc_id, XMEDIA_FALSE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_FALSE, 0);
}
STAGE1_FUNC static xmedia_void mipi_rx_set_misc_sel(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode mipi_lane_num)
{
volatile xmedia_u32 mipi_misc_reg = MIPI_MISC_CTRL;
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
if (dev_id == 0) {
vi_reg_write_bit(mipi_misc_reg, 1, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 1, 1);
}
} else {
if (dev_id == 0 || dev_id == 1) {
vi_reg_write_bit(mipi_misc_reg, 0, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 0, 1);
}
}
}
static xmedia_void mipi_rx_phy_get_lane_swap(xmedia_s32 dev_id, const xmedia_vi_dev_config *dev_config,
mipi_lane_swap_attr *lane_swap_mode)
{
/*
* 默认phy与lane的链接关系:
* mipi0-phy0-data0-lane0
* mipi0-phy0-data1-lane1
* mipi1-phy1-data0-lane2
* mipi1-phy1-data1-lane3
*/
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy0_clk_sel = 0;
} else { // VI_DEV1
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy1_clk_sel = 0;
}
}
if (dev_config->lane_config.enable != XMEDIA_TRUE) {
return;
}
// 用户任意配置链接关系
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[2];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[3];
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy0_clk_sel = (lane_swap_mode->phy0_data_lane0 > 1) ? 1 : 0;
} else {
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_clk_sel = (lane_swap_mode->phy1_data_lane0 > 1) ? 0 : 1;
}
}
}
static xmedia_void mipi_rx_phy_lane_swap(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode lane_mode,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
} else if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
} else {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
}
}
STAGE1_FUNC static xmedia_void mipi_rx_phy_init(xmedia_s32 dev_id, xmedia_u32 mipi_rate,
xmedia_vi_mipi_lane_divide_mode mipi_lane_num,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
xmedia_u32 data_rate;
xmedia_u32 td_term_en_max;
xmedia_u32 td_term_en;
xmedia_u32 ths_settle_max;
xmedia_u32 ths_settle;
xmedia_u32 tclk_term_en_max;
xmedia_u32 tclk_term_en;
xmedia_u32 tclk_settle_max;
xmedia_u32 tclk_settle;
xmedia_u32 tx_clk_esc = 24; // 24MHz 晶振配置 (T-tx_clk_esc = 41.7 ns)
if (mipi_rate == 0) {
puts("mipi_rate invalid");
puts("\n");
}
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(mipi_phy_addr, 1, 0); // mipirxphy_sel
} else {
vi_reg_write_bit(mipi_phy_addr, 0, 0); // mipirxphy_sel
}
mipi_rx_phy_lane_swap(dev_id, mipi_lane_num, lane_swap);
data_rate = mipi_rate;
td_term_en_max = 35 + 4000 / data_rate;
td_term_en = td_term_en_max * data_rate / 2000 - 1;
ths_settle_max = 145 + 10 * 1000 / data_rate;
ths_settle = (ths_settle_max - td_term_en * 2000 / data_rate) * data_rate / 2000 - 1;
tclk_term_en_max = 38;
tclk_term_en = (tx_clk_esc * tclk_term_en_max) / 1000;
tclk_settle_max = 300;
tclk_settle = (tclk_settle_max - tclk_term_en * 1000 / tx_clk_esc) * tx_clk_esc / 1000 - 1;
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xb4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 2); // dl1_enable
} else if (dev_id == 1) {
vi_reg_write_32(mipi_phy_addr + 0xd4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 2); // dl1_enable
} else {
puts("mipi phy num err, dev_id ");
putdec(dev_id);
puts("\n");
}
}
STAGE1_GLOBAL static xmedia_u32 ret_mipi_date_type[10] = { 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x27, 0x18, 0x1a, 0x1e };
STAGE1_FUNC xmedia_u32 mipi_rx_get_data_type(xmedia_intf_mipi_csi_data_type data_type)
{
return ret_mipi_date_type[data_type];
}
STAGE1_FUNC xmedia_void mipi_rx_set_ipi_reg(xmedia_s32 dev_id, xmedia_intf_mipi_csi_data_type data_type)
{
volatile unsigned int mipi_rx_addr = g_mipi_rx_reg[dev_id];
xmedia_u32 ipi_data_type;
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 24); // ipi enable
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 16); // ipi_cut_through
// ipi_color_com
if (data_type <= XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_16BIT) {
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 8);
} else {
vi_reg_write_bit(mipi_rx_addr + 0x80, 0, 8);
}
vi_reg_write_32(mipi_rx_addr + 0x84, 0, 0, 2); // ipi vc id
ipi_data_type = mipi_rx_get_data_type(data_type);
vi_reg_write_32(mipi_rx_addr + 0x88, ipi_data_type, 0, 6); // ipi data type
vi_reg_write_bit(mipi_rx_addr + 0x88, 1, 8); // embedded_data[A]
vi_reg_write_bit(mipi_rx_addr + 0x8c, 1, 8); // ipi mem auto flush
vi_reg_write_32(mipi_rx_addr + 0x90, 0xa, 0, 12); // hsa
vi_reg_write_32(mipi_rx_addr + 0x94, 0xa, 0, 12); // hbp
vi_reg_write_32(mipi_rx_addr + 0x98, 0xa, 0, 12); // hsd
vi_reg_write_32(mipi_rx_addr + 0x9c, 0x898, 0, 15); // hline_time
vi_reg_write_bit(mipi_rx_addr + 0xa0, 1, 0); // soft reset
// advanced feature
vi_reg_write_bit(mipi_rx_addr + 0xac, 0, 0);
vi_reg_write_32(mipi_rx_addr + 0xac, 0, 8, 6);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 16);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 17);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 18);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 19);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 20);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 21);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 22);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 24);
}
xmedia_u32 vi_get_bit_width(xmedia_video_data_width data_width)
{
xmedia_u32 bit_width;
switch (data_width) {
case XMEDIA_VIDEO_DATA_WIDTH_8:
bit_width = 8;
break;
case XMEDIA_VIDEO_DATA_WIDTH_10:
bit_width = 10;
break;
case XMEDIA_VIDEO_DATA_WIDTH_12:
bit_width = 12;
break;
case XMEDIA_VIDEO_DATA_WIDTH_14:
bit_width = 14;
break;
case XMEDIA_VIDEO_DATA_WIDTH_16:
bit_width = 16;
break;
default:
bit_width = 16;
break;
}
return bit_width;
}
xmedia_u32 vi_viproc_get_bit_deepth(xmedia_video_data_width bit_width, xmedia_video_wdr_mode wdr_mode)
{
if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_NONE) {
return VI_PACK_12BIT;
} else if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_BUILT_IN) {
if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_8) {
return VI_PACK_8BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_10) {
return VI_PACK_10BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_12) {
return VI_PACK_12BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_14) {
return VI_PACK_14BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_16) {
return VI_PACK_16BIT;
} else {
puts("viproc built-in wdr mode not support bit_width ");
putdec(bit_width);
puts("\n");
return VI_PACK_12BIT;
}
} else {
puts("viproc not support wdr_mode ");
putdec(wdr_mode);
puts("\n");
return VI_PACK_12BIT;
}
}
xmedia_void hal_vi_vicap_reg_newer(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0x48), 1, 0);
}
xmedia_void hal_vi_vicap_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 bit_width;
// input_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->height, 16, 14);
// bit_width
bit_width = vi_get_bit_width(pipe_config->bit_width);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x28), bit_width, 16, 6);
// output_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->height, 16, 14);
// vicap reg newer
hal_vi_vicap_reg_newer(fe_id);
// todo offline set_output_memory
if (pipe_config->vi_work_mode == 1) {
}
}
xmedia_u32 hal_vi_vicap_get_top_int_status(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_status = vi_read_reg(vicap_addr + 0x10);
return top_int_status;
}
xmedia_u32 hal_vi_vicap_get_top_int_mask(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_mask;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_mask = vi_read_reg(vicap_addr + 0x14);
return top_int_mask;
}
xmedia_u32 hal_vi_vicap_get_chn_int_status(xmedia_s32 fe_id)
{
xmedia_u32 irq_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
irq_status = vi_read_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40));
return irq_status;
}
xmedia_void hal_vi_vicap_clear_int(xmedia_s32 fe_id, xmedia_u32 mask)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_write_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), mask); // clear int
}
xmedia_s32 hal_vi_get_vicap_irq_num(xmedia_u32 vicap_id)
{
return VICAP_IRQ_NUM;
}
xmedia_s32 hal_vi_get_viproc_irq_num(xmedia_u32 viproc_id)
{
return VIPROC0_IRQ_NUM;
}
xmedia_u32 hal_viproc_get_reg_public_int_status(xmedia_u32 viproc_id)
{
xmedia_u32 int_status;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_status = vi_read_reg(viproc_addr + 0x48);
return int_status;
}
xmedia_u32 hal_viproc_get_reg_public_int_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x2c);
return int_mask;
}
xmedia_u32 hal_viproc_common_get_reg_early_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x1e8);
return int_mask;
}
xmedia_void hal_viproc_clr_reg_int(xmedia_u32 viproc_id, xmedia_u32 mask)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_write_reg(viproc_addr + 0x48, mask);
}
STAGE1_FUNC xmedia_void hal_mipi_init(xmedia_void)
{
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
}
STAGE1_FUNC xmedia_s32 hal_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 mipi_lane_num = 0;
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
mipi_lane_swap_attr lane_swap_mode = { 0 };
// mipi_rx mipi_phy clk enable
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, dev); // mipi_rx_cken
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 3); // mipi_rx0_4line_cken
}
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 9); // mipi_phy0_cken
// 延时5 us,等待时钟稳定
sleep_us(5);
// mipi_rx复位
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_FALSE, 0);
sleep_us(5);
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_TRUE, 0);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE) {
mipi_lane_num = 0x0;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
mipi_lane_num = 0x1;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_lane_num = 0x3;
} else {
// mipi_lane错误参数
puts("vi mipi lane is invalid\n");
}
vi_reg_write_32(mipi_rx_addr + 0x4, mipi_lane_num, 0, 3); // mipi_lane
vi_reg_write_bit(mipi_rx_addr + 0x44, 1, 0); // mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 1, 0); // mipi0_phy_shutdownz
mipi_rx_set_misc_sel(dev, dev_config->mipi_lane_num);
mipi_rx_phy_get_lane_swap(dev, dev_config, &lane_swap_mode);
mipi_rx_phy_init(dev, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_rx_phy_init(dev + 1, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
}
sleep_us(5);
mipi_rx_set_ipi_reg(dev, dev_config->data_type); // ipi cfg, todo:暂不考虑wdr
vi_reg_write_32(mipi_rx_addr + 0x640, 0, 0, 3); // hdr_data_mode,0:VC
vi_reg_write_32(mipi_rx_addr + 0x654, 0x142, 0, 16); // rft_speeder
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_init(xmedia_void)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// 初始化mipi_rx、vicap、viproc时钟
// vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 3, 3); // bit[3:5]: vicap_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 6, 3); // bit[6:8]: viproc_clk_sel
// vicap时钟使能,dev、fe复位
vi_vicap_clk_reset_init(0);
// viproc时钟使能、复位,init开启时钟,isp_init需要配置viproc算法寄存器
vi_viproc_clk_reset_init(0);
// vicap viproc outstanding
vi_reg_write_32(vicap_addr + 0x74, 0x88, 0, 9);
vi_reg_write_32(viproc_addr + 0x10, 0x10, 8, 5); // wr outstanding
vi_reg_write_32(viproc_addr + 0x10, 0x20, 16, 6); // rd outstanding
// 屏蔽中断
vi_reg_write_32(vicap_addr + 0x14, 0x7fffff, 0, 23); // top mask
}
xmedia_void hal_vi_exit(xmedia_void)
{
// viproc时钟去使能,dev、fe复位
// vi_viproc_clk_reset_deinit(0);
// vicap时钟去使能,dev、fe复位
vi_vicap_clk_reset_deinit(0);
}
xmedia_s32 hal_vi_enable_dev(xmedia_s32 dev)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// pt intf modetodo :其他接口待适配
if (dev == 0) {
vi_reg_write_32(vicap_addr + 0xc, 0, 0, 2);
} else if (dev == 1) {
vi_reg_write_32(vicap_addr + 0xc, 0, 2, 2);
} else if (dev == 2) {
vi_reg_write_32(vicap_addr + 0xc, 0, 4, 3);
} else {
puts("dev_id is err ");
putdec(dev);
puts("\n");
}
// enable pt
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 4); // debug_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
}
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
#if 0
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
vi_reg_write_bit(mipi_rx_addr + 0x44, 0, 0); //mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 0, 0); //mipi0_phy_shutdownz
// mipi_rx mipi_phy clk disable
vi_reg_write_bit(sys_config_addr, 0, dev); // diable mipi_rx clk
vi_reg_write_bit(sys_config_addr, 0, 9 + dev); // diable mipi_rx phy clk
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, 0, 9 + dev + 1);
}
#endif
// disable pt
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 4); // debug_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 2); // ck_dyn_gt_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000) + 0x2c, XMEDIA_FALSE, 0); // ck_dyn_gt_en
}
}
xmedia_s32 hal_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, dev, (fe_id * 3), 3);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, 0, (fe_id * 3), 3);
}
xmedia_s32 hal_vi_start_vicap(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
// 打开对应fe上报中断开关、中断掩码
vi_reg_write_bit(vicap_addr + 0x14, 0, fe_id + 5);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0x6, 0, 16);
// 在线离线工作模式
if (pipe_config->vi_work_mode == 0) {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), XMEDIA_TRUE, 0); // online_en
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_TRUE, 1); // viproc_external_timing_en
} else {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), 0, 0);
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_FALSE, 1);
}
// 设置early行号、early位置
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), 1, 0, 2);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), (pipe_config->height * 4 / 5), 8, 13);
// clear_int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
hal_vi_vicap_online_config(fe_id, pipe_config);
// enable fe
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, fe_id + 5);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_viproc_reg_start(xmedia_u32 viproc_id)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 0); // ctl_up_finish_enable
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 4); // filter_up_finish_enable
}
xmedia_void hal_vi_viproc_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 bit_deepth;
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// inch0_path_sel
vi_reg_write_32(viproc_addr + 0x174, 0, 1, 2);
// list_mode_enable false
vi_reg_write_bit(viproc_addr + 0x14, 0, 8);
// early line/location
vi_reg_write_32(viproc_addr + 0x1dc, 1, 4, 2);
vi_reg_write_32(viproc_addr + 0x1e0, (pipe_config->height * 4 / 5), 16, 14);
// inch0_en
vi_reg_write_bit(viproc_addr + 0x174, XMEDIA_TRUE, 0);
// inch0_bit_deepth
bit_deepth = vi_viproc_get_bit_deepth(pipe_config->bit_width, pipe_config->wdr_mode);
vi_reg_write_32(viproc_addr + 0x174, bit_deepth, 16, 5);
// input_data_mode
vi_reg_write_bit(viproc_addr + 0x16c, 0, 3);
// valid_in_width/height
vi_reg_write_32(viproc_addr + 0x190, pipe_config->width, 0, 14);
vi_reg_write_32(viproc_addr + 0x190, pipe_config->height, 16, 14);
// early mask
vi_reg_write_32(viproc_addr + 0x1e8, 0x6, 0, 3);
// todo:node id
}
xmedia_s32 hal_vi_start_viproc(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// vi_viproc_clk_reset_init(0);
// viproc 中断掩码
vi_reg_write_32(viproc_addr + 0x2c, 0x20, 0, 32);
// viproc clear int
vi_reg_write_32(viproc_addr + 0x48, 0xffffffff, 0, 32);
hal_vi_viproc_online_config(fe_id, pipe_config);
// ctl_up_finish_enable/filter_up_finish_enable
hal_vi_viproc_reg_start(0);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_stop_viproc(xmedia_s32 fe_id)
{
vi_viproc_clk_reset_deinit(0);
}
xmedia_void hal_vi_stop_vicap(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// disable fe
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, fe_id + 5);
// ck_dyn_gt_en_enable
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0xa0), XMEDIA_FALSE, 0);
// int none mask
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0xffff, 0, 16);
// clear int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
vi_vicap_fe_reset(fe_id, XMEDIA_TRUE);
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef __HAL_VI_H_
#define __HAL_VI_H_
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "compile.h"
#define VI_CAP_FRAME_START_INT (0x1 << 6)
#define VI_CAP_FRAME_LOWDELAY_INT (0x1 << 1)
#define VI_CAP_FRAME_EARLY_INT (0x1 << 0)
#define VI_CAP_FRAME_END_INT (0x1 << 7)
#define VI_CAP_FRAME_END_INT_TIMING (0x1 << 11)
#define VI_CAP_FRAME_ERR_INT ((0x1 << 8) | (0x1 << 12) | (0x1 << 3) | (0x1 << 4) | (0x1 << 13))
#define VI_CAP_FRAME_TIMEOUT_INT ((0x1 << 9) | (0x1 << 10))
#define VI_PROC_FRAME_LIST_INT (0x1 << 5)
#define VI_PROC_FRAME_START_INT (0x1 << 3)
#define VI_PROC_FRAME_EARLY_INT (0x1)
#define VI_PROC_LOWDELAY_INT (0x1 << 1)
#define VI_PROC_FRAME_END_INT (0x1 << 4)
#define VI_PROC_FRAME_ERR_INT \
((0x1 << 6) | (0x1 << 7) | (0x1 << 8) | (0x1 << 9) | (0x1 << 13) | (0x1 << 14) | (0x1 << 15) | (0x1 << 16) | \
(0x1 << 17) | (0x1 << 18) | (0x1 << 19) | (0x1 << 20) | (0x1 << 21) | (0x1 << 22) | (0x1 << 27) | (0x1 << 28) | \
(0x1 << 29) | (0x1 << 30) | (0x1 << 31))
#define VI_PROC_FRAME_TIMEOUT_INT ((0x1 << 19) | (0x1 << 20))
#define VI_PROC_FRAME_ERR_IGNORE_INT (0x7 << 10)
#define sleep_us(x) \
do { \
for (xmedia_s32 i = x; i > 0; i--) { \
asm("nop"); \
asm("nop"); \
asm("nop"); \
asm("nop"); \
asm("nop"); \
} \
} while (0)
typedef enum {
VI_PACK_8BIT = 8,
VI_PACK_10BIT = 10,
VI_PACK_12BIT = 12,
VI_PACK_14BIT = 14,
VI_PACK_16BIT = 16,
VI_PACK_MAX,
} vi_pack_bit_width;
xmedia_void hal_vi_vicap_reg_newer(xmedia_s32 fe_id);
xmedia_void hal_vi_vicap_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_u32 hal_vi_vicap_get_top_int_status(xmedia_u32 vicap_id);
xmedia_u32 hal_vi_vicap_get_top_int_mask(xmedia_u32 vicap_id);
xmedia_u32 hal_vi_vicap_get_chn_int_status(xmedia_s32 fe_id);
xmedia_void hal_vi_vicap_clear_int(xmedia_s32 fe_id, xmedia_u32 mask);
xmedia_s32 hal_vi_get_vicap_irq_num(xmedia_u32 vicap_id);
xmedia_s32 hal_vi_get_viproc_irq_num(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_get_reg_public_int_status(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_get_reg_public_int_mask(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_common_get_reg_early_mask(xmedia_u32 viproc_id);
xmedia_void hal_viproc_clr_reg_int(xmedia_u32 viproc_id, xmedia_u32 mask);
xmedia_void hal_vi_init(xmedia_void);
xmedia_void hal_vi_exit(xmedia_void);
xmedia_s32 hal_vi_enable_dev(xmedia_s32 dev);
xmedia_void hal_mipi_init(xmedia_void);
xmedia_s32 hal_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_void hal_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 hal_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 fe_id);
xmedia_void hal_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 fe_id);
xmedia_s32 hal_vi_start_vicap(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_viproc_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_viproc_reg_start(xmedia_u32 viproc_id);
xmedia_s32 hal_vi_start_viproc(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_stop_viproc(xmedia_s32 fe_id);
xmedia_void hal_vi_stop_vicap(xmedia_s32 fe_id);
#endif
+65
View File
@@ -0,0 +1,65 @@
#ifndef _ISP_DEF_H_
#define _ISP_DEF_H_
#include "compile.h"
#define ISP_SUPPORT_PIPE_NUM 1
#if CONFIG_MEDIA_PIPE_NUM > ISP_SUPPORT_PIPE_NUM
#error "NOT supportted CONFIG_MEDIA_PIPE_NUM > 1.\n"
#endif
#define ISP_PIPE_MAX_NUM CONFIG_MEDIA_PIPE_NUM
#define ISP_COST_TIME_DEBUG 0
#define ISP_COUNT_SIZE_DEBUG 0
typedef struct {
xmedia_u32 frame_cnt;
xmedia_isp_awb_stat_global awb_stat_global;
// xmedia_isp_awb_stat_local_avg_r awb_stat_local_avg_r;
// xmedia_isp_awb_stat_local_avg_g awb_stat_local_avg_g;
// xmedia_isp_awb_stat_local_avg_b awb_stat_local_avg_b;
// xmedia_isp_awb_stat_local_valid_count stat_local_valid_count;
xmedia_u32 *awb_zone_avg_r;
xmedia_u32 *awb_zone_avg_g;
xmedia_u32 *awb_zone_avg_b;
xmedia_u32 *awb_zone_valid_count;
xmedia_u8 awb_gain_switch;
xmedia_u8 awb_stat_switch;
xmedia_u32 wdr_wb_gain[XMEDIA_ISP_BAYER_PATTERN_NUM];
xmedia_u8 awb_zone_row_num;
xmedia_u8 awb_zone_col_num;
xmedia_u16 awb_width;
xmedia_u16 awb_height;
} xmedia_isp_awb_stat;
typedef xmedia_isp_be_ae_stat_hist xmedia_isp_ae_stat_hist;
typedef xmedia_isp_be_ae_stat_global_avg xmedia_isp_ae_stat_global_avg;
typedef xmedia_isp_be_ae_stat_zone_avg xmedia_isp_ae_stat_zone_avg;
typedef struct {
xmedia_u64 frame_cnt;
// xmedia_u8 ae_zone_row_num;
// xmedia_u8 ae_zone_col_num;
xmedia_isp_ae_stat_hist ae_stat_hist;
xmedia_isp_ae_stat_global_avg ae_stat_global_avg;
// xmedia_isp_ae_stat_zone_avg ae_stat_zone_avg;
} xmedia_isp_ae_stat;
typedef struct{
xmedia_isp_ae_stat ae_stat;
xmedia_isp_awb_stat awb_stat;
}xmedia_isp_statistics;
typedef struct{
xmedia_isp_ae_result ae_result;
xmedia_isp_awb_result awb_result;
}xmedia_isp_result;
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/common.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/defines.h
+34
View File
@@ -0,0 +1,34 @@
#ifndef _DRV_ISP_H_
#define _DRV_ISP_H_
#include "xmedia_isp.h"
typedef enum {
ISP_IRQ_TYPE_PT_FRAME_START,
ISP_IRQ_TYPE_PT_FRAME_END,
ISP_IRQ_TYPE_FE_FRAME_START,
ISP_IRQ_TYPE_FE_FRAME_END,
ISP_IRQ_TYPE_BE_FRAME_START,
ISP_IRQ_TYPE_BE_FRAME_END,
ISP_IRQ_TYPE_MAX,
} isp_irq_type;
xmedia_s32 drv_sensor_init(xmedia_u32 pipe, xmedia_sensor_config *cfg);
xmedia_s32 drv_sensor_exit(xmedia_u32 pipe);
xmedia_s32 drv_sensor_resume(xmedia_u32 pipe);
xmedia_s32 drv_sensor_start(xmedia_u32 pipe);
xmedia_s32 drv_sensor_stop(xmedia_u32 pipe);
xmedia_s32 drv_sensor_set_mipi_lanes(xmedia_u32 pipe, const xmedia_sensor_mipi_lanes mipi_lanes);
xmedia_s32 drv_sensor_set_attr(xmedia_u32 pipe, const xmedia_sensor_attr *sns_attr);
xmedia_s32 drv_sensor_set_init_param(xmedia_u32 pipe, const xmedia_sensor_init_param *init_param);
xmedia_s32 drv_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg);
xmedia_s32 drv_isp_exit(xmedia_u32 pipe);
xmedia_s32 drv_isp_start(xmedia_u32 pipe);
xmedia_s32 drv_isp_stop(xmedia_u32 pipe);
xmedia_s32 drv_isp_notifier(xmedia_u32 pipe, isp_irq_type irq_type);
xmedia_s32 drv_isp_process(xmedia_u32 pipe);
xmedia_s32 drv_isp_config(xmedia_u32 pipe);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef __DRV_VI_H_
#define __DRV_VI_H_
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "compile.h"
xmedia_s32 drv_vi_init(xmedia_void);
xmedia_s32 drv_vi_exit(xmedia_void);
xmedia_void drv_mipi_init(xmedia_void);
xmedia_s32 drv_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 drv_vi_enable_dev(xmedia_s32 dev);
xmedia_s32 drv_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 drv_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 pipe);
xmedia_s32 drv_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 pipe);
xmedia_s32 drv_vi_start_pipe(xmedia_s32 pipe, xmedia_vi_pipe_config *pipe_config);
xmedia_s32 drv_vi_stop_pipe(xmedia_s32 pipe);
#endif
+28
View File
@@ -0,0 +1,28 @@
#ifndef _I2C_DEV_H_
#define _I2C_DEV_H_
#include "xmedia_type.h"
static __inline__ xmedia_s32 i2c_open(xmedia_u8 i2c_dev)
{
return i2c_dev;
}
static __inline__ xmedia_s32 i2c_close(xmedia_s32 fd)
{
return XMEDIA_SUCCESS;
}
static __inline__ xmedia_s32 i2c_set_slave_addr(xmedia_s32 fd, xmedia_u16 slave_addr)
{
return XMEDIA_SUCCESS;
}
xmedia_s32 i2c_read(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u32 read_addr,
xmedia_u8 addr_width, xmedia_u8 *buff, xmedia_u32 length);
xmedia_s32 i2c_write(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u8 *buff, xmedia_u32 length);
#endif
+53
View File
@@ -0,0 +1,53 @@
#ifndef __MEDIA_SAMPLE_H__
#define __MEDIA_SAMPLE_H__
#include <stdio.h>
#include "xmedia_type.h"
#include "drv_vi.h"
#include "drv_isp.h"
#include "xmedia_ae.h"
#include "xmedia_awb.h"
#include "i2c_dev.h"
#include "i2c.h"
#include "compile.h"
#define MEDIA_ERROR 1
#define MEDIA_PRINTF 1
#define MEDIA_ERR(fmt...) \
do {\
if(MEDIA_ERROR == 1)\
{\
puts(fmt);\
}\
}while(0)
#define MEDIA_PRT(fmt...) \
do {\
if(MEDIA_PRINTF == 1)\
{\
puts(fmt);\
}\
}while(0)
#define MEDIA_STAGE1_ERR(fmt...) \
do {\
if(MEDIA_ERROR == 1)\
{\
puts(STAGE1_STR(fmt));\
}\
}while(0)
//#define SENSOR_SC485SL_2LANE_SUPPORT 1
//#define SENSOR_SC485SL_4LANE_SUPPORT
#define SENSOR_SC485SL_4LANE_60FPS_SUPPORT
//#define SENSOR_SC235HAI_2LANE_60FPS_SUPPORT
#ifdef CONFIG_MEDIA_SAMPLE_QUICKSTART
xmedia_s32 quickstart_media_preinit(void);
xmedia_s32 quickstart_media_start(void);
#endif
#endif /*__MEDIA_SAMPLE_H__*/
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/sns_comm.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_ae.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_af.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_awb.h
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _XMEDIA_DEBUG_H_
#define _XMEDIA_DEBUG_H_
#define MODULE_DBG_EMERG 0
#define MODULE_DBG_ALERT 1
#define MODULE_DBG_CRIT 2
#define MODULE_DBG_ERR 3
#define MODULE_DBG_WARN 4
#define MODULE_DBG_NOTICE 5
#define MODULE_DBG_INFO 6
#define MODULE_DBG_DEBUG 7
#define XMEDIA_ASSERT(expr)
#define MODULE_TRACE(level, mod_id, fmt...)
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_errcode.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_intf_common.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_isp.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_type.h
+37
View File
@@ -0,0 +1,37 @@
#ifndef __XMEDIA_VI_H__
#define __XMEDIA_VI_H__
#include "xmedia_video_common.h"
#include "xmedia_intf_common.h"
#include "xmedia_type.h"
#define VI_MIPI_DATA_LANE_MAX_NUM 4
typedef enum {
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE = 0,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_MAX
} xmedia_vi_mipi_lane_divide_mode;
typedef struct {
xmedia_bool enable;
xmedia_u32 lane_cfg[VI_MIPI_DATA_LANE_MAX_NUM];
} xmedia_vi_mipi_lane_config;
typedef struct {
xmedia_vi_mipi_lane_divide_mode mipi_lane_num;
xmedia_intf_mipi_csi_data_type data_type;
xmedia_u32 mipi_rate; // 单位:Mbps
xmedia_vi_mipi_lane_config lane_config;
} xmedia_vi_dev_config;
typedef struct {
xmedia_video_data_width bit_width;
xmedia_u32 width;
xmedia_u32 height;
xmedia_u32 vi_work_mode; // 0:在线 1:离线
xmedia_video_wdr_mode wdr_mode;
} xmedia_vi_pipe_config;
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_video_common.h
+1
View File
@@ -0,0 +1 @@
SRCS-$(CONFIG_MEDIA_SAMPLE_QUICKSTART) += media_quickstart.c
+412
View File
@@ -0,0 +1,412 @@
#include <malloc.h>
#include <timer.h>
#include <pwm.h>
#include <common.h>
#include "media_sample.h"
#define MCU_CPU_SYNC_REG 0x1202014c
#define MCU_END_VALUE 0xbeef0002
#define MCU_EXIT_VALUE 0xbeef0003
//#define INFRARED_SUPPORT 1
#ifdef INFRARED_SUPPORT
#define PWM_R_LED_NUM 8
#define PWM_R_LED_REG 0x11980014
#define PWM_R_LED_VALUE 0x401
#define PWM_ENABLE_REG 0x11980018
#endif
#ifdef SENSOR_SC485SL_2LANE_SUPPORT
#define MCU_SENSOR_WIDTH 2560
#define MCU_SENSOR_HEIGHT 1440
#elif defined (SENSOR_SC485SL_4LANE_SUPPORT)
#define MCU_SENSOR_WIDTH 2688
#define MCU_SENSOR_HEIGHT 1520
#elif defined (SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
#define MCU_SENSOR_WIDTH 2560
#define MCU_SENSOR_HEIGHT 1440
#elif defined (SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
#define MCU_SENSOR_WIDTH 1920
#define MCU_SENSOR_HEIGHT 1080
#else
#define MCU_SENSOR_WIDTH 2688
#define MCU_SENSOR_HEIGHT 1520
#endif
STAGE1_FUNC xmedia_void media_comm_write_reg(xmedia_u32 addr, xmedia_u32 value)
{
*((xmedia_u32 *)addr) = value;
}
STAGE1_FUNC xmedia_u32 media_comm_read_reg(xmedia_u32 addr)
{
return *((xmedia_u32 *)addr);
}
xmedia_bool media_comm_get_mcu_end_signal()
{
if (MCU_END_VALUE == media_comm_read_reg(MCU_CPU_SYNC_REG))
{
return XMEDIA_TRUE;
}
return XMEDIA_FALSE;
}
xmedia_void media_comm_set_mcu_exit_signal()
{
media_comm_write_reg(MCU_CPU_SYNC_REG, MCU_EXIT_VALUE);
}
#ifdef INFRARED_SUPPORT
xmedia_s32 media_comm_infrared_init()
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
//set pinmux
media_comm_write_reg(PWM_R_LED_REG, PWM_R_LED_VALUE);
//duty_cycle_us > 0, is smaller the light brighter
s32Ret = pwm_config(PWM_R_LED_NUM, 1, 100);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("pwm config fail \n");
return s32Ret;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 media_comm_set_infrared(LIGHT_STATUS state)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
if (state == LIGHT_STATUS_NIGHT) {
media_comm_write_reg(PWM_ENABLE_REG, 1 << 8);
return pwm_enable(PWM_R_LED_NUM);
} else if (state == LIGHT_STATUS_DAY) {
return pwm_disable(PWM_R_LED_NUM);
}
return s32Ret;
}
xmedia_s32 media_comm_set_ir_cut_state(xmedia_s32 vi_dev, LIGHT_STATUS state)
{
if (vi_dev == 0 || vi_dev == 1) {
media_comm_write_reg(0x112C00BC,0x1400);
media_comm_write_reg(0x112C00C0,0x1400);
if (state == LIGHT_STATUS_DAY) {
media_comm_write_reg(0x120B2400,0x03);
media_comm_write_reg(0x120B200C,0x02);
} else if (state == LIGHT_STATUS_NIGHT){
media_comm_write_reg(0x120B2400,0x03);
media_comm_write_reg(0x120B200C,0x01);
} else {
return XMEDIA_FAILURE;
}
} else if (vi_dev == 2 || vi_dev == 3) {
media_comm_write_reg(0x112C00C8,0x1400);
media_comm_write_reg(0x112C00CC,0x1400);
if (state == LIGHT_STATUS_DAY) {
media_comm_write_reg(0x120B5400,0x03);
media_comm_write_reg(0x120B500C,0x02);
} else if (state == LIGHT_STATUS_NIGHT){
media_comm_write_reg(0x120B5400,0x03);
media_comm_write_reg(0x120B500C,0x01);
} else {
return XMEDIA_FAILURE;
}
}
if (vi_dev == 0 || vi_dev == 1) {
media_comm_write_reg(0x120B2400,0x00);
media_comm_write_reg(0x120B200C,0x00);
} else if (vi_dev == 2 || vi_dev == 3) {
media_comm_write_reg(0x120B5400,0x00);
media_comm_write_reg(0x120B500C,0x00);
}
return XMEDIA_SUCCESS;
}
#endif
STAGE1_FUNC static xmedia_void quickstart_sensor_register(xmedia_s32 isp_pipe)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_REGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_REGISTER_DRIVER(isp_pipe, sc235hai);
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_void quickstart_sensor_unregister(xmedia_s32 isp_pipe)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc235hai);
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_void quickstart_vi_get_devcfg(xmedia_vi_dev_config *vi_dev_cfg)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 1080;
#elif defined(SENSOR_SC485SL_4LANE_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 1126;
#elif defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 864;
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_10BIT;
vi_dev_cfg->mipi_rate = 756;
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_sensor_mipi_lanes quickstart_from_vi_get_mipi_lanes(xmedia_vi_dev_config *vi_dev_cfg)
{
xmedia_sensor_mipi_lanes mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_1L;
} else if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
} else if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_4L;
}
return mipi_lanes;
}
STAGE1_FUNC xmedia_s32 quickstart_media_preinit(void)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 isp_pipe = 0;
xmedia_s32 vi_dev = 0;
xmedia_vi_dev_config vi_dev_cfg = {0};
xmedia_sensor_config sensor_cfg = {0};
xmedia_sensor_attr sensor_attr = {0};
xmedia_sensor_mipi_lanes mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
sensor_cfg.comm_bus.type = XMEDIA_SENSOR_BUS_TYPE_I2C;
sensor_cfg.init_mode = XMEDIA_SENSOR_INIT_MODE_NORMAL;
sensor_cfg.comm_bus.i2c_dev = 0;
sensor_cfg.ctrl_sig.clk_ch = 0;
sensor_cfg.ctrl_sig.rst_ch = 0;
s32Ret = i2c_init(sensor_cfg.comm_bus.i2c_dev);
if (s32Ret != 0) {
MEDIA_STAGE1_ERR("i2c init error\n");
return s32Ret;
}
drv_mipi_init();
quickstart_vi_get_devcfg(&vi_dev_cfg);
s32Ret = drv_mipi_enable(vi_dev, &vi_dev_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("mipi enable fail \n");
return s32Ret;
}
quickstart_sensor_register(isp_pipe);
s32Ret = drv_sensor_init(isp_pipe, &sensor_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor init fail\n");
return s32Ret;
}
mipi_lanes = quickstart_from_vi_get_mipi_lanes(&vi_dev_cfg);
drv_sensor_set_mipi_lanes(isp_pipe, mipi_lanes);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor set mipi lanes fail\n");
return s32Ret;
}
sensor_attr.width = MCU_SENSOR_WIDTH;
sensor_attr.height = MCU_SENSOR_HEIGHT;
sensor_attr.wdr_mode = 0;
s32Ret = drv_sensor_set_attr(isp_pipe, &sensor_attr);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor set attr fail\n");
return s32Ret;
}
s32Ret = drv_sensor_start(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("sensor start fail\n");
return s32Ret;
}
#ifdef CONFIG_STOPWATCH_SUPPORT
stopwatch_trigger();
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 quickstart_media_start(void)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 isp_pipe = 0;
xmedia_s32 vi_dev = 0;
xmedia_s32 vi_pipe = 0;
xmedia_vi_dev_config vi_dev_cfg = {0};
xmedia_vi_pipe_config vi_pipe_cfg = {0};
xmedia_isp_config isp_cfg = {0};
quickstart_vi_get_devcfg(&vi_dev_cfg);
s32Ret = drv_vi_init();
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi init fail \n");
return s32Ret;
}
s32Ret = drv_vi_enable_dev(vi_dev);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi enable dev fail\n");
return s32Ret;
}
s32Ret = drv_vi_set_dev_bind_pipe(vi_dev, vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi dev bind pipe fail\n");
return s32Ret;
}
quickstart_vi_get_devcfg(&vi_dev_cfg);
vi_pipe_cfg.bit_width = vi_dev_cfg.data_type;
vi_pipe_cfg.width = MCU_SENSOR_WIDTH;
vi_pipe_cfg.height = MCU_SENSOR_HEIGHT;
vi_pipe_cfg.vi_work_mode = 0;
vi_pipe_cfg.wdr_mode = XMEDIA_VIDEO_WDR_MODE_NONE;
s32Ret = xmedia_awb_register(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("awb init fail\n");
puthex(s32Ret);
return s32Ret;
}
s32Ret = xmedia_ae_register(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("ae init fail\n");
puthex(s32Ret);
return s32Ret;
}
isp_cfg.size.width = MCU_SENSOR_WIDTH;
isp_cfg.size.height = MCU_SENSOR_HEIGHT;
#if defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT) ||defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
isp_cfg.fps = 60;
#else
isp_cfg.fps = 30;
#endif
isp_cfg.wdr_mode = XMEDIA_VIDEO_WDR_MODE_NONE;
isp_cfg.bayer_fmt = XMEDIA_VIDEO_BAYER_FMT_BGGR;
isp_cfg.pixel_fmt = XMEDIA_VIDEO_PIXEL_FMT_RAW;
isp_cfg.mode_config.work_mode = XMEDIA_ISP_WORK_MODE_MASTER;
isp_cfg.mode_config.master_mode.blend_stat_enable = XMEDIA_FALSE;
isp_cfg.mode_config.master_mode.slave_num = 0;
s32Ret = drv_isp_init(isp_pipe, &isp_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp init fail\n");
return s32Ret;
}
s32Ret = drv_vi_start_pipe(vi_pipe, &vi_pipe_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi start pipe fail\n");
return s32Ret;
}
s32Ret = drv_isp_start(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp start fail\n");
return s32Ret;
}
while(1)
{
s32Ret = drv_isp_process(isp_pipe);
if (s32Ret == XMEDIA_SUCCESS ) {
if (XMEDIA_TRUE == media_comm_get_mcu_end_signal()){
break;
}
}
}
#ifdef CONFIG_STOPWATCH_SUPPORT
stopwatch_trigger();
#endif
s32Ret = drv_isp_stop(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp stop fail\n");
return s32Ret;
}
s32Ret = drv_vi_stop_pipe(vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp stop fail\n");
return s32Ret;
}
s32Ret = drv_isp_exit(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp exit fail\n");
return s32Ret;
}
s32Ret = xmedia_ae_unregister(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("ae exit fail\n");
return s32Ret;
}
s32Ret = xmedia_awb_unregister(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("awb exit fail\n");
return s32Ret;
}
quickstart_sensor_unregister(isp_pipe);
s32Ret = drv_vi_set_dev_unbind_pipe(vi_dev, vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi dev unbind pipe fail\n");
return s32Ret;
}
s32Ret = drv_vi_disable_dev(vi_dev, &vi_dev_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi disable dev fail\n");
return s32Ret;
}
s32Ret = drv_vi_exit();
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi exit fail \n");
return s32Ret;
}
media_comm_set_mcu_exit_signal();
return XMEDIA_SUCCESS;
}
+1
View File
@@ -0,0 +1 @@
../../source/gmp/usr/isp/sensor/