diff --git a/middleware/v2/modules/Makefile b/middleware/v2/modules/Makefile new file mode 100644 index 000000000..39db6ec10 --- /dev/null +++ b/middleware/v2/modules/Makefile @@ -0,0 +1,25 @@ +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../Makefile.param + include $(PARAM_FILE) +endif + +.PHONY: all clean $(MODULES) + +MODULES = sys bin vpu audio mipi_tx venc vdec misc ive osdc isp + +all: + @echo "########################################################################################################" + @echo "#" + @echo "# Compiling 'module libs' Configs as below ..." + @echo "# "CROSS_COMPILE=$(CROSS_COMPILE) + @echo "# "KERNEL_DIR=$(KERNEL_DIR) + @echo "#" + @echo "########################################################################################################" + @for x in $(MODULES); \ + do cd $$x; if [ $$? ]; then $(MAKE) all || exit 1; cd -; fi; done + +clean: + @for x in `find -L ./ -maxdepth 2 -mindepth 2 -name "Makefile" `; \ + do cd `dirname $$x`; if [ $$? ]; then $(MAKE) clean; cd -; fi; done + @make -C isp clean + @echo "#" diff --git a/middleware/v2/modules/audio/.gitkeep b/middleware/v2/modules/audio/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/middleware/v2/modules/audio/Makefile b/middleware/v2/modules/audio/Makefile new file mode 100644 index 000000000..e6d6350d5 --- /dev/null +++ b/middleware/v2/modules/audio/Makefile @@ -0,0 +1,17 @@ +.PHONY: clean all +.SILENT: clean all + +include audio.mk + +all: + cp lib/$(SDK_VER)/lib* $(MW_LIB) + +clean: + rm $(MW_LIB)/libaac* + rm $(MW_LIB)/libcvi_audio* + rm $(MW_LIB)/libcvi_RES1* + rm $(MW_LIB)/libcvi_ssp* + rm $(MW_LIB)/libcvi_VoiceEngine* + rm $(MW_LIB)/libcvi_vqe* + rm $(MW_LIB)/libdnvqe* + rm $(MW_LIB)/libtinyalsa* diff --git a/middleware/v2/modules/audio/audio.mk b/middleware/v2/modules/audio/audio.mk new file mode 100644 index 000000000..fc487b373 --- /dev/null +++ b/middleware/v2/modules/audio/audio.mk @@ -0,0 +1,4 @@ +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../../$(shell echo $(MW_VER))/Makefile.param + include $(PARAM_FILE) +endif diff --git a/middleware/v2/modules/gyro/Makefile b/middleware/v2/modules/gyro/Makefile new file mode 100644 index 000000000..911047a5d --- /dev/null +++ b/middleware/v2/modules/gyro/Makefile @@ -0,0 +1,38 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I./include -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libcvi_gyro.a +TARGET_SO = $(MW_LIB)/libcvi_gyro.so + +EXTRA_CFLAGS = $(INCS) + +.PHONY : clean all install +all : $(TARGET_A) $(TARGET_SO) install + +install: + @cp include/cvi_gyro.h $(MW_INC) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/gyro/src/cvi_gyro.c b/middleware/v2/modules/gyro/src/cvi_gyro.c new file mode 100644 index 000000000..aa7eeb6fa --- /dev/null +++ b/middleware/v2/modules/gyro/src/cvi_gyro.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_gyro.h" +#include "linux/cvi_gyro_ioctl.h" + +#define DEV_NODE "/dev/cvi-gyro" + +int g_devfd = CVI_FAILURE; + +CVI_S32 _dev_check(CVI_VOID) +{ + if (g_devfd <= 0) { + printf("Device gyro is not open, please check it\n"); + return -1; + } + return CVI_SUCCESS; +} + +CVI_S32 _cvi_gyro_get_2byte(int reg, CVI_S16 *val) +{ + CVI_S32 ret = CVI_FAILURE; + + if (_dev_check() == 0) { + struct cvi_gy_regval regval; + + regval.addr = reg; + ret = ioctl(g_devfd, CVI_GYRO_IOC_READ_2BYTE, ®val); + *val = regval.val; + } + return ret; +} + +CVI_S32 _cvi_gyro_get_xyz(int reg, CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val) +{ + CVI_S32 ret = CVI_FAILURE; + + if (_dev_check() == 0) { + struct cvi_gy_regval_6byte regval; + + regval.addr = reg; + ret = ioctl(g_devfd, CVI_GYRO_IOC_READ_6BYTE, ®val); + if (x_val != NULL) + *x_val = regval.x_val; + if (y_val != NULL) + *y_val = regval.y_val; + if (z_val != NULL) + *z_val = regval.z_val; + return ret; + } + return ret; +} + +CVI_S32 CVI_GYRO_Create(CVI_VOID) +{ + if (g_devfd <= 0) { + g_devfd = open(DEV_NODE, O_RDWR); + if (g_devfd < 0) { + printf("Can't open %s\n", DEV_NODE); + return CVI_FAILURE; + } + } + return CVI_SUCCESS; +} + +CVI_VOID CVI_GYRO_Destroy(CVI_VOID) +{ + if (g_devfd > 0) { + close(g_devfd); + } + g_devfd = 0; +} + +CVI_S32 CVI_GYRO_Reset(CVI_VOID) +{ + CVI_S32 ret = CVI_FAILURE; + + ret = CVI_GYRO_WRITE(PWR_MGMT_1, 0x80); + usleep(100 * 1000); + return ret; +} + +CVI_S32 CVI_GYRO_GET_G_XYZ(CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val) +{ + return _cvi_gyro_get_xyz(GYRO_XOUT_H, x_val, y_val, z_val); +} + +CVI_S32 CVI_GYRO_GET_A_XYZ(CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val) +{ + return _cvi_gyro_get_xyz(ACCEL_XOUT_H, x_val, y_val, z_val); +} + +CVI_S32 CVI_GYRO_GET_GX(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(GYRO_XOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_GY(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(GYRO_YOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_GZ(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(GYRO_ZOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_AX(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(ACCEL_XOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_AY(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(ACCEL_YOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_AZ(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(ACCEL_ZOUT_H, val); +} + +CVI_S32 CVI_GYRO_GET_TEMP(CVI_S16 *val) +{ + return _cvi_gyro_get_2byte(TEMP_OUT_H, val); +} + +CVI_S32 CVI_GYRO_ACC_CALIBRATION(CVI_VOID) +{ + if (_dev_check() == 0) { + return ioctl(g_devfd, CVI_GYRO_IOC_ACC_ADJUST); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_GYRO_CALIBRATION(CVI_VOID) +{ + if (_dev_check() == 0) { + return ioctl(g_devfd, CVI_GYRO_IOC_ADJUST); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_GYRO_WHO_AM_I(CVI_U8 *val) +{ + CVI_S32 ret = CVI_FAILURE; + struct cvi_gy_regval reg; + + if (_dev_check() == 0) { + ret = ioctl(g_devfd, CVI_GYRO_IOC_CHECK, ®); + if (val != NULL) + *val = (CVI_U8) (reg.val & 0xFF); + } + return ret; +} + +CVI_S32 CVI_GYRO_READ(CVI_U8 addr, CVI_U8 *val) +{ + CVI_S32 ret = CVI_FAILURE; + struct cvi_gy_regval reg; + + if (_dev_check() == 0) { + reg.addr = addr; + ret = ioctl(g_devfd, CVI_GYRO_IOC_READ, ®); + if (val != NULL) + *val = (CVI_U8) (reg.val & 0xFF); + } + return ret; +} + +CVI_S32 CVI_GYRO_WRITE(CVI_U8 addr, CVI_U8 val) +{ + CVI_S32 ret = CVI_FAILURE; + struct cvi_gy_regval reg; + + if (_dev_check() == 0) { + reg.addr = addr; + reg.val = val; + ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE, ®); + } + return ret; +} + +CVI_S32 CVI_GYRO_WRITE_OR(CVI_U8 addr, CVI_U8 val) +{ + CVI_S32 ret = CVI_FAILURE; + struct cvi_gy_regval reg; + + if (_dev_check() == 0) { + reg.addr = addr; + reg.val = val; + ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE_OR, ®); + } + return ret; +} + +CVI_S32 CVI_GYRO_WRITE_AND(CVI_U8 addr, CVI_U8 val) +{ + CVI_S32 ret = CVI_FAILURE; + struct cvi_gy_regval reg; + + if (_dev_check() == 0) { + reg.addr = addr; + reg.val = val; + ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE_AND, ®); + } + return ret; +} \ No newline at end of file diff --git a/middleware/v2/modules/ive/Makefile b/middleware/v2/modules/ive/Makefile new file mode 100644 index 000000000..bdc2eb016 --- /dev/null +++ b/middleware/v2/modules/ive/Makefile @@ -0,0 +1,38 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I./include -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I../../3rdparty +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libcvi_ive.a +TARGET_SO = $(MW_LIB)/libcvi_ive.so + +EXTRA_CFLAGS = $(INCS) + +.PHONY : clean all install +all : $(TARGET_A) $(TARGET_SO) install + +install: + @cp include/cvi_ive.h $(MW_INC) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/ive/src/cvi_ive.c b/middleware/v2/modules/ive/src/cvi_ive.c new file mode 100644 index 000000000..3e4a3497d --- /dev/null +++ b/middleware/v2/modules/ive/src/cvi_ive.c @@ -0,0 +1,2678 @@ +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb/stb_image_write.h" + +#include "cvi_sys.h" +#include "cvi_ive.h" +#include "linux/cvi_ive_ioctl.h" + +#define IVE_DEV_NODE "/dev/cvi-ive" +#define STRFY(s) #s + +typedef void *IVE_HANDLE; + +enum DIRECTION { + VERTICAL = 0, + HORIZON = 1, + SLASH = 2, + BACK_SLASH = 3, + ZERO = 4, +}; + +struct IVE_HANDLE_CTX { + int devfd; + int used_time; +}; + +struct IVE_HANDLE_CTX handle_ctx; + +const char *cviIveImgEnTypeStr[] = { + STRFY(IVE_IMAGE_TYPE_U8C1), STRFY(IVE_IMAGE_TYPE_S8C1), + STRFY(IVE_IMAGE_TYPE_YUV420SP), STRFY(IVE_IMAGE_TYPE_YUV422SP), + STRFY(IVE_IMAGE_TYPE_YUV420P), STRFY(IVE_IMAGE_TYPE_YUV422P), + STRFY(IVE_IMAGE_TYPE_S8C2_PACKAGE), STRFY(IVE_IMAGE_TYPE_S8C2_PLANAR), + STRFY(IVE_IMAGE_TYPE_S16C1), STRFY(IVE_IMAGE_TYPE_U16C1), + STRFY(IVE_IMAGE_TYPE_U8C3_PACKAGE), STRFY(IVE_IMAGE_TYPE_U8C3_PLANAR), + STRFY(IVE_IMAGE_TYPE_S32C1), STRFY(IVE_IMAGE_TYPE_U32C1), + STRFY(IVE_IMAGE_TYPE_S64C1), STRFY(IVE_IMAGE_TYPE_U64C1), + STRFY(IVE_IMAGE_TYPE_BF16C1), STRFY(IVE_IMAGE_TYPE_FP32C1) +}; + +int open_ive_dev() +{ + if (handle_ctx.devfd != 0) + return handle_ctx.devfd; + + int devfd; + + do { + if (handle_ctx.devfd <= 0) + devfd = open(IVE_DEV_NODE, O_RDWR); + else + devfd = handle_ctx.devfd; + if (devfd < 0) { + printf("Can't open %s\n", IVE_DEV_NODE); + return ERR_IVE_OPEN_FILE; + } + } while (0); + return devfd; +} + +uint32_t WidthAlign(const uint32_t width, const uint32_t align) +{ + uint32_t stride = (uint32_t)(width / align) * align; + if (stride < width) { + stride += align; + } + return stride; +} + +void dump_data_u8(const CVI_U8 *data, CVI_S32 count, const CVI_CHAR *desc) +{ + CVI_S32 i; + + printf("%s\n", desc); + for (i = 0; i < count; ++i) { + printf("%02X ", data[i]); + if ((i + 1) % 8 == 0 || i + 1 == count) { + printf(" "); + if ((i + 1) % 16 == 0) { + printf("\n"); + } else if (i + 1 == count) { + printf("\n"); + } + } + } +} + +static CVI_S32 find_first_diff_u8(const CVI_U8 *A, const CVI_U8 *B, + CVI_S32 count) +{ + CVI_S32 i; + CVI_S32 result = -1; + for (i = 0; i < count; ++i) { + if (A[i] != B[i]) { + result = i; + break; + } + } + return result; +} + +static CVI_S32 find_first_diff_u16(const CVI_U16 *A, const CVI_U16 *B, + CVI_S32 count) +{ + CVI_S32 i; + CVI_S32 result = -1; + for (i = 0; i < count; ++i) { + if (A[i] != B[i]) { + result = i; + break; + } + } + return result; +} + +void dump_data_u16(const CVI_U16 *data, CVI_S32 count, const CVI_CHAR *desc) +{ + CVI_S32 i; + printf("%s\n", desc); + for (i = 0; i < count; ++i) { + printf("%04X ", data[i]); + if ((i + 1) % 8 == 0 || i + 1 == count) { + printf(" "); + if ((i + 1) % 16 == 0) { + printf("\n"); + } else if (i + 1 == count) { + printf("\n"); + } + } + } +} + +static CVI_S32 find_first_diff_u32(const CVI_U32 *A, const CVI_U32 *B, + CVI_S32 count) +{ + CVI_S32 i; + CVI_S32 result = -1; + for (i = 0; i < count; ++i) { + if (A[i] != B[i]) { + result = i; + break; + } + } + return result; +} +void dump_data_u32(const CVI_U32 *data, CVI_S32 count, const CVI_CHAR *desc) +{ + CVI_S32 i; + printf("%s\n", desc); + for (i = 0; i < count; ++i) { + printf("%08X ", data[i]); + if ((i + 1) % 4 == 0 || i + 1 == count) { + printf(" "); + if ((i + 1) % 8 == 0) { + printf("\n"); + } else if (i + 1 == count) { + printf("\n"); + } + } + } +} + +static CVI_S32 find_first_diff_u64(const CVI_U64 *A, const CVI_U64 *B, + CVI_S32 count) +{ + CVI_S32 i; + CVI_S32 result = -1; + for (i = 0; i < count; ++i) { + if (A[i] != B[i]) { + result = i; + break; + } + } + return result; +} + +void dump_data_u64(const CVI_U64 *data, CVI_S32 count, const CVI_CHAR *desc) +{ + CVI_S32 i; + printf("%s\n", desc); + for (i = 0; i < count; ++i) { + printf("%016jX ", data[i]); + if ((i + 1) % 2 == 0 || i + 1 == count) { + printf(" "); + if ((i + 1) % 4 == 0) { + printf("\n"); + } else if (i + 1 == count) { + printf("\n"); + } + } + } +} + +void boundary_check(IVE_POINT_U16_S *point, int width, int height) +{ + if ((CVI_S16)point->u16X < 0) { + point->u16X = 0; + } + if ((CVI_S16)point->u16Y < 0) { + point->u16Y = 0; + } + if (point->u16X >= width) { + point->u16X = width - 1; + } + if (point->u16Y >= height) { + point->u16Y = height - 1; + } +} + +int do_hysteresis_wo_ang(unsigned char *pEdgeMap, + unsigned char *dst, int imw, int imh, int stride) +{ + IVE_POINT_U16_S p1, p2, p; + unsigned char *visited = + (unsigned char *)calloc(imh * stride, sizeof(unsigned char)); + unsigned char *pdst = + (unsigned char *)calloc(imh * stride, sizeof(unsigned char)); + + for (int i = 0; i < imh; i++) { + for (int j = 0; j < imw; j++) { + int index = i * stride + j; + + if (pEdgeMap[index] == 2) { + pdst[index] = 255; + } else { + pdst[index] = 0; + } + } + } + + for (int y = 1; y < imh - 1; y++) { + for (int x = 1; x < imw - 1; x++) { + // if pixel not in upper or had visited, skip + if (pEdgeMap[y * stride + x] != 2 || + visited[y * stride + x] > 0) + continue; + p.u16X = x; + p.u16Y = y; + visited[p.u16Y * stride + p.u16X] = 255; + pdst[p.u16Y * stride + p.u16X] = 255; + for (unsigned char dir = 0; dir < 4; dir++) { + if (dir == VERTICAL) { + p1.u16X = p.u16X + 1; + p1.u16Y = p.u16Y; + p2.u16X = p.u16X - 1; + p2.u16Y = p.u16Y; + } else if (dir == HORIZON) { + p1.u16X = p.u16X; + p1.u16Y = p.u16Y + 1; + p2.u16X = p.u16X; + p2.u16Y = p.u16Y - 1; + } else if (dir == SLASH) { + p1.u16X = p.u16X + 1; + p1.u16Y = p.u16Y - 1; + p2.u16X = p.u16X - 1; + p2.u16Y = p.u16Y + 1; + } else if (dir == BACK_SLASH) { + p1.u16X = p.u16X + 1; + p1.u16Y = p.u16Y + 1; + p2.u16X = p.u16X - 1; + p2.u16Y = p.u16Y - 1; + } else { + p1.u16X = p.u16X; + p1.u16Y = p.u16Y; + p2.u16X = p.u16X; + p2.u16Y = p.u16Y; + } + boundary_check(&p1, imw, imh); + boundary_check(&p2, imw, imh); + if (pEdgeMap[p1.u16Y * stride + p1.u16X] == 0 && + visited[p1.u16Y * stride + p1.u16X] == 0) { + visited[p1.u16Y * stride + p1.u16X] = 255; + pdst[p1.u16Y * stride + p1.u16X] = 255; + } + if (pEdgeMap[p2.u16Y * stride + p2.u16X] == 0 && + visited[p2.u16Y * stride + p2.u16X] == 0) { + visited[p2.u16Y * stride + p2.u16X] = 255; + pdst[p2.u16Y * stride + p2.u16X] = 255; + } + } + } + } + + memcpy(dst, pdst, stride * imh); + free(visited); + free(pdst); + return 0; +} + +IVE_HANDLE CVI_IVE_CreateHandle() +{ + handle_ctx.devfd = open_ive_dev(); + handle_ctx.used_time++; + return &handle_ctx; +} + +CVI_S32 CVI_IVE_DestroyHandle(IVE_HANDLE pIveHandle) +{ + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + p->used_time--; + if (p->used_time <= 0 && p->devfd > 0) { + close(p->devfd); + p->devfd = 0; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_CompareIveData(IVE_DATA_S *pstData1, IVE_DATA_S *pstData2) +{ + int n; + CVI_U32 y; + + if (pstData1->u32Width != pstData2->u32Width) { + printf("Not same u32Width, %d vs %d\n", pstData1->u32Width, + pstData2->u32Width); + return CVI_ERR_IVE_INVALID_DEVID; + } + if (pstData1->u32Height != pstData2->u32Height) { + printf("Not same u32Height, %d vs %d\n", pstData1->u32Height, + pstData2->u32Height); + return CVI_ERR_IVE_INVALID_DEVID; + } + printf("compare A at %p, B at %p\n", + (char *)(uintptr_t)pstData1->u64VirAddr, + (char *)(uintptr_t)pstData2->u64VirAddr); + + + for (y = 0; y < pstData1->u32Height; y++) { + n = memcmp((char *)(uintptr_t)pstData1->u64VirAddr + y * pstData1->u32Stride, + (char *)(uintptr_t)pstData2->u64VirAddr + y * pstData1->u32Stride, + pstData1->u32Width); + if (n != 0) { + printf("Not same content\n"); + return CVI_FAILURE; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_CompareIveMem(IVE_MEM_INFO_S *pstMem1, IVE_MEM_INFO_S *pstMem2) +{ + int n; + + if (pstMem1->u32Size != pstMem2->u32Size || pstMem1->u32Size == 0) { + printf("Not same u32Size, %d vs %d\n", pstMem1->u32Size, + pstMem2->u32Size); + return CVI_ERR_IVE_INVALID_DEVID; + } + + if ((char *)(uintptr_t)pstMem1->u64VirAddr == NULL || + (char *)(uintptr_t)pstMem2->u64VirAddr == NULL) { + printf("invalid address\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + + printf("compare A at %p, B at %p\n", + (char *)(uintptr_t)pstMem1->u64VirAddr, + (char *)(uintptr_t)pstMem2->u64VirAddr); + n = memcmp((char *)(uintptr_t)pstMem1->u64VirAddr, + (char *)(uintptr_t)pstMem2->u64VirAddr, pstMem1->u32Size); + if (n != 0) { + return CVI_FAILURE; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_CompareIveImage(IVE_IMAGE_S *pstImage1, IVE_IMAGE_S *pstImage2) +{ + CVI_U32 u32Stride; + CVI_S32 s32Succ; + IVE_IMAGE_TYPE_E enType; + CVI_U32 u32Width; + CVI_U32 u32Height; + CVI_U8 *pData1; + CVI_U8 *pData2; + CVI_U16 *pData1_U16; + CVI_U16 *pData2_U16; + CVI_U32 *pData1_U32; + CVI_U32 *pData2_U32; + CVI_U64 *pData1_U64; + CVI_U64 *pData2_U64; + CVI_U16 y; + int n; + + if (pstImage1->enType != pstImage2->enType) { + printf("Not same IMAGE_TYPE, %d vs %d\n", pstImage1->enType, + pstImage2->enType); + return CVI_ERR_IVE_INVALID_DEVID; + } + if (pstImage1->u32Width != pstImage2->u32Width) { + printf("Not same u32Width, %d vs %d\n", pstImage1->u32Width, + pstImage2->u32Width); + return CVI_ERR_IVE_INVALID_DEVID; + } + if (pstImage1->u32Height != pstImage2->u32Height) { + printf("Not same u32Height, %d vs %d\n", pstImage1->u32Height, + pstImage2->u32Height); + return CVI_ERR_IVE_INVALID_DEVID; + } + + enType = pstImage1->enType; + u32Width = pstImage1->u32Width; + u32Height = pstImage1->u32Height; + + //u32Stride = CVI_CalcStride(u32Width, CVI_IVE2_STRIDE_ALIGN); + u32Stride = pstImage1->u32Stride[0];//WidthAlign(u32Width, DEFAULT_ALIGN); + s32Succ = CVI_SUCCESS; + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compare A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_YUV420SP: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compareY A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare Y failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[1]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[1]; + printf("compareUV A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height / 2; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare UV failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_YUV422SP: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compareY A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare Y failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[1]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[1]; + printf("compareUV A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare UV failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_YUV420P: + case IVE_IMAGE_TYPE_YUV422P: + case IVE_IMAGE_TYPE_S8C2_PACKAGE: + case IVE_IMAGE_TYPE_S8C2_PLANAR: { + printf("Unsupported IMAGE_TYPE %d\n", enType); + s32Succ = CVI_FAILURE; + } break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compare U8C3_PACKAGE A at %p, B at %p\n", pData1, + pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width * 3); + //dump_data_u8(pData1, u32Width, "dst"); + //dump_data_u8(pData2, u32Width, "ref"); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32Width * 3); + CVI_ASSERT(idx >= 0); + printf("Compare U8C3_PACKAGE failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width * 3, "A"); + dump_data_u8(pData2, u32Width * 3, "B"); + CVI_IVE_WriteImg(0, "sample_CSC_YUV4442RGB_1.yuv", pstImage1); + CVI_IVE_WriteImg(0, "sample_CSC_YUV4442RGB_2.yuv", pstImage2); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + for (int i = 0; i < 3; i++) { + char YUVStr[4] = { 'Y', 'U', 'V' }; + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[i]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[i]; + printf("compare U8C3_PLANAR[%c] A at %p, B at %p\n", + YUVStr[i], pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width); + if (n != 0) { + int idx = find_first_diff_u8( + pData1, pData2, u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare %c failed, at y = %d, x = %d, n = %d\n", + YUVStr[i], y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32Width, "A"); + dump_data_u8(pData2, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } + } break; + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compare A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width * 2); + if (n != 0) { + pData1_U16 = (CVI_U16 *)pData1; + pData2_U16 = (CVI_U16 *)pData2; + int idx = find_first_diff_u16( + pData1_U16, pData2_U16, u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%04X, B = 0x%04X\n", + pData1_U16[idx], pData2_U16[idx]); + dump_data_u16(pData1_U16, u32Width, "A"); + dump_data_u16(pData2_U16, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_S32C1: + case IVE_IMAGE_TYPE_U32C1: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compareU32C1 A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + n = memcmp(pData1, pData2, u32Width * 4); + if (n != 0) { + pData1_U32 = (CVI_U32 *)pData1; + pData2_U32 = (CVI_U32 *)pData2; + int idx = find_first_diff_u32( + pData1_U32, pData2_U32, u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%08X, B = 0x%08X\n", + pData1_U32[idx], pData2_U32[idx]); + dump_data_u32(pData1_U32, u32Width, "A"); + dump_data_u32(pData2_U32, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + case IVE_IMAGE_TYPE_S64C1: + case IVE_IMAGE_TYPE_U64C1: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compareU64C1 A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32Height; + y++, pData1 += u32Stride, pData2 += u32Stride) { + int m = memcmp(pData1, pData2, u32Width * 4); + + n = memcmp(pData1 + u32Width * 4, pData2 + u32Width * 4, + u32Width * 4); + if (n != 0 || m != 0) { + pData1_U64 = (CVI_U64 *)pData1; + pData2_U64 = (CVI_U64 *)pData2; + int idx = find_first_diff_u64( + pData1_U64, pData2_U64, u32Width); + CVI_ASSERT(idx >= 0); + printf("Compare failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%016jX, B = 0x%016jX\n", + pData1_U64[idx], pData2_U64[idx]); + dump_data_u64(pData1_U64, u32Width, "A"); + dump_data_u64(pData2_U64, u32Width, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + default: { + printf("Unknown IMAGE_TYPE %d\n", enType); + s32Succ = CVI_ERR_IVE_ILLEGAL_PARAM; + } break; + } + return s32Succ; +} + +CVI_S32 CVI_IVE_CompareSADImage(IVE_IMAGE_S *pstImage1, IVE_IMAGE_S *pstImage2, + IVE_SAD_MODE_E mode, CVI_BOOL isDMAhalf) +{ + CVI_U32 u32Stride; + CVI_S32 s32Succ; + IVE_IMAGE_TYPE_E enType; + CVI_U32 u32Width, u32SADWidth; + CVI_U32 u32Height, u32SADHeight; + CVI_U32 u32SADStride; + CVI_U32 u32ByteSize; + CVI_U8 *pData1; + CVI_U8 *pData2; + CVI_U16 y; + int n; + + if (pstImage1->enType != pstImage2->enType) { + printf("Not same IMAGE_TYPE, %d vs %d\n", pstImage1->enType, + pstImage2->enType); + return CVI_FAILURE; + } + if (pstImage1->u32Width != pstImage2->u32Width) { + printf("Not same u32Width, %d vs %d\n", pstImage1->u32Width, + pstImage2->u32Width); + return CVI_FAILURE; + } + if (pstImage1->u32Height != pstImage2->u32Height) { + printf("Not same u32Height, %d vs %d\n", pstImage1->u32Height, + pstImage2->u32Height); + return CVI_FAILURE; + } + + if (pstImage1->u32Stride[0] != pstImage2->u32Stride[0]) { + printf("Not same u32Stride, %d vs %d\n", pstImage1->u32Stride[0], + pstImage2->u32Stride[0]); + return CVI_FAILURE; + } + + enType = pstImage1->enType; + u32Width = pstImage1->u32Width; + u32Height = pstImage1->u32Height; + + u32Stride = pstImage1->u32Stride[0]; + s32Succ = CVI_SUCCESS; + switch (enType) { + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: + u32ByteSize = 2; + break; + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: + u32ByteSize = 1; + break; + default: + printf("not support output type %d, return\n", enType); + return CVI_FAILURE; + } + switch (mode) { + case IVE_SAD_MODE_MB_4X4: + u32SADWidth = u32Width * u32ByteSize / 4; + u32SADHeight = u32Height / 4; + break; + case IVE_SAD_MODE_MB_8X8: + u32SADWidth = u32Width * u32ByteSize / 8; + u32SADHeight = u32Height / 8; + break; + case IVE_SAD_MODE_MB_16X16: + u32SADWidth = u32Width * u32ByteSize / 16; + u32SADHeight = u32Height / 16; + break; + default: + printf("not support mode type %d, return\n", mode); + return CVI_FAILURE; + } + u32SADStride = (isDMAhalf) ? pstImage1->u32Stride[0] / 2 : pstImage1->u32Stride[0]; + printf("SAD Width %u Height %u Stride %u %u\n", u32SADWidth, + u32SADHeight, u32SADStride, u32Stride); + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: { + pData1 = (CVI_U8 *)(uintptr_t)pstImage1->u64VirAddr[0]; + pData2 = (CVI_U8 *)(uintptr_t)pstImage2->u64VirAddr[0]; + printf("compareSAD A at %p, B at %p\n", pData1, pData2); + for (y = 0; y < u32SADHeight; + y++, pData1 += u32SADStride, pData2 += u32Stride) { //dst=96 ref=384 + n = memcmp(pData1, pData2, u32SADWidth); + if (n != 0) { + int idx = find_first_diff_u8(pData1, pData2, + u32SADWidth); + CVI_ASSERT(idx >= 0); + printf("Compare failed, at y = %d, x = %d, n = %d\n", + y, idx, n); + printf(" A = 0x%02X, B = 0x%02X\n", + pData1[idx], pData2[idx]); + dump_data_u8(pData1, u32SADWidth, "A"); + dump_data_u8(pData2, u32SADWidth, "B"); + s32Succ = CVI_FAILURE; + break; + } + } + } break; + default: { + printf("Unknown IMAGE_TYPE %d\n", enType); + s32Succ = CVI_ERR_IVE_ILLEGAL_PARAM; + } break; + } + + return s32Succ; +} + +CVI_S32 CVI_IVE_VideoFrameInfo2Image(VIDEO_FRAME_INFO_S *pstVFISrc, IVE_IMAGE_S *pstIIDst) +{ + CVI_U32 u32Channel = 1; + VIDEO_FRAME_S *pstVFSrc = &pstVFISrc->stVFrame; + IVE_IMAGE_TYPE_E img_type = IVE_IMAGE_TYPE_U8C1; + + switch (pstVFSrc->enPixelFormat) { + case PIXEL_FORMAT_YUV_400: { + img_type = IVE_IMAGE_TYPE_U8C1; + } break; + case PIXEL_FORMAT_NV21: + case PIXEL_FORMAT_NV12: { + img_type = IVE_IMAGE_TYPE_YUV420SP; + u32Channel = 2; + } break; + case PIXEL_FORMAT_YUV_PLANAR_420: { + img_type = IVE_IMAGE_TYPE_YUV420P; + u32Channel = 3; + } break; + case PIXEL_FORMAT_YUV_PLANAR_422: { + img_type = IVE_IMAGE_TYPE_YUV422P; + u32Channel = 3; + } break; + case PIXEL_FORMAT_RGB_888: + case PIXEL_FORMAT_BGR_888: { + img_type = IVE_IMAGE_TYPE_U8C3_PACKAGE; + } break; + case PIXEL_FORMAT_RGB_888_PLANAR: { + img_type = IVE_IMAGE_TYPE_U8C3_PLANAR; + u32Channel = 3; + } break; + case PIXEL_FORMAT_INT16_C1: { + img_type = IVE_IMAGE_TYPE_S16C1; + } break; + case PIXEL_FORMAT_UINT16_C1: { + img_type = IVE_IMAGE_TYPE_U16C1; + } break; + default: { + printf("Unsupported conversion type: %u.\n", pstVFSrc->enPixelFormat); + return CVI_FAILURE; + } + } + + for (CVI_U32 i = 0; i < u32Channel; i++) { + pstIIDst->u64VirAddr[i] = (CVI_U64)(uintptr_t)pstVFSrc->pu8VirAddr[i]; + pstIIDst->u64PhyAddr[i] = pstVFSrc->u64PhyAddr[i]; + pstIIDst->u32Stride[i] = pstVFSrc->u32Stride[i]; + } + pstIIDst->enType = img_type; + pstIIDst->u32Width = pstVFSrc->u32Width; + pstIIDst->u32Height = pstVFSrc->u32Height; + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_Image2VideoFrameInfo(IVE_IMAGE_S *pstIISrc, VIDEO_FRAME_INFO_S *pstVFIDst) + //, CVI_BOOL invertPackage) +{ + CVI_U32 u32Channel = 1; + VIDEO_FRAME_S *pstVFSrc = &pstVFIDst->stVFrame; + PIXEL_FORMAT_E img_type = PIXEL_FORMAT_YUV_400; + + pstVFIDst->u32PoolId = -1; + switch (pstIISrc->enType) { + case IVE_IMAGE_TYPE_U8C1: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + img_type = PIXEL_FORMAT_YUV_400; + } break; + case IVE_IMAGE_TYPE_YUV420SP: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + pstVFSrc->u32Stride[1] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + img_type = PIXEL_FORMAT_NV21; + u32Channel = 2; + } break; + case IVE_IMAGE_TYPE_YUV420P: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + pstVFSrc->u32Stride[1] = WidthAlign(pstIISrc->u32Width >> 1, DEFAULT_ALIGN); + pstVFSrc->u32Stride[2] = pstVFSrc->u32Stride[1]; + img_type = PIXEL_FORMAT_YUV_PLANAR_420; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_YUV422P: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + pstVFSrc->u32Stride[1] = WidthAlign(pstIISrc->u32Width >> 1, DEFAULT_ALIGN); + pstVFSrc->u32Stride[2] = pstVFSrc->u32Stride[1]; + img_type = PIXEL_FORMAT_YUV_PLANAR_422; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width * 3, DEFAULT_ALIGN); + img_type = PIXEL_FORMAT_RGB_888; + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + pstVFSrc->u32Stride[0] = WidthAlign(pstIISrc->u32Width, DEFAULT_ALIGN); + pstVFSrc->u32Stride[1] = pstVFSrc->u32Stride[0]; + pstVFSrc->u32Stride[2] = pstVFSrc->u32Stride[0]; + img_type = PIXEL_FORMAT_RGB_888_PLANAR; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_S16C1: { + pstVFSrc->u32Stride[0] = + WidthAlign(pstIISrc->u32Width * sizeof(int16_t), DEFAULT_ALIGN); + img_type = PIXEL_FORMAT_INT16_C1; + } break; + case IVE_IMAGE_TYPE_U16C1: { + pstVFSrc->u32Stride[0] = + WidthAlign(pstIISrc->u32Width * sizeof(uint16_t), DEFAULT_ALIGN); + img_type = PIXEL_FORMAT_UINT16_C1; + } break; + default: { + printf("Unsupported conversion type: %u.\n", pstIISrc->enType); + return CVI_FAILURE; + } + } + + for (CVI_U32 i = 0; i < u32Channel; i++) { + pstVFSrc->pu8VirAddr[i] = (CVI_U8 *)(uintptr_t)pstIISrc->u64VirAddr[i]; + pstVFSrc->u64PhyAddr[i] = pstIISrc->u64PhyAddr[i]; + pstVFSrc->u32Length[i] = pstIISrc->u32Height * pstIISrc->u32Stride[i]; + } + for (CVI_U32 i = u32Channel; i < 3; i++) { + pstVFSrc->pu8VirAddr[i] = 0; + pstVFSrc->u64PhyAddr[i] = 0; + pstVFSrc->u32Stride[i] = 0; + pstVFSrc->u32Length[i] = 0; + } + pstVFSrc->enPixelFormat = img_type; + pstVFSrc->u32Width = pstIISrc->u32Width; + pstVFSrc->u32Height = pstIISrc->u32Height; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_ReadData(IVE_HANDLE pIveHandle, IVE_DATA_S *pstData, + const char *filename, CVI_U16 u32Width, + CVI_U16 u32Height) +{ + CVI_U16 u32Stride = WidthAlign(u32Width, DEFAULT_ALIGN); + int uSize = u32Stride * u32Height; + CVI_S32 s32Succ = CVI_SUCCESS; + FILE *fp; + + fp = fopen(filename, "r"); + if (fp == NULL) { + printf("Can't open %s\n", filename); + return ERR_IVE_OPEN_FILE; + } + + s32Succ = CVI_IVE_CreateDataInfo(pIveHandle, pstData, u32Width, + u32Height); + if (s32Succ) { + printf("Ion alloc failed\n"); + return s32Succ; + } + + int readCnt = + fread((char *)(uintptr_t)pstData->u64VirAddr, 1, uSize, fp); + + if (readCnt == 0) { + printf("Image %s read failed.\n", filename); + return ERR_IVE_READ_FILE; + } + fclose(fp); + return s32Succ; +} + +CVI_S32 CVI_IVE_ReadDataArray(IVE_HANDLE pIveHandle, IVE_DATA_S *pstData, + char *pBuffer, CVI_U16 u32Width, CVI_U16 u32Height) +{ + char *ptr = NULL; + CVI_S32 s32Succ = CVI_SUCCESS; + + s32Succ = CVI_IVE_CreateDataInfo(pIveHandle, pstData, u32Width, + u32Height); + if (s32Succ) { + printf("Ion alloc failed\n"); + return s32Succ; + } + printf("u32Stride = %d\n", pstData->u32Stride); + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstData->u64VirAddr + + (j * pstData->u32Stride)), ptr, u32Width); + ptr += u32Width; + } + return s32Succ; +} + +CVI_S32 CVI_IVE_ReadMem(IVE_HANDLE pIveHandle, IVE_MEM_INFO_S *pstMem, + const char *filename, CVI_U32 uSize) +{ + CVI_S32 s32Succ = CVI_SUCCESS; + FILE *fp; + + fp = fopen(filename, "r"); + if (fp == NULL) { + printf("Can't open %s\n", filename); + return ERR_IVE_OPEN_FILE; + } + + s32Succ = CVI_IVE_CreateMemInfo(pIveHandle, pstMem, uSize); + if (s32Succ) { + printf("Ion alloc failed\n"); + return s32Succ; + } + + int readCnt = + fread((char *)(uintptr_t)pstMem->u64VirAddr, 1, uSize, fp); + + if (readCnt == 0) { + printf("Image %s read failed.\n", filename); + return ERR_IVE_READ_FILE; + } + fclose(fp); + return s32Succ; +} + +CVI_S32 CVI_IVE_ReadMemArray(IVE_HANDLE pIveHandle, IVE_MEM_INFO_S *pstMem, + char *pBuffer, CVI_U32 uSize) +{ + CVI_S32 s32Succ = CVI_SUCCESS; + + s32Succ = CVI_IVE_CreateMemInfo(pIveHandle, pstMem, uSize); + if (s32Succ) { + printf("Ion alloc failed\n"); + return s32Succ; + } + memcpy((char *)(uintptr_t)pstMem->u64VirAddr, (void *)pBuffer, uSize); + return s32Succ; +} + +CVI_S32 CVI_IVE_ReadImageArray(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, + char *pBuffer, IVE_IMAGE_TYPE_E enType, + CVI_U16 u32Width, CVI_U16 u32Height) +{ + char *ptr = NULL; + + memset(pstImg, 0, sizeof(IVE_IMAGE_S)); + + CVI_IVE_CreateImage(pIveHandle, pstImg, enType, u32Width, u32Height); + + if (enType == IVE_IMAGE_TYPE_U8C3_PLANAR) { + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[0] + + (j * pstImg->u32Stride[0])), + ptr, u32Width); + ptr += u32Width; + } + for (size_t j = 0; j < (size_t)pstImg->u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[1] + + (j * pstImg->u32Stride[1])), + ptr, u32Width); + ptr += u32Width; + } + for (size_t j = 0; j < (size_t)pstImg->u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[2] + + (j * pstImg->u32Stride[2])), + ptr, u32Width); + ptr += u32Width; + } + } else if (enType == IVE_IMAGE_TYPE_U8C3_PACKAGE) { + // yyy... uuu... vvv... to yyy... uuu... vvv... + ptr = pBuffer; + for (size_t i = 0; i < (size_t)u32Height; i++) { + uint32_t stb_stride = i * u32Width * 3; + uint32_t image_stride = (i * pstImg->u32Stride[0]); + + for (size_t j = 0; j < (size_t)u32Width; j++) { + uint32_t buf_idx = stb_stride + (j * 3); + uint32_t img_idx = image_stride + (j * 3); + ((char *)(uintptr_t) + pstImg->u64VirAddr[0])[img_idx] = + ptr[buf_idx]; + ((char *)(uintptr_t) + pstImg->u64VirAddr[0])[img_idx + 1] = + ptr[buf_idx + 1]; + ((char *)(uintptr_t) + pstImg->u64VirAddr[0])[img_idx + 2] = + ptr[buf_idx + 2]; + } + } + } else if (enType == IVE_IMAGE_TYPE_YUV420SP) { + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[0] + + (j * pstImg->u32Stride[0])), + ptr, u32Width); + ptr += u32Width; + } + for (size_t j = 0; j < (size_t)pstImg->u32Height / 2; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[1] + + (j * pstImg->u32Stride[1])), + ptr, u32Width); + ptr += u32Width; + } + } else if (enType == IVE_IMAGE_TYPE_YUV422SP) { + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[0] + + (j * pstImg->u32Stride[0])), + ptr, u32Width); + ptr += u32Width; + } + for (size_t j = 0; j < (size_t)pstImg->u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[1] + + (j * pstImg->u32Stride[1])), + ptr, u32Width); + ptr += u32Width; + } + } else if (enType == IVE_IMAGE_TYPE_U16C1 || + enType == IVE_IMAGE_TYPE_S16C1) { + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[0] + + (j * pstImg->u32Stride[0])), + ptr, u32Width * (sizeof(uint16_t))); + ptr += u32Width * (sizeof(uint16_t)); + } + } else { + ptr = pBuffer; + for (size_t j = 0; j < (size_t)u32Height; j++) { + memcpy((char *)(uintptr_t)(pstImg->u64VirAddr[0] + + (j * pstImg->u32Stride[0])), + ptr, u32Width); + ptr += u32Width; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_ReadRawImage(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, + const char *filename, IVE_IMAGE_TYPE_E enType, + CVI_U16 u32Width, CVI_U16 u32Height) +{ + float desiredNChannels = -1; + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: + desiredNChannels = 1; + break; + case IVE_IMAGE_TYPE_YUV420SP: + desiredNChannels = 1.5; + break; + case IVE_IMAGE_TYPE_U16C1: + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_YUV422SP: + desiredNChannels = 2; + break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: + case IVE_IMAGE_TYPE_U8C3_PACKAGE: + desiredNChannels = 3; + break; + default: + printf("Not support channel %s.\n", cviIveImgEnTypeStr[enType]); + return CVI_ERR_IVE_ILLEGAL_PARAM; + } + + if (desiredNChannels > 0) { + int buf_size = (int)((float)u32Width * (float)u32Height * + (float)desiredNChannels); + char buffer[buf_size]; + FILE *fp; + + fp = fopen(filename, "r"); + int readCnt = fread(buffer, 1, buf_size, fp); + + if (readCnt == 0) { + printf("Image %s read failed.\n", filename); + return ERR_IVE_READ_FILE; + } + fclose(fp); + + CVI_IVE_ReadImageArray(pIveHandle, pstImg, buffer, enType, + u32Width, u32Height); + return CVI_SUCCESS; + } + return CVI_FAILURE; +} + +IVE_IMAGE_S CVI_IVE_ReadImage(IVE_HANDLE pIveHandle, const char *filename, IVE_IMAGE_TYPE_E enType) +{ + int desiredNChannels = -1; + CVI_BOOL invertPackage = false; + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + desiredNChannels = STBI_grey; + break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: + desiredNChannels = STBI_rgb; + break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: + desiredNChannels = STBI_rgb; + break; + default: + printf("Not support channel %s.\n", cviIveImgEnTypeStr[enType]); + break; + } + IVE_IMAGE_S img; + + memset(&img, 0, sizeof(IVE_IMAGE_S)); + if (desiredNChannels >= 0) { + int width, height, nChannels; + stbi_uc *stbi_data = stbi_load(filename, &width, &height, &nChannels, desiredNChannels); + + if (stbi_data == NULL) { + printf("Image %s read failed.\n", filename); + return img; + } + CVI_IVE_CreateImage(pIveHandle, &img, enType, width, height); + //printf("desiredNChannels, width, height: %d %d %d\n", desiredNChannels, width, height); + if (enType == IVE_IMAGE_TYPE_U8C3_PLANAR) { + for (size_t i = 0; i < (size_t)height; i++) { + for (size_t j = 0; j < (size_t)width; j++) { + size_t stb_idx = (i * width + j) * 3; + size_t img_idx = (i * img.u32Stride[0] + j); + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[0])[img_idx] = stbi_data[stb_idx]; + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[1])[img_idx] = stbi_data[stb_idx + 1]; + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[2])[img_idx] = stbi_data[stb_idx + 2]; + } + } + } else { + if (invertPackage && enType == IVE_IMAGE_TYPE_U8C3_PACKAGE) { + for (size_t i = 0; i < (size_t)height; i++) { + uint32_t stb_stride = i * width * 3; + uint32_t image_stride = (i * img.u32Stride[0]); + + for (size_t j = 0; j < (size_t)width; j++) { + uint32_t stb_idx = stb_stride + (j * 3); + uint32_t img_idx = image_stride + (j * 3); + + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[0])[img_idx] = + stbi_data[stb_idx + 2]; + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[0])[img_idx + 1] = + stbi_data[stb_idx + 1]; + ((CVI_U8 *)(uintptr_t)img.u64VirAddr[0])[img_idx + 2] = + stbi_data[stb_idx]; + } + } + } else { + stbi_uc *ptr = stbi_data; + + for (size_t j = 0; j < (size_t)height; j++) { + memcpy((void *)(uintptr_t)img.u64VirAddr[0] + (j * img.u32Stride[0]), + ptr, width * desiredNChannels); + ptr += width * desiredNChannels; + } + } + } + stbi_image_free(stbi_data); + } + return img; +} + +CVI_S32 CVI_IVE_WriteImage(IVE_HANDLE pIveHandle, const char *filename, IVE_IMAGE_S *pstImg) +{ + UNUSED(pIveHandle); + int desiredNChannels = -1; + int stride = 1; + uint8_t *arr = NULL; + bool remove_buffer = false; + + switch (pstImg->enType) { + case IVE_IMAGE_TYPE_U8C1: + desiredNChannels = STBI_grey; + arr = (CVI_U8 *)(uintptr_t)pstImg->u64VirAddr[0]; + break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + desiredNChannels = STBI_rgb; + stride = 1; + arr = (uint8_t *)calloc((size_t)pstImg->u32Stride[0] * pstImg->u32Height * desiredNChannels, + (size_t)sizeof(uint8_t)); + size_t image_total = pstImg->u32Stride[0] * pstImg->u32Height; + + for (size_t i = 0; i < image_total; i++) { + size_t stb_idx = i * 3; + + arr[stb_idx] = ((CVI_U8 *)(uintptr_t)pstImg->u64VirAddr[0])[i]; + arr[stb_idx + 1] = ((CVI_U8 *)(uintptr_t)pstImg->u64VirAddr[1])[i]; + arr[stb_idx + 2] = ((CVI_U8 *)(uintptr_t)pstImg->u64VirAddr[2])[i]; + } + stride = 3; + remove_buffer = true; + } break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: + desiredNChannels = STBI_rgb; + arr = (CVI_U8 *)(uintptr_t)pstImg->u64VirAddr[0]; + stride = 1; + break; + default: + printf("Not supported channel %s.", cviIveImgEnTypeStr[pstImg->enType]); + return CVI_FAILURE; + } + stbi_write_png(filename, pstImg->u32Width, pstImg->u32Height, desiredNChannels, arr, + pstImg->u32Stride[0] * stride); + if (remove_buffer) { + free(arr); + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_ResetImage(IVE_IMAGE_S *pstImage, CVI_U8 val) +{ + CVI_U32 u32Stride; + CVI_S32 s32Succ; + IVE_IMAGE_TYPE_E enType; + CVI_U32 u32Width; + CVI_U32 u32Height; + CVI_U8 *pData; + CVI_U16 y; + + enType = pstImage->enType; + u32Width = pstImage->u32Width; + u32Height = pstImage->u32Height; + u32Stride = WidthAlign(u32Width, DEFAULT_ALIGN); + s32Succ = CVI_SUCCESS; + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: { + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[0]; + for (y = 0; y < u32Height; y++, pData += u32Stride) { + memset(pData, val, u32Width); + } + } break; + case IVE_IMAGE_TYPE_YUV420SP: { + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[0]; + for (y = 0; y < u32Height; y++, pData += u32Stride) { + memset(pData, val, u32Width); + } + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[1]; + for (y = 0; y < u32Height / 2; y++, pData += u32Stride) { + memset(pData, val, u32Width); + } + } break; + case IVE_IMAGE_TYPE_YUV422SP: { + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[0]; + for (y = 0; y < u32Height; y++, pData += u32Stride) { + memset(pData, val, u32Width); + } + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[1]; + for (y = 0; y < u32Height; y++, pData += u32Stride) { + memset(pData, val, u32Width); + } + } break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: { + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[0]; + for (y = 0; y < pstImage->u32Height; + y++, pData += pstImage->u32Stride[0] * 3) { + memset(pData, val, pstImage->u32Width * 3); + } + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + for (int i = 0; i < 3; i++) { + pData = (CVI_U8 *)(uintptr_t)pstImage->u64VirAddr[i]; + for (y = 0; y < pstImage->u32Height; + y++, pData += pstImage->u32Stride[i]) { + memset(pData, val, pstImage->u32Width); + } + } + + } break; + case IVE_IMAGE_TYPE_YUV420P: + case IVE_IMAGE_TYPE_YUV422P: + case IVE_IMAGE_TYPE_S8C2_PACKAGE: + case IVE_IMAGE_TYPE_S8C2_PLANAR: + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: + case IVE_IMAGE_TYPE_S32C1: + case IVE_IMAGE_TYPE_U32C1: + case IVE_IMAGE_TYPE_S64C1: + case IVE_IMAGE_TYPE_U64C1: { + printf("Unsupported IMAGE_TYPE %d\n", enType); + s32Succ = CVI_ERR_IVE_ILLEGAL_PARAM; + } break; + default: { + printf("Unknown IMAGE_TYPE %d\n", enType); + s32Succ = CVI_ERR_IVE_ILLEGAL_PARAM; + } break; + } + + return s32Succ; +} + +CVI_S32 CVI_IVE_CreateMemInfo(IVE_HANDLE pIveHandle, IVE_MEM_INFO_S *pstMemInfo, + CVI_U32 u32ByteSize) +{ + UNUSED(pIveHandle); + int s32Ret = CVI_SYS_IonAlloc((CVI_U64 *)&pstMemInfo->u64PhyAddr, + (CVI_VOID **)&pstMemInfo->u64VirAddr, + "ive_mesh", u32ByteSize); + + memset((char *)(uintptr_t)pstMemInfo->u64VirAddr, 0, u32ByteSize); + pstMemInfo->u32Size = u32ByteSize; + return s32Ret; +} + +CVI_S32 CVI_IVE_CreateDataInfo(IVE_HANDLE pIveHandle, IVE_DATA_S *pstDataInfo, + CVI_U16 u32Width, CVI_U16 u32Height) +{ + UNUSED(pIveHandle); + pstDataInfo->u32Stride = WidthAlign(u32Width, LUMA_PHY_ALIGN); + int s32Ret = CVI_SYS_IonAlloc((CVI_U64 *)&pstDataInfo->u64PhyAddr, + (CVI_VOID **)&pstDataInfo->u64VirAddr, + "ive_mesh", + pstDataInfo->u32Stride * u32Height); + + memset((char *)(uintptr_t)pstDataInfo->u64VirAddr, 0, + pstDataInfo->u32Stride * u32Height); + pstDataInfo->u32Width = u32Width; + pstDataInfo->u32Height = u32Height; + return s32Ret; +} + +CVI_S32 _CVI_IVE_CreateImage(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, + IVE_IMAGE_TYPE_E enType, uint16_t u32Width, + uint16_t u32Height, CVI_BOOL bCached) +{ + UNUSED(pIveHandle); + CVI_S32 s32Ret; + CVI_U32 u32Len = 0, u32Channel = 1; + CVI_U32 u32Coffset[3] = { 0 }; + + if (u32Width == 0 || u32Height == 0) { + printf("Image width or height cannot be 0.\n"); + pstImg->enType = enType; + pstImg->u32Width = 0; + pstImg->u32Height = 0; + pstImg->u32Reserved = 0; + for (size_t i = 0; i < 3; i++) { + pstImg->u64VirAddr[i] = 0; + pstImg->u64PhyAddr[i] = 0; + pstImg->u32Stride[i] = 0; + } + return CVI_FAILURE; + } + + switch (enType) { + case IVE_IMAGE_TYPE_S8C1: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_U8C1: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_YUV420SP: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + u32Len = pstImg->u32Stride[0] * u32Height; + u32Coffset[1] = u32Len; + pstImg->u32Stride[1] = WidthAlign(u32Width, DEFAULT_ALIGN); + u32Len += pstImg->u32Stride[0] * u32Height >> 1; + u32Channel = 2; + } break; + case IVE_IMAGE_TYPE_YUV420P: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + u32Len = pstImg->u32Stride[0] * u32Height; + u32Coffset[1] = u32Len; + pstImg->u32Stride[1] = + WidthAlign(u32Width >> 1, DEFAULT_ALIGN); + pstImg->u32Stride[2] = pstImg->u32Stride[1]; + u32Len += pstImg->u32Stride[1] * u32Height >> 1; + u32Coffset[2] = u32Len; + u32Len += pstImg->u32Stride[1] * u32Height >> 1; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_YUV422SP: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + pstImg->u32Stride[1] = pstImg->u32Stride[0]; + u32Len = pstImg->u32Stride[0] * u32Height; + u32Coffset[1] = u32Len; + u32Len += pstImg->u32Stride[0] * u32Height; + u32Channel = 2; + } break; + case IVE_IMAGE_TYPE_YUV422P: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + pstImg->u32Stride[1] = + WidthAlign(u32Width >> 1, DEFAULT_ALIGN); + pstImg->u32Stride[2] = pstImg->u32Stride[1]; + u32Len = pstImg->u32Stride[0] * u32Height; + u32Coffset[1] = u32Len; + u32Len += pstImg->u32Stride[1] * u32Height; + u32Coffset[2] = u32Len; + u32Len += pstImg->u32Stride[1] * u32Height; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_U8C3_PACKAGE: { + pstImg->u32Stride[0] = WidthAlign(u32Width * 3, DEFAULT_ALIGN); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + pstImg->u32Stride[0] = WidthAlign(u32Width, DEFAULT_ALIGN); + pstImg->u32Stride[1] = pstImg->u32Stride[0]; + pstImg->u32Stride[2] = pstImg->u32Stride[0]; + u32Len = pstImg->u32Stride[0] * u32Height; + u32Coffset[1] = u32Len; + u32Len += pstImg->u32Stride[0] * u32Height; + u32Coffset[2] = u32Len; + u32Len += pstImg->u32Stride[0] * u32Height; + u32Channel = 3; + } break; + case IVE_IMAGE_TYPE_BF16C1: { + pstImg->u32Stride[0] = + WidthAlign(u32Width, DEFAULT_ALIGN) * sizeof(int16_t); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_U16C1: { + pstImg->u32Stride[0] = + WidthAlign(u32Width, DEFAULT_ALIGN) * sizeof(uint16_t); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_S16C1: { + pstImg->u32Stride[0] = + WidthAlign(u32Width, DEFAULT_ALIGN) * sizeof(uint16_t); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_U32C1: { + pstImg->u32Stride[0] = + WidthAlign(u32Width, DEFAULT_ALIGN) * sizeof(uint32_t); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_FP32C1: { + pstImg->u32Stride[0] = + WidthAlign(u32Width, DEFAULT_ALIGN) * sizeof(float); + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + default: + printf("Not supported enType %s.\n", + cviIveImgEnTypeStr[enType]); + return CVI_ERR_IVE_ILLEGAL_PARAM; + break; + } + pstImg->enType = enType; + if (pstImg->u32Stride[0] == 0 || u32Len == 0) { + printf("[DEV] Stride not set.\n"); + return CVI_ERR_IVE_ILLEGAL_PARAM; + } + pstImg->u32Width = u32Width; + pstImg->u32Height = u32Height; + if (bCached) { + s32Ret = CVI_SYS_IonAlloc_Cached(&pstImg->u64PhyAddr[0], + (CVI_VOID **)&pstImg->u64VirAddr[0], + "ive_mesh", u32Len); + } else { + s32Ret = CVI_SYS_IonAlloc(&pstImg->u64PhyAddr[0], + (CVI_VOID **)&pstImg->u64VirAddr[0], + "ive_mesh", u32Len); + } + memset((char *)(uintptr_t)pstImg->u64VirAddr[0], 0, u32Len); + if (s32Ret) { + printf("CVI_SYS_IonAlloc failed with %#x\n", s32Ret); + return CVI_FAILURE; + } + + for (size_t i = 1; i < u32Channel; i++) { + pstImg->u64VirAddr[i] = pstImg->u64VirAddr[0] + u32Coffset[i]; + pstImg->u64PhyAddr[i] = pstImg->u64PhyAddr[0] + u32Coffset[i]; + } + + for (size_t i = u32Channel; i < 3; i++) { + pstImg->u64VirAddr[i] = 0; + pstImg->u64PhyAddr[i] = -1; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_CreateImage(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, + IVE_IMAGE_TYPE_E enType, uint16_t u32Width, + uint16_t u32Height) +{ + return _CVI_IVE_CreateImage(pIveHandle, pstImg, enType, u32Width, u32Height, false); +} + +CVI_S32 CVI_IVE_CreateImage_Cached(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, + IVE_IMAGE_TYPE_E enType, uint16_t u32Width, + uint16_t u32Height) +{ + return _CVI_IVE_CreateImage(pIveHandle, pstImg, enType, u32Width, u32Height, true); +} + +CVI_S32 _CVI_IVE_BufFlush_Request(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg, CVI_BOOL bFlush) +{ + UNUSED(pIveHandle); + CVI_U32 u32Len = 0; + CVI_U32 u32Height = pstImg->u32Height; + + switch (pstImg->enType) { + case IVE_IMAGE_TYPE_S8C1: + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_U8C3_PACKAGE: + case IVE_IMAGE_TYPE_BF16C1: + case IVE_IMAGE_TYPE_U16C1: + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U32C1: + case IVE_IMAGE_TYPE_FP32C1: { + u32Len = pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_YUV420SP: { + u32Len = pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[0] * u32Height >> 1; + } break; + case IVE_IMAGE_TYPE_YUV420P: { + u32Len = pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[1] * u32Height >> 1; + u32Len += pstImg->u32Stride[1] * u32Height >> 1; + } break; + case IVE_IMAGE_TYPE_YUV422SP: { + u32Len = pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[0] * u32Height; + } break; + case IVE_IMAGE_TYPE_YUV422P: { + u32Len = pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[1] * u32Height; + u32Len += pstImg->u32Stride[1] * u32Height; + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + u32Len = pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[0] * u32Height; + u32Len += pstImg->u32Stride[0] * u32Height; + } break; + default: + printf("Not supported enType %s.\n", + cviIveImgEnTypeStr[pstImg->enType]); + return CVI_ERR_IVE_ILLEGAL_PARAM; + } + if (u32Len == 0) { + printf("[DEV] BufFlush Stride not set.\n"); + return CVI_ERR_IVE_ILLEGAL_PARAM; + } + if (bFlush) + return CVI_SYS_IonFlushCache(pstImg->u64PhyAddr[0], (char *)(uintptr_t)pstImg->u64VirAddr[0], u32Len); + return CVI_SYS_IonInvalidateCache(pstImg->u64PhyAddr[0], (char *)(uintptr_t)pstImg->u64VirAddr[0], u32Len); +} + +CVI_S32 CVI_IVE_BufFlush(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg) +{ + return _CVI_IVE_BufFlush_Request(pIveHandle, pstImg, true); +} + +CVI_S32 CVI_IVE_BufRequest(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg) +{ + return _CVI_IVE_BufFlush_Request(pIveHandle, pstImg, false); +} + +CVI_S32 _CVI_IVE_Write(const char *filename, CVI_U64 u64VirAddr, CVI_U32 len) +{ + FILE *fp; + int readCnt = 0; + + fp = fopen(filename, "w"); + if (fp == NULL) { + printf("Can't open %s\n", filename); + return ERR_IVE_OPEN_FILE; + } + while (len) { + readCnt = fwrite((char *)(uintptr_t)(u64VirAddr + readCnt), 1, + len, fp); + len -= readCnt; + if (readCnt == 0) { + printf("Image %s write failed.\n", filename); + return ERR_IVE_WRITE_FILE; + } + } + + fclose(fp); + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_WriteData(IVE_HANDLE pIveHandle, const char *filename, + IVE_DATA_S *pstData) +{ + UNUSED(pIveHandle); + return _CVI_IVE_Write(filename, pstData->u64VirAddr, + pstData->u32Stride * pstData->u32Height); +} + +CVI_S32 CVI_IVE_WriteMem(IVE_HANDLE pIveHandle, const char *filename, + IVE_MEM_INFO_S *pstMem) +{ + UNUSED(pIveHandle); + return _CVI_IVE_Write(filename, pstMem->u64VirAddr, pstMem->u32Size); +} + +CVI_S32 CVI_IVE_WriteImg(IVE_HANDLE pIveHandle, const char *filename, + IVE_IMAGE_S *pstImg) +{ + UNUSED(pIveHandle); + float desiredNChannels = 1.0; + + switch (pstImg->enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: + case IVE_IMAGE_TYPE_S32C1: + case IVE_IMAGE_TYPE_U32C1: + case IVE_IMAGE_TYPE_S64C1: + case IVE_IMAGE_TYPE_U64C1: + case IVE_IMAGE_TYPE_U8C3_PACKAGE: { + desiredNChannels = 1; + } break; + case IVE_IMAGE_TYPE_YUV420P: + case IVE_IMAGE_TYPE_YUV420SP: { + desiredNChannels = 1.5; + } break; + case IVE_IMAGE_TYPE_YUV422P: + case IVE_IMAGE_TYPE_YUV422SP: { + desiredNChannels = 2; + } break; + case IVE_IMAGE_TYPE_U8C3_PLANAR: { + desiredNChannels = 3; + } break; + default: { + printf("Unsupported conversion type: %u.\n", pstImg->enType); + return CVI_ERR_IVE_ILLEGAL_PARAM; + } break; + } + int len = (int)((float)pstImg->u32Stride[0] * (float)pstImg->u32Height * + desiredNChannels); + + return _CVI_IVE_Write(filename, pstImg->u64VirAddr[0], len); +} + +CVI_S32 CVI_SYS_FreeM(IVE_HANDLE pIveHandle, IVE_MEM_INFO_S *pstMem) +{ + UNUSED(pIveHandle); + return CVI_SYS_IonFree(pstMem->u64PhyAddr, + (char *)(uintptr_t)pstMem->u64VirAddr); +} + +CVI_S32 CVI_SYS_FreeI(IVE_HANDLE pIveHandle, IVE_IMAGE_S *pstImg) +{ + UNUSED(pIveHandle); + return CVI_SYS_IonFree(pstImg->u64PhyAddr[0], + (char *)(uintptr_t)pstImg->u64VirAddr[0]); +} + +CVI_S32 CVI_SYS_FreeD(IVE_HANDLE pIveHandle, IVE_DATA_S *pstData) +{ + UNUSED(pIveHandle); + return CVI_SYS_IonFree(pstData->u64PhyAddr, + (char *)(uintptr_t)pstData->u64VirAddr); +} + +CVI_S32 CVI_IVE_DiffFg_Split(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstDiffFg, + IVE_DST_IMAGE_S *pstBgDiffFg, + IVE_DST_IMAGE_S *pstFrmDiffFg) +{ + UNUSED(pIveHandle); + int i = 0; + int size = (pstDiffFg->u32Stride[0] / sizeof(uint16_t)) * + pstDiffFg->u32Height; + + for (i = 0; i < size; i++) { + ((char *)(uintptr_t)pstBgDiffFg->u64VirAddr[0])[i] = + ((char *)(uintptr_t)pstDiffFg->u64VirAddr[0])[i * 2]; + ((char *)(uintptr_t)pstFrmDiffFg->u64VirAddr[0])[i] = + ((char *)(uintptr_t)pstDiffFg->u64VirAddr[0])[i * 2 + 1]; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_ChgSta_Split(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstChgSta, + IVE_DST_IMAGE_S *pstChgStaImg, + IVE_DST_IMAGE_S *pstChgStaFg, + IVE_DST_IMAGE_S *pstChStaLift) +{ + UNUSED(pIveHandle); + int i = 0; + int size = (pstChgSta->u32Stride[0] / sizeof(uint32_t)) * + pstChgSta->u32Height; + + for (i = 0; i < size; i++) { + ((char *)(uintptr_t)pstChgStaImg->u64VirAddr[0])[i] = + ((char *)(uintptr_t)pstChgSta->u64VirAddr[0])[i * 4];//0 + ((char *)(uintptr_t)pstChgStaFg->u64VirAddr[0])[i] = + ((char *)(uintptr_t)pstChgSta->u64VirAddr[0])[i * 4 + 1];//1 + ((char *)(uintptr_t)pstChStaLift->u64VirAddr[0])[i * 2] = + ((char *)(uintptr_t)pstChgSta->u64VirAddr[0])[i * 4 + 2];//2 + ((char *)(uintptr_t)pstChStaLift->u64VirAddr[0])[i * 2 + 1] = + ((char *)(uintptr_t)pstChgSta->u64VirAddr[0])[i * 4 + 3];//3 + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_DUMP(IVE_HANDLE pIveHandle) +{ + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ioctl(p->devfd, CVI_IVE_IOC_DUMP); + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_RESET(IVE_HANDLE pIveHandle, int s) +{ + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ioctl(p->devfd, CVI_IVE_IOC_RESET, &s); + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_QUERY(IVE_HANDLE pIveHandle, CVI_BOOL *pbFinish, + CVI_BOOL bBlock) +{ + struct cvi_ive_query_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.pbFinish = pbFinish; + ive_arg.bBlock = bBlock; + ioctl(p->devfd, CVI_IVE_IOC_QUERY, &ive_arg); + return CVI_SUCCESS; +} + +CVI_S32 CVI_IVE_DMA(IVE_HANDLE pIveHandle, IVE_DATA_S *pstSrc, + IVE_DST_DATA_S *pstDst, IVE_DMA_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_dma_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_DMA, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_And(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstDst, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_and_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_And, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Or(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstDst, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_or_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Or, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Xor(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstDst, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_xor_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Xor, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Add(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstDst, + IVE_ADD_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_add_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.pstCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + if (ioctl(p->devfd, CVI_IVE_IOC_Add, &ive_arg) < 0) { + fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__); + return -1; + } + return 0; +} + +CVI_S32 CVI_IVE_Sub(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstDst, + IVE_SUB_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_sub_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Sub, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Erode(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_ERODE_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_erode_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Erode, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Dilate(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_DILATE_CTRL_S *pstctrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_dilate_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstctrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Dilate, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Thresh(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_THRESH_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_thresh_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Thresh, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_MatchBgModel(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstCurImg, + IVE_DATA_S *pstBgModel, IVE_IMAGE_S *pstFgFlag, + IVE_DST_IMAGE_S *pstDiffFg, + IVE_DST_MEM_INFO_S *pstStatData, + IVE_MATCH_BG_MODEL_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_match_bgmodel_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stCurImg = *pstCurImg; + ive_arg.stBgModel = *pstBgModel; + ive_arg.stFgFlag = *pstFgFlag; + ive_arg.stDiffFg = *pstDiffFg; + ive_arg.stStatData = *pstStatData; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_MatchBgModel, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_UpdateBgModel(IVE_HANDLE pIveHandle, IVE_DATA_S *pstBgModel, + IVE_IMAGE_S *pstFgFlag, IVE_DST_IMAGE_S *pstBgImg, + IVE_DST_IMAGE_S *pstChgSta, + IVE_DST_MEM_INFO_S *pstStatData, + IVE_UPDATE_BG_MODEL_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_update_bgmodel_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stBgModel = *pstBgModel; + ive_arg.stFgFlag = *pstFgFlag; + ive_arg.stBgImg = *pstBgImg; + ive_arg.stChgSta = *pstChgSta; + ive_arg.stStatData = *pstStatData; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_UpdateBgModel, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_GMM(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstFg, IVE_DST_IMAGE_S *pstBg, + IVE_MEM_INFO_S *pstModel, IVE_GMM_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_gmm_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stFg = *pstFg; + ive_arg.stBg = *pstBg; + ive_arg.stModel = *pstModel; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_GMM, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_GMM2(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_SRC_IMAGE_S *pstFactor, IVE_DST_IMAGE_S *pstFg, + IVE_DST_IMAGE_S *pstBg, IVE_DST_IMAGE_S *pstMatchModelInfo, + IVE_MEM_INFO_S *pstModel, IVE_GMM2_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_gmm2_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stFactor = *pstFactor; + ive_arg.stFg = *pstFg; + ive_arg.stBg = *pstBg; + ive_arg.stInfo = *pstMatchModelInfo; + ive_arg.stModel = *pstModel; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_GMM2, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Bernsen(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_BERNSEN_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_bernsen_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Bernsen, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Filter(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_FILTER_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_filter_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Filter, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Sobel(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDstH, IVE_DST_IMAGE_S *pstDstV, + IVE_SOBEL_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_sobel_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + if (pstDstH != CVI_NULL) + ive_arg.stDstH = *pstDstH; + if (pstDstV != CVI_NULL) + ive_arg.stDstV = *pstDstV; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Sobel, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_MagAndAng(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDstMag, + IVE_DST_IMAGE_S *pstDstAng, + IVE_MAG_AND_ANG_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_maganang_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + if (pstDstMag != CVI_NULL) + ive_arg.stDstMag = *pstDstMag; + if (pstDstAng != CVI_NULL) + ive_arg.stDstAng = *pstDstAng; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_MagAndAng, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_CSC(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_CSC_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_csc_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_CSC, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_FilterAndCSC(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_FILTER_AND_CSC_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_filter_and_csc_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_FilterAndCSC, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Hist(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_MEM_INFO_S *pstDst, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_hist_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Hist, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Map(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_SRC_MEM_INFO_S *pstMap, IVE_DST_IMAGE_S *pstDst, + IVE_MAP_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_map_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stMap = *pstMap; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Map, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_NCC(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_MEM_INFO_S *pstDst, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_ncc_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_NCC, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Integ(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_MEM_INFO_S *pstDst, IVE_INTEG_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_integ_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Integ, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_LBP(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_LBP_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_lbp_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = p; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + ioctl(p->devfd, CVI_IVE_IOC_LBP, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Thresh_S16(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_THRESH_S16_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_thresh_s16_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Thresh_S16, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Thresh_U16(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_THRESH_U16_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_thres_su16_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Thresh_U16, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_16BitTo8Bit(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_16BIT_TO_8BIT_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_16bit_to_8bit_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_16BitTo8Bit, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_OrdStatFilter(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_ORD_STAT_FILTER_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_ord_stat_filter_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_OrdStatFilter, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_CannyEdge(IVE_IMAGE_S *pstEdge, IVE_MEM_INFO_S *pstStack) +{ + UNUSED(pstStack); + do_hysteresis_wo_ang((unsigned char *)(uintptr_t)pstEdge->u64VirAddr[0], + (unsigned char *)(uintptr_t)pstEdge->u64VirAddr[0], + pstEdge->u32Width, pstEdge->u32Height, pstEdge->u32Stride[0]); + + return 0; +} + +CVI_S32 CVI_IVE_CannyHysEdge(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstEdge, + IVE_DST_MEM_INFO_S *pstStack, + IVE_CANNY_HYS_EDGE_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_canny_hys_edge_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstEdge; + ive_arg.stStack = *pstStack; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_CannyHysEdge, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_NormGrad(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDstH, IVE_DST_IMAGE_S *pstDstV, + IVE_DST_IMAGE_S *pstDstHV, + IVE_NORM_GRAD_CTRL_S *pstCtrl, CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_norm_grad_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + if (pstDstH != CVI_NULL) + ive_arg.stDstH = *pstDstH; + if (pstDstV != CVI_NULL) + ive_arg.stDstV = *pstDstV; + if (pstDstHV != CVI_NULL) + ive_arg.stDstHV = *pstDstHV; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_NormGrad, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_GradFg(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstBgDiffFg, + IVE_SRC_IMAGE_S *pstCurGrad, IVE_SRC_IMAGE_S *pstBgGrad, + IVE_DST_IMAGE_S *pstGradFg, IVE_GRAD_FG_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_grad_fg_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + if (pstBgDiffFg != CVI_NULL) + ive_arg.stBgDiffFg = *pstBgDiffFg; + if (pstCurGrad != CVI_NULL) + ive_arg.stCurGrad = *pstCurGrad; + ive_arg.stBgGrad = *pstBgGrad; + ive_arg.stGradFg = *pstGradFg; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_GradFg, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_SAD(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, IVE_DST_IMAGE_S *pstSad, + IVE_DST_IMAGE_S *pstThr, IVE_SAD_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_sad_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stSad = *pstSad; + ive_arg.stThr = *pstThr; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_SAD, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_Resize(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S astSrc[], + IVE_DST_IMAGE_S astDst[], IVE_RESIZE_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_resize_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.astSrc = astSrc; + ive_arg.astDst = astDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_Resize, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_imgInToOdma(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, IVE_FILTER_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_filter_arg ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_imgInToOdma, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_rgbPToYuvToErodeToDilate(IVE_HANDLE pIveHandle, + IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst1, + IVE_DST_IMAGE_S *pstDst2, + IVE_FILTER_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_rgbPToYuvToErodeToDilate ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst1 = *pstDst1; + ive_arg.stDst2 = *pstDst2; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_rgbPToYuvToErodeToDilate, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_STCandiCorner(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc, + IVE_DST_IMAGE_S *pstDst, + IVE_ST_CANDI_CORNER_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_stcandicorner ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc = *pstSrc; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_STCandiCorner, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_FrameDiffMotion(IVE_HANDLE pIveHandle, IVE_SRC_IMAGE_S *pstSrc1, + IVE_SRC_IMAGE_S *pstSrc2, + IVE_DST_IMAGE_S *pstDst, + IVE_FRAME_DIFF_MOTION_CTRL_S *pstCtrl, + CVI_BOOL bInstant) +{ + struct cvi_ive_ioctl_md ive_arg; + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + ive_arg.pIveHandle = pIveHandle; + ive_arg.stSrc1 = *pstSrc1; + ive_arg.stSrc2 = *pstSrc2; + ive_arg.stDst = *pstDst; + ive_arg.stCtrl = *pstCtrl; + ive_arg.bInstant = bInstant; + + ioctl(p->devfd, CVI_IVE_IOC_MD, &ive_arg); + return 0; +} + +CVI_S32 CVI_IVE_CMDQ(IVE_HANDLE pIveHandle) +{ + struct IVE_HANDLE_CTX *p = (struct IVE_HANDLE_CTX *)pIveHandle; + + if (p->devfd <= 0) { + printf("Device ive is not open, please check it\n"); + return CVI_ERR_IVE_INVALID_DEVID; + } + + ioctl(p->devfd, CVI_IVE_IOC_CMDQ, NULL); + return 0; +} diff --git a/middleware/v2/modules/mipi_tx/Makefile b/middleware/v2/modules/mipi_tx/Makefile new file mode 100644 index 000000000..5a42ea1b9 --- /dev/null +++ b/middleware/v2/modules/mipi_tx/Makefile @@ -0,0 +1,35 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I./include +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libmipi_tx.a +TARGET_SO = $(MW_LIB)/libmipi_tx.so + +EXTRA_CFLAGS = $(INCS) + +.PHONY : clean all +all : $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/mipi_tx/src/mipi_tx.c b/middleware/v2/modules/mipi_tx/src/mipi_tx.c new file mode 100644 index 000000000..f974e5704 --- /dev/null +++ b/middleware/v2/modules/mipi_tx/src/mipi_tx.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include "mipi_tx.h" + +static void _cal_htt_extra(struct combo_dev_cfg_s *dev_cfg) +{ + unsigned char lane_num = 0, bits = 0; + unsigned short htt_old, htt_new, htt_new_extra; + unsigned short vtt; + float fps; + float bit_rate_MHz; + float clk_hs_MHz; + float clk_hs_ns; + float line_rate_KHz, line_time_us; + float over_head; + float t_period_max, t_period_real; + struct sync_info_s *sync_info = &dev_cfg->sync_info; + + for (int i = 0; i < LANE_MAX_NUM; i++) { + if ((dev_cfg->lane_id[i] < 0) || (dev_cfg->lane_id[i] >= MIPI_TX_LANE_MAX)) + continue; + if (dev_cfg->lane_id[i] != MIPI_TX_LANE_CLK) + ++lane_num; + } + + switch (dev_cfg->output_format) { + case OUT_FORMAT_RGB_16_BIT: + bits = 16; + break; + + case OUT_FORMAT_RGB_18_BIT: + bits = 18; + break; + + case OUT_FORMAT_RGB_24_BIT: + bits = 24; + break; + + case OUT_FORMAT_RGB_30_BIT: + bits = 30; + break; + + default: + break; + } + + htt_old = sync_info->vid_hsa_pixels + sync_info->vid_hbp_pixels + + sync_info->vid_hline_pixels + sync_info->vid_hfp_pixels; + vtt = sync_info->vid_vsa_lines + sync_info->vid_vbp_lines + + sync_info->vid_active_lines + sync_info->vid_vfp_lines; + fps = dev_cfg->pixel_clk * 1000.0 / (htt_old * vtt); + bit_rate_MHz = dev_cfg->pixel_clk / 1000.0 * bits / lane_num; + clk_hs_MHz = bit_rate_MHz / 2; + clk_hs_ns = 1000 / clk_hs_MHz; + line_rate_KHz = vtt * fps / 1000; + line_time_us = 1000 / line_rate_KHz; + over_head = (3 * 50 * 2 * 3) + clk_hs_ns * 360; + t_period_max = line_time_us * 1000 - over_head; + t_period_real = clk_hs_ns * sync_info->vid_hline_pixels * bits / 4 / 2; + htt_new = (unsigned short)(htt_old * t_period_real / t_period_max); + if (htt_new > htt_old) { + if (htt_new & 0x0003) + htt_new += (4 - (htt_new & 0x0003)); + htt_new_extra = htt_new - htt_old; + sync_info->vid_hfp_pixels += htt_new_extra; + dev_cfg->pixel_clk = htt_new * vtt * fps / 1000; + } +} + +int mipi_tx_cfg(int fd, struct combo_dev_cfg_s *dev_cfg) +{ + struct combo_dev_cfg_s dev_cfg_t = *dev_cfg; + + _cal_htt_extra(&dev_cfg_t); + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_DEV_CFG, &dev_cfg_t)) { + perror("CVI_VIP_MIPI_TX_SET_DEV_CFG"); + return -1; + } + return 0; +} + +int mipi_tx_send_cmd(int fd, struct cmd_info_s *cmd_info) +{ + if (cmd_info->cmd_size == 0) + return -1; + + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_CMD, cmd_info)) { + perror("CVI_VIP_MIPI_TX_SET_CMD"); + return -1; + } + return 0; +} + + +int mipi_tx_recv_cmd(int fd, struct get_cmd_info_s *cmd_info) +{ + if (cmd_info->get_data_size == 0) + return -1; + + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_GET_CMD, cmd_info)) { + perror("CVI_VIP_MIPI_TX_GET_CMD"); + return -1; + } + return 0; +} + +int mipi_tx_enable(int fd) +{ + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_ENABLE, NULL)) { + perror("CVI_VIP_MIPI_TX_ENABLE"); + return -1; + } + return 0; +} + +int mipi_tx_disable(int fd) +{ + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_DISABLE, NULL)) { + perror("CVI_VIP_MIPI_TX_DISABLE"); + return -1; + } + return 0; +} + +int mipi_tx_set_hs_settle(int fd, const struct hs_settle_s *hs_cfg) +{ + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_HS_SETTLE, hs_cfg)) { + perror("CVI_VIP_MIPI_TX_SET_HS_SETTLE"); + return -1; + } + return 0; +} + +int mipi_tx_get_hs_settle(int fd, struct hs_settle_s *hs_cfg) +{ + if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_GET_HS_SETTLE, hs_cfg)) { + perror("CVI_VIP_MIPI_TX_GET_HS_SETTLE"); + return -1; + } + return 0; +} + diff --git a/middleware/v2/modules/misc/Makefile b/middleware/v2/modules/misc/Makefile new file mode 100644 index 000000000..77989c094 --- /dev/null +++ b/middleware/v2/modules/misc/Makefile @@ -0,0 +1,35 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I$(MW_INC) +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libmisc.a +TARGET_SO = $(MW_LIB)/libmisc.so + +EXTRA_CFLAGS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) + +.PHONY : clean all +all : $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/misc/src/cvi_misc.c b/middleware/v2/modules/misc/src/cvi_misc.c new file mode 100644 index 000000000..86bd62b28 --- /dev/null +++ b/middleware/v2/modules/misc/src/cvi_misc.c @@ -0,0 +1,667 @@ +#include +#include +#include +#include /* low-level i/o */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "cvi_base.h" + +#define CVI_EFUSE_CHIP_SN_SIZE 8 +#define CVI_EFUSE_CHIP_SN_ADDR 0x0C + +CVI_S32 CVI_MISC_SysSuspend(void) +{ + CVI_VPSS_Suspend(); + //CVI_GDC_Suspend(); + CVI_VO_Suspend(); + + //TODO + //v4l2_dev_close(false, true, true, true); + return CVI_SUCCESS; +} + +CVI_S32 CVI_MISC_SysResume(void) +{ + //TODO + //v4l2_dev_open(false, true, true, true); + + VI_VPSS_MODE_S stVIVPSSMode; + VPSS_MODE_S stVPSSMode; + + CVI_SYS_GetVIVPSSMode(&stVIVPSSMode); + CVI_SYS_GetVPSSModeEx(&stVPSSMode); +//TODO +#if 0 + if (init_vpss_device() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "init vpss failed.\n"); + return CVI_FAILURE; + } + + if (init_disp_device() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "init disp failed.\n"); + return CVI_FAILURE; + } + + if (init_dwa_device() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "init dwa failed.\n"); + return CVI_FAILURE; + } + + if (init_isp_device() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "init isp failed.\n"); + return CVI_FAILURE; + } +#endif + CVI_SYS_SetVIVPSSMode(&stVIVPSSMode); + CVI_SYS_SetVPSSModeEx(&stVPSSMode); + + CVI_VO_Resume(); + //CVI_GDC_Resume(); + CVI_VPSS_Resume(); + + return CVI_SUCCESS; +} + + +CVI_S32 CVI_MISC_GetChipSNSize(CVI_U32 *pu32SNSize) +{ + if (pu32SNSize) + *pu32SNSize = CVI_EFUSE_CHIP_SN_SIZE; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_MISC_GetChipSN(CVI_U8 *pu8SN, CVI_U32 u32SNSize) +{ + FILE *fp; + + if (!pu8SN) + return CVI_ERR_SYS_ILLEGAL_PARAM; + + fp = fopen("/sys/class/cvi-base/base_efuse_shadow", "r"); + if (!fp) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Can't open efuse file.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (u32SNSize > CVI_EFUSE_CHIP_SN_SIZE) + u32SNSize = CVI_EFUSE_CHIP_SN_SIZE; + + fseek(fp, CVI_EFUSE_CHIP_SN_ADDR, SEEK_SET); + if (fread(pu8SN, 1, u32SNSize, fp) != u32SNSize) { + CVI_TRACE_SYS(CVI_DBG_ERR, "fread failed\n"); + return CVI_FAILURE; + } + + fclose(fp); + + return CVI_SUCCESS; +} + +#define SIGBASE_STATE_CHANGE 44 +pthread_t pm_thread; +CVI_BOOL g_is_pm_running = CVI_FALSE; + +static CVI_S32 register_pm_ioctl(int io_fd) +{ + struct base_statesignal cs; + int ret; + + memset(&cs, 0, sizeof(cs)); + cs.signr = SIGBASE_STATE_CHANGE; + ret = ioctl(io_fd, IOCTL_STATESIG, &cs); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "register connect signal fail %d", ret); + return -1; + } + return 0; +} + +static CVI_VOID *pm_event_handler(CVI_VOID *data) +{ + int base_pm_fd; + sigset_t mask; + siginfo_t info; + struct timespec ts; + int ret; + + prctl(PR_SET_NAME, "pm_event_handler"); + (void)(data); + + if (open_device(BASE_DEV_NAME, &base_pm_fd) == -1) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base dev open fail!\n"); + return NULL; + } + + /* BLOCK signal. */ + sigemptyset(&mask); + sigaddset(&mask, SIGBASE_STATE_CHANGE); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Cannot block SIGBASE_STATE_CHANGE: %s.\n", strerror(errno)); + return NULL; + } + + /* register signal */ + if (register_pm_ioctl(base_pm_fd) < 0) + return NULL; + /* configure the timeout 50ms */ + ts.tv_sec = 0; + ts.tv_nsec = 50000000; + while (g_is_pm_running) { + sigemptyset(&mask); + sigaddset(&mask, SIGBASE_STATE_CHANGE); + ret = sigtimedwait(&mask, &info, &ts); + if (ret == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + CVI_TRACE_SYS(CVI_DBG_ERR, "sigwaitinfo() failed: %s.\n", strerror(errno)); + goto exit_loop; + } + if (info.si_signo == SIGBASE_STATE_CHANGE) { + CVI_U32 pm_state; + /* get current state. */ + ret = ioctl(base_pm_fd, IOCTL_READ_STATE, &pm_state); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "get currenct state fail %d\n", ret); + goto exit_loop; + } + CVI_TRACE_SYS(CVI_DBG_INFO, "receive state %d\n", pm_state); + printf("receive state %d\n", pm_state); + switch (pm_state) { + case BASE_STATE_SUSPEND_PREPARE: { + /* call VIP user space suspend. */ + CVI_VI_Suspend(); + + CVI_MISC_SysSuspend(); + + /* notify the user space suspend is complete*/ + ret = ioctl(base_pm_fd, IOCTL_USER_SUSPEND_DONE, 0); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "set suspend done fail %d\n", ret); + goto exit_loop; + } + break; + } + case BASE_STATE_RESUME: { + CVI_MISC_SysResume(); + + /* call VIP user space resume. */ + CVI_VI_Resume(); + /* notify the user space resume is complete*/ + ret = ioctl(base_pm_fd, IOCTL_USER_RESUME_DONE, 0); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "set resume done fail %d\n", ret); + goto exit_loop; + } + break; + } + default: + /* receive other state change */ + break; + } + + } else { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "other signal number %d, %d\n", ret, info.si_signo); + } + + } + close(base_pm_fd); + +exit_loop: + g_is_pm_running = CVI_FALSE; + pthread_exit(NULL); +} + +CVI_S32 CVI_MISC_StartPMThread(void) +{ + struct sched_param param; + pthread_attr_t attr; + + if (g_is_pm_running == CVI_TRUE) { + CVI_TRACE_SYS(CVI_DBG_WARN, "already started\n"); + return CVI_FAILURE; + } + g_is_pm_running = CVI_TRUE; + + param.sched_priority = 70; + + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + + pthread_create(&pm_thread, &attr, (void *)pm_event_handler, NULL); + CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StartPMThread\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_MISC_StopPMThread(void) +{ + if (g_is_pm_running == CVI_FALSE) { + CVI_TRACE_SYS(CVI_DBG_WARN, "not start yet\n"); + return CVI_FAILURE; + } + + g_is_pm_running = CVI_FALSE; + if (pm_thread) { + pthread_join(pm_thread, NULL); + pm_thread = 0; + } + CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StopPMThread\n"); + return CVI_SUCCESS; +} + +// =========================================================================== +// EFUSE API +// =========================================================================== +static struct _CVI_EFUSE_AREA_S { + CVI_U32 addr; + CVI_U32 size; +} cvi_efuse_area[] = { [CVI_EFUSE_AREA_USER] = { 0x40, 40 }, + [CVI_EFUSE_AREA_DEVICE_ID] = { 0x8c, 8 }, + [CVI_EFUSE_AREA_HASH0_PUBLIC] = { 0xA8, 32 }, + [CVI_EFUSE_AREA_LOADER_EK] = { 0xD8, 16 }, + [CVI_EFUSE_AREA_DEVICE_EK] = { 0xE8, 16 }, + [CVI_EFUSE_AREA_CHIP_SN] = { 0x0C, 8 } }; + +static struct _CVI_EFUSE_LOCK_S { + CVI_U32 wlock_shift; + CVI_U32 rlock_shift; +} cvi_efuse_lock[] = { [CVI_EFUSE_LOCK_HASH0_PUBLIC] = { 0, 8 }, + [CVI_EFUSE_LOCK_LOADER_EK] = { 4, 12 }, + [CVI_EFUSE_LOCK_DEVICE_EK] = { 6, 14 } }; + +static struct _CVI_EFUSE_USER_S { + CVI_U32 addr; + CVI_U32 size; +} cvi_efuse_user[] = { + { 0x40, 4 }, + { 0x48, 4 }, + { 0x50, 4 }, + { 0x58, 4 }, + { 0x60, 4 }, + { 0x68, 4 }, + { 0x70, 4 }, + { 0x78, 4 }, + { 0x80, 4 }, + { 0x88, 4 }, +}; + +#define CVI_EFUSE_TOTAL_SIZE 0x100 + +#define CVI_EFUSE_LOCK_ADDR 0xF8 +#define CVI_EFUSE_SECURE_CONF_ADDR 0xA0 +#define CVI_EFUSE_SCS_ENABLE_SHIFT 0 +#define CVI_EFUSE_SW_INFO 0x2C +#define CVI_EFUSE_CUSTOMER_ADDR 0x4 + +#define CVI_EFUSE_PATH_PROG "/sys/class/cvi-base/base_efuse_prog" +#define CVI_EFUSE_PATH_SHADOW "/sys/class/cvi-base/base_efuse_shadow" + +CVI_S32 CVI_EFUSE_GetSize(CVI_EFUSE_AREA_E area, CVI_U32 *size) +{ + if (area >= ARRAY_SIZE(cvi_efuse_area) || + cvi_efuse_area[area].size == 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area); + return CVI_ERR_SYS_NOMEM; + } + + if (size) + *size = cvi_efuse_area[area].size; + + return 0; +} + +static CVI_S32 _CVI_EFUSE_Read(CVI_U32 addr, void *buf, CVI_U32 buf_size) +{ + CVI_S32 ret = -1; + + CVI_TRACE_SYS(CVI_DBG_DEBUG, "addr=0x%02x\n", addr); + + if (!buf) + return CVI_ERR_SYS_ILLEGAL_PARAM; + + FILE *fp = fopen(CVI_EFUSE_PATH_SHADOW, "r"); + + if (!fp) { + ret = errno; + CVI_TRACE_SYS(CVI_DBG_ERR, "fopen(%s)\n", + CVI_EFUSE_PATH_SHADOW); + return ret; + } + + fseek(fp, addr, SEEK_SET); + ret = fread(buf, buf_size, 1, fp); + if (ret < 0) + CVI_TRACE_SYS(CVI_DBG_ERR, "ret=%d\n", ret); + + fclose(fp); + + return ret; +} + +static CVI_S32 _CVI_EFUSE_Write(CVI_U32 addr, const void *buf, CVI_U32 buf_size) +{ + CVI_TRACE_SYS(CVI_DBG_DEBUG, "addr=0x%02x\n", addr); + + char cmd[64]; + CVI_U32 value; + CVI_U32 aligned_addr = addr; + CVI_U32 aligned_size = buf_size; + void *aligned_buf = NULL; + size_t i; + + if (!buf) + return CVI_ERR_SYS_ILLEGAL_PARAM; + + if (aligned_addr % 4) { + aligned_addr -= aligned_addr % 4; + } + + if (aligned_size % 4) { + aligned_size += 4 - aligned_size % 4; + } + + aligned_buf = malloc(aligned_size); + memset(aligned_buf, 0, aligned_size); + memcpy((CVI_U8 *)aligned_buf + (addr - aligned_addr), buf, buf_size); + + for (i = 0; i < aligned_size; i += 4) { + memcpy(&value, (CVI_U8 *)aligned_buf + i, sizeof(value)); + snprintf(cmd, sizeof(cmd), "0x%04zx=0x%08x", addr + i, value); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "cmd=%s\n", cmd); + + FILE *fp = fopen(CVI_EFUSE_PATH_PROG, "w"); + int ret; + + if (!fp) { + ret = errno; + CVI_TRACE_SYS(CVI_DBG_ERR, "fopen(%s)\n", + CVI_EFUSE_PATH_PROG); + return ret; + } + + ret = fwrite(cmd, strlen(cmd), 1, fp); + if (ret < 0) + CVI_TRACE_SYS(CVI_DBG_ERR, "ret=%d\n", ret); + fclose(fp); + } + + return 0; +} + +CVI_S32 CVI_EFUSE_Read(CVI_EFUSE_AREA_E area, CVI_U8 *buf, CVI_U32 buf_size) +{ + CVI_U32 user_size = cvi_efuse_area[CVI_EFUSE_AREA_USER].size; + CVI_U8 user[user_size], *p; + CVI_S32 ret; + size_t i; + + if (area >= ARRAY_SIZE(cvi_efuse_area) || + cvi_efuse_area[area].size == 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area); + return CVI_ERR_SYS_NOMEM; + } + + if (!buf) + return CVI_ERR_SYS_ILLEGAL_PARAM; + + memset(buf, 0, buf_size); + + if (buf_size > cvi_efuse_area[area].size) + buf_size = cvi_efuse_area[area].size; + + if (area != CVI_EFUSE_AREA_USER) + return _CVI_EFUSE_Read(cvi_efuse_area[area].addr, buf, + buf_size); + + memset(user, 0, user_size); + + p = user; + for (i = 0; i < ARRAY_SIZE(cvi_efuse_user); i++) { + ret = _CVI_EFUSE_Read(cvi_efuse_user[i].addr, p, + cvi_efuse_user[i].size); + if (ret < 0) + return ret; + p += cvi_efuse_user[i].size; + } + + memcpy(buf, user, buf_size); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_EFUSE_Write(CVI_EFUSE_AREA_E area, const CVI_U8 *buf, + CVI_U32 buf_size) +{ + CVI_U32 user_size = cvi_efuse_area[CVI_EFUSE_AREA_USER].size; + CVI_U8 user[user_size], *p; + CVI_S32 ret; + size_t i; + + if (area >= ARRAY_SIZE(cvi_efuse_area) || + cvi_efuse_area[area].size == 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area); + return CVI_ERR_SYS_NOMEM; + } + if (!buf) + return CVI_ERR_SYS_ILLEGAL_PARAM; + + if (buf_size > cvi_efuse_area[area].size) + buf_size = cvi_efuse_area[area].size; + + if (area != CVI_EFUSE_AREA_USER) { + return _CVI_EFUSE_Write(cvi_efuse_area[area].addr, buf, + buf_size); + } + + memset(user, 0, user_size); + memcpy(user, buf, buf_size); + + p = user; + for (i = 0; i < ARRAY_SIZE(cvi_efuse_user); i++) { + ret = _CVI_EFUSE_Write(cvi_efuse_user[i].addr, p, + cvi_efuse_user[i].size); + if (ret < 0) + return ret; + p += cvi_efuse_user[i].size; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_EFUSE_EnableSecureBoot(void) +{ + CVI_U32 value = 0x3 << CVI_EFUSE_SCS_ENABLE_SHIFT; + + return _CVI_EFUSE_Write(CVI_EFUSE_SECURE_CONF_ADDR, &value, + sizeof(value)); +} + +CVI_S32 CVI_EFUSE_IsSecureBootEnabled(void) +{ + CVI_U32 value = 0; + CVI_S32 ret = 0; + + ret = _CVI_EFUSE_Read(CVI_EFUSE_SECURE_CONF_ADDR, &value, + sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + value &= 0x3 << CVI_EFUSE_SCS_ENABLE_SHIFT; + return !!value; +} + +CVI_S32 CVI_EFUSE_EnableFastBoot(void) +{ + CVI_U32 value = 0, data; + CVI_S32 ret = 0; + CVI_U32 chip = 0; + + CVI_SYS_GetChipId(&chip); + if (!IS_CHIP_CV181X(chip) && !IS_CHIP_CV180X(chip)) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "chip id=%d\n", chip); + return CVI_FAILURE; + } + + ret = _CVI_EFUSE_Read(CVI_EFUSE_SW_INFO, &value, sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + data = (value & (0x3 << 22)) >> 22; + if (data > 0x1) + return CVI_FAILURE; + + data = (value & (0x3 << 24)) >> 24; + if (data > 0x1) + return CVI_FAILURE; + + data = (value & (0x3 << 26)) >> 26; + if (data > 0x1) + return CVI_FAILURE; + + // set sd dl button + value = (0x1 << 22); + value |= (0x1 << 24); + value |= (0x1 << 26); + + ret = _CVI_EFUSE_Write(CVI_EFUSE_SW_INFO, &value, sizeof(value)); + if (ret < 0) + return ret; + + if (IS_CHIP_PKG_TYPE_QFN(chip)) + value = 0x1E1E64; // AUX0 + else + value = 0x1; // USB_ID + + return _CVI_EFUSE_Write(CVI_EFUSE_CUSTOMER_ADDR, &value, sizeof(value)); +} + +CVI_S32 CVI_EFUSE_IsFastBootEnabled(void) +{ + CVI_U32 value = 0; + CVI_S32 ret = 0; + CVI_U32 chip = 0; + + CVI_SYS_GetChipId(&chip); + if (!IS_CHIP_CV181X(chip) && !IS_CHIP_CV180X(chip)) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "chip id=%d\n", chip); + return CVI_FAILURE; + } + + ret = _CVI_EFUSE_Read(CVI_EFUSE_SW_INFO, &value, sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + if (((value & (0x3 << 22)) != (0x1 << 22)) + && ((value & (0x3 << 24)) != (0x1 << 24)) + && ((value & (0x3 << 26)) != (0x1 << 26))) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "sw_info isn't fastboot config\n"); + return CVI_FAILURE; + } + + ret = _CVI_EFUSE_Read(CVI_EFUSE_CUSTOMER_ADDR, &value, sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + if (IS_CHIP_PKG_TYPE_QFN(chip)) { + if (value == 0x1E1E64) + return CVI_SUCCESS; // AUX0 + else + return CVI_FAILURE; + } else { + if (value == 0x1) + return CVI_SUCCESS; // USB_ID + else + return CVI_FAILURE; + } + + return CVI_FAILURE; +} + +CVI_S32 CVI_EFUSE_Lock(CVI_EFUSE_LOCK_E lock) +{ + CVI_U32 value = 0; + CVI_S32 ret = 0; + + if (lock >= ARRAY_SIZE(cvi_efuse_lock)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock); + return CVI_ERR_SYS_NOMEM; + } + + value = 0x3 << cvi_efuse_lock[lock].wlock_shift; + ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value)); + if (ret < 0) + return ret; + + value = 0x3 << cvi_efuse_lock[lock].rlock_shift; + ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value)); + return ret; +} + +CVI_S32 CVI_EFUSE_IsLocked(CVI_EFUSE_LOCK_E lock) +{ + CVI_S32 ret = 0; + CVI_U32 value = 0; + + if (lock >= ARRAY_SIZE(cvi_efuse_lock)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock); + return CVI_ERR_SYS_NOMEM; + } + + ret = _CVI_EFUSE_Read(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + value &= 0x3 << cvi_efuse_lock[lock].wlock_shift; + return !!value; +} + +CVI_S32 CVI_EFUSE_LockWrite(CVI_EFUSE_LOCK_E lock) +{ + CVI_U32 value = 0; + CVI_S32 ret = 0; + + if (lock >= ARRAY_SIZE(cvi_efuse_lock)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock); + return CVI_ERR_SYS_NOMEM; + } + + value = 0x3 << cvi_efuse_lock[lock].wlock_shift; + ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value)); + return ret; +} + +CVI_S32 CVI_EFUSE_IsWriteLocked(CVI_EFUSE_LOCK_E lock) +{ + CVI_S32 ret = 0; + CVI_U32 value = 0; + + if (lock >= ARRAY_SIZE(cvi_efuse_lock)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock); + return CVI_ERR_SYS_NOMEM; + } + + ret = _CVI_EFUSE_Read(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value)); + CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value); + if (ret < 0) + return ret; + + value &= 0x3 << cvi_efuse_lock[lock].wlock_shift; + return !!value; +} + + diff --git a/middleware/v2/modules/osdc/Makefile b/middleware/v2/modules/osdc/Makefile new file mode 100644 index 000000000..4c9bf3559 --- /dev/null +++ b/middleware/v2/modules/osdc/Makefile @@ -0,0 +1,65 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +CSRCS := $(wildcard $(SDIR)/*.c) +COBJS = $(CSRCS:.c=.o) +CDEPS = $(CSRCS:.c=.d) +CXXSRCS := $(wildcard $(SDIR)/*.cpp) +CXXOBJS = $(CXXSRCS:.cpp=.o) +CXXDEPS = $(CXXSRCS:.cpp=.d) + +TARGET_A = $(MW_LIB)/libosdc.a +TARGET_SO = $(MW_LIB)/libosdc.so + +INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(OSDC_INC) + +EXTRA_CFLAGS = $(INCS) -fpack-struct=8 +EXTRA_CFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\" +EXTRA_CFLAGS += -DSDK_VER=\"$(SDK_VER)\" +ifeq ($(SDK_VER), 32bit) +EXTRA_CFLAGS += -D_FILE_OFFSET_BITS=64 + +endif +EXTRA_CXXFLAGS = $(INCS) -fpack-struct=8 +EXTRA_CXXFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\" +EXTRA_CXXFLAGS += -DSDK_VER=\"$(SDK_VER)\" +ifeq ($(SDK_VER), 32bit) +EXTRA_CXXFLAGS += -D_FILE_OFFSET_BITS=64 +endif + +.PHONY : clean all +all : prepare $(TARGET_A) $(TARGET_SO) + +prepare: + cp include/cmpr_canvas.h $(MW_INC) + cp include/cvi_osdc.h $(MW_INC) + cp include/osd_cmpr.h $(MW_INC) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(SDIR)/%.o: $(SDIR)/%.cpp + @$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(EXTRA_CXXFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(COBJS) $(CXXOBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(COBJS) $(CXXOBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + @echo "$$AR_MRI" | $(AR) -M + +$(TARGET_SO): $(OBJS) $(CXXOBJS) + @$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $(TARGET_SO) --start-group $(COBJS) $(CXXOBJS) $(LIBS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(COBJS) $(CXXOBJS) $(CDEPS) $(CXXDEPS) $(TARGET_A) $(TARGET_SO) + @rm -f $(MW_INC)/cmpr_canvas.h + @rm -f $(MW_INC)/cvi_osdc.h + @rm -f $(MW_INC)/osd_cmpr.h + +-include $(DEPS) diff --git a/middleware/v2/modules/osdc/src/cmpr_canvas.cpp b/middleware/v2/modules/osdc/src/cmpr_canvas.cpp new file mode 100644 index 000000000..f787e80a3 --- /dev/null +++ b/middleware/v2/modules/osdc/src/cmpr_canvas.cpp @@ -0,0 +1,740 @@ +#include "cmpr_canvas.h" + +static bool is_in_range(int x, int begin, int end) +{ + return (x >= begin && x < end); +} + +template T clip(const T &n, const T &lower, const T &upper) +{ + return std::max(lower, std::min(n, upper)); +} + +int count_repeat_pixel(uint8_t *src, int pixel_sz, int pixel_num) +{ + int num = pixel_num - 1; + for (int byte_i = 0; byte_i < pixel_sz; byte_i++) { + uint8_t ref = src[byte_i]; + uint8_t *cur_ptr = &src[byte_i + pixel_sz]; + for (int cnt = 0; cnt < num; cnt++) { + if (ref != (*cur_ptr)) { + num = cnt; + break; + } + cur_ptr += pixel_sz; + } + } + + return num + 1; +} + +int recycle_obj_slices(vector &slice_vec, int end_idx, int x) +{ + auto it = slice_vec.begin(); + int recycle_cnt = 0; + for (int chk_cnt = 0; chk_cnt <= end_idx; chk_cnt++) { + if (x >= (*it).x1) { + it = slice_vec.erase(it); + recycle_cnt++; + } else { + ++it; + } + } + + return recycle_cnt; +} + +void recycle_draw_obj(vector &obj_vec, int y) +{ + for (auto it = obj_vec.begin(); it != obj_vec.end();) { + if (y > (*it)._max_y) { + it = obj_vec.erase(it); + } else { + ++it; + } + } +} + +int obj_project_on_line(vector &obj_vec, vector &slice_vec, + int y, int &next_y, int canvas_width) +{ + for (int obj_i = 0; obj_i < (int)obj_vec.size(); obj_i++) { + DRAW_OBJ &obj_attr = obj_vec[obj_i]; + if (is_in_range(y, obj_attr._min_y, obj_attr._max_y) == false) { + next_y = min(next_y, max(obj_attr._min_y, y + 1)); + continue; + } + if (obj_attr.type == RECT) { + OBJ_SLICE slice; + slice.x0 = obj_attr.rect.x; + slice.x1 = obj_attr.rect.x + obj_attr.rect.width; + slice.obj_id = obj_i; + slice_vec.push_back(slice); + next_y = min(next_y, obj_attr._max_y); + } else if (obj_attr.type == BIT_MAP || + obj_attr.type == CMPR_BIT_MAP) { + OBJ_SLICE slice; + slice.x0 = obj_attr.bitmap.rect.x; + slice.x1 = obj_attr.bitmap.rect.x + + obj_attr.bitmap.rect.width; + slice.obj_id = obj_i; + next_y = min(next_y, obj_attr._max_y); + slice_vec.push_back(slice); + } else if (obj_attr.type == STROKE_RECT) { + int y1 = obj_attr.rect.y + obj_attr.rect.thickness; + int y2 = obj_attr.rect.y + obj_attr.rect.height - + obj_attr.rect.thickness; + if (is_in_range(y, y1, y2)) { + OBJ_SLICE slice0, slice1; + slice0.x0 = obj_attr.rect.x; + slice0.x1 = obj_attr.rect.x + + obj_attr.rect.thickness; + slice1.x1 = + obj_attr.rect.x + obj_attr.rect.width; + slice1.x0 = slice1.x1 - obj_attr.rect.thickness; + slice0.obj_id = obj_i; + slice1.obj_id = obj_i; + slice_vec.push_back(slice0); + slice_vec.push_back(slice1); + next_y = min(next_y, y2); + } else { + OBJ_SLICE slice; + slice.x0 = obj_attr.rect.x; + slice.x1 = + obj_attr.rect.x + obj_attr.rect.width; + slice.obj_id = obj_i; + slice_vec.push_back(slice); + next_y = min( + next_y, + (y > y1) ? + obj_attr.rect.y + + obj_attr.rect.height : + y1); + } + } else if (obj_attr.type == LINE) { + float pt_x0, pt_x1; + if (is_in_range(y, round(obj_attr.line._by[0]), + round(obj_attr.line._by[1]))) { + float delta_x0 = obj_attr.line._mx * + (y - obj_attr.line._by[0]); + pt_x0 = obj_attr.line._bx[0] + delta_x0; + float width = (y - obj_attr.line._by[0]) * + (obj_attr.line.ts_h / + (obj_attr.line._by[1] - + obj_attr.line._by[0])); + pt_x1 = pt_x0 - width; + } else if (is_in_range( + y, round(obj_attr.line._by[1]), + round(obj_attr.line._ey[0] + 1.))) { + float delta_x0 = obj_attr.line._mx * + (y - obj_attr.line._by[0]); + pt_x0 = obj_attr.line._bx[0] + delta_x0; + pt_x1 = pt_x0 - obj_attr.line.ts_h; + } else { + float delta_x0 = obj_attr.line._mx * + (y - obj_attr.line._by[1]); + pt_x0 = obj_attr.line._bx[1] + delta_x0; + float width = (obj_attr.line._ey[1] - y) * + (obj_attr.line.ts_h / + (obj_attr.line._ey[1] - + obj_attr.line._ey[0])); + pt_x1 = pt_x0 + width; + } + OBJ_SLICE slice; + slice.x0 = clip((int)round(min(pt_x0, pt_x1)), 0, canvas_width-1); + slice.x1 = clip((int)round(max(pt_x0, pt_x1)), 0, canvas_width-1); + slice.obj_id = obj_i; + slice_vec.push_back(slice); + next_y = y + 1; + } + } + + return slice_vec.size(); +} + +void draw_cmpr_init(Cmpr_Canvas_Ctrl &ctrl, uint8_t *obuf, int buf_size, + Canvas_Attr *canvas) +{ + bool trial_enc = (obuf == nullptr) || (buf_size == 0); + OSDCmpr_Ctrl *osdCmpr_ctrl = &ctrl.osdCmpr_ctrl; + //memset(osdCmpr_ctrl, 0, sizeof(OSDCmpr_Ctrl)); + *osdCmpr_ctrl = {}; + osdCmpr_ctrl->reg_image_width = canvas->width; + osdCmpr_ctrl->reg_image_height = canvas->height; + osdCmpr_ctrl->reg_palette_mode_en = OSDEC_PAL_BD > 0; + osdCmpr_ctrl->reg_palette_idx_bd = OSDEC_PAL_BD; + osdCmpr_ctrl->reg_run_len_bd = OSDEC_RL_BD; + osdCmpr_ctrl->reg_osd_format = canvas->format; + osdCmpr_ctrl->pel_sz = osd_cmpr_get_pixel_sz(canvas->format); + osd_cmpr_frame_init(&ctrl.osdCmpr_ctrl); + int hdr_sz; + if (trial_enc) { + buf_size = 0; + hdr_sz = 0; + } else { + osd_cmpr_enc_header(obuf, osdCmpr_ctrl); + hdr_sz = osd_cmpr_get_header_sz(); + } + init_stream(&ctrl.bitstream, &obuf[hdr_sz], buf_size - hdr_sz, + trial_enc); + ctrl.md = NUM_OF_MODE; // must be invalid type to bypass the first run + ctrl.rl_cnt = -1; +} + +void draw_cmpr_finish(Cmpr_Canvas_Ctrl &ctrl) +{ + int dummy = 0; + RGBA dummy_c; + osd_cmpr_enc_const_pixel(dummy_c, ctrl.last_color, ctrl.rl_cnt, ctrl.md, + ctrl.code, dummy, true, OSDEC_MAX_RL, + &ctrl.osdCmpr_ctrl, &ctrl.bitstream); +} + +void draw_cmpr_pixel(uint8_t *color_code_ptr, int length, bool is_first_pel, + Cmpr_Canvas_Ctrl &ctrl) +{ + RGBA cur_c = + get_color(color_code_ptr, ctrl.osdCmpr_ctrl.reg_osd_format); + osd_cmpr_enc_const_pixel(cur_c, ctrl.last_color, ctrl.rl_cnt, ctrl.md, + ctrl.code, length, is_first_pel, OSDEC_MAX_RL, + &ctrl.osdCmpr_ctrl, &ctrl.bitstream); + while (length > 0) { + osd_cmpr_enc_followed_run(cur_c, ctrl.rl_cnt, ctrl.md, + ctrl.code, length, OSDEC_MAX_RL, + &ctrl.osdCmpr_ctrl, &ctrl.bitstream); + } +} + +void draw_cmpr_canvas_line(Cmpr_Canvas_Ctrl &ctrl, vector &obj_vec, + int y, int pixel_sz, vector &segment_vec) +{ + for (int seg_i = 0; seg_i < (int)segment_vec.size(); seg_i++) { + SEGMENT &segment = segment_vec[seg_i]; + if (segment.is_const) { + if(segment.width>0) { + draw_cmpr_pixel((uint8_t *)&segment.color.code, + segment.width, y == 0 && seg_i == 0, + ctrl); + } + } else { + int rep_cnt; + uint8_t *src_ptr = segment.color.buf; + if (segment.is_cmpr) { + int pel_cnt = 0; + while (pel_cnt < segment.width) { + rep_cnt = min(src_ptr[0] + 1, + segment.width - pel_cnt); + uint8_t *cur_ptr = &src_ptr[1]; + draw_cmpr_pixel(cur_ptr, rep_cnt, + y == 0 && seg_i == 0 && + pel_cnt == 0, + ctrl); + src_ptr += (1 + pixel_sz); + pel_cnt += rep_cnt; + } + segment.color.buf += *(segment.bs_len); + obj_vec[segment.id].bitmap.bs_offset += + *(segment.bs_len); + segment.bs_len++; + } else { + for (int pel_i = 0; pel_i < segment.width; + pel_i += rep_cnt) { + uint8_t *cur_ptr = + &src_ptr[pel_i * pixel_sz]; + rep_cnt = count_repeat_pixel( + cur_ptr, pixel_sz, + segment.width - pel_i); + draw_cmpr_pixel(cur_ptr, rep_cnt, + y == 0 && seg_i == 0 && + pel_i == 0, + ctrl); + } + segment.color.buf += + (segment.stride * pixel_sz); + } + } + } +} + +void plot_segments_on_line(vector &obj_vec, int width, int y, + int pixel_sz, int &next_y, + vector &segment_vec, uint32_t bg_color_code) +{ + vector slice_vec; + if (obj_project_on_line(obj_vec, slice_vec, y, next_y, width) == 0) { + SEGMENT bg_seg{ true, false, (uint16_t)width, 0, bg_color_code, 0 }; + segment_vec.push_back(bg_seg); + return; + } + int step; + int next_slice_idx = -1; + for (int x = 0; x < width; x += step) { + int obj_idx = -1; // "-1": background + int x0 = x; + int x1 = width; + int slices_num = slice_vec.size(); + if (next_slice_idx >= 0) { + x0 = slice_vec[next_slice_idx].x0; + x1 = slice_vec[next_slice_idx].x1; + obj_idx = next_slice_idx; + } else { + // iter all slices + for (int idx = (slices_num - 1); idx >= 0; idx--) { + if (is_in_range(x, slice_vec[idx].x0, + slice_vec[idx].x1)) { + x0 = slice_vec[idx].x0; + x1 = slice_vec[idx].x1; + obj_idx = idx; + break; + } + } + } + // find end point from higher priority slices + next_slice_idx = -1; + int end_x = x1; + for (int hp_slice_i = (slices_num - 1); hp_slice_i > obj_idx; + hp_slice_i--) { + if (is_in_range(slice_vec[hp_slice_i].x0, x0, end_x)) { + end_x = slice_vec[hp_slice_i].x0; + next_slice_idx = hp_slice_i; + } + } + step = end_x - x; + + SEGMENT segment{ true, false, (uint16_t)width, 0, bg_color_code, 0 }; + segment.width = step; + if (obj_idx >= 0) { + DRAW_OBJ &obj = obj_vec[slice_vec[obj_idx].obj_id]; + segment.is_const = (obj.type == BIT_MAP || + obj.type == CMPR_BIT_MAP) ? + false : + true; + if (segment.is_const) { + segment.color.code = obj.color.code; + } else { + segment.is_cmpr = + (obj.type == BIT_MAP) ? false : true; + int incr_y = y - obj.bitmap.rect.y; + if (!segment.is_cmpr) { + segment.stride = obj.bitmap.stride; + segment.color.buf = + obj.color.buf + + ((incr_y * segment.stride) + + (x - slice_vec[obj_idx].x0)) * + pixel_sz; + } else { + segment.color.buf = + &obj.color.buf + [obj.bitmap.bs_offset]; + segment.bs_len = &( + (uint16_t *) + obj.color.buf)[incr_y]; + segment.id = slice_vec[obj_idx].obj_id; + } + } + // slices required recycle only when current segment is not background + int recycle_cnt = recycle_obj_slices(slice_vec, obj_idx, + x + step); + // correct next slice index due to recycled slices + next_slice_idx -= recycle_cnt; + } + segment_vec.push_back(segment); + } // end of draw a part of a slice +} + +// ---------------------- cmpr_canvas main API ---------------------- +int draw_cmpr_canvas(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num, + uint8_t *obuf, int buf_size, uint32_t* p_osize) +{ + vector obj_vec(objs, objs+obj_num); + Cmpr_Canvas_Ctrl ctrl; + draw_cmpr_init(ctrl, obuf, buf_size, canvas); + size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas->format); + int y_step; + for (int y = 0; y < canvas->height; y += y_step) { + int next_y = canvas->height; + vector segment_vec; + plot_segments_on_line(obj_vec, canvas->width, y, pixel_sz, + next_y, segment_vec, canvas->bg_color_code); + y_step = next_y - y; + for (int line_i = 0; line_i < y_step; line_i++) { + draw_cmpr_canvas_line(ctrl, obj_vec, y + line_i, + pixel_sz, segment_vec); + } + recycle_draw_obj(obj_vec, y + y_step - 1); + } + draw_cmpr_finish(ctrl); + uint32_t stream_sz = (ctrl.bitstream.bit_pos + 7) >> 3; // in byte + //add 16 bytes per DE's suggestion + *p_osize = (((stream_sz + osd_cmpr_get_header_sz() + 15) >> 4) + 1) << 4; // 16byte align + return ctrl.bitstream.status; +} + +#if (CMPR_CANVAS_DBG) +void fill_n_pixel(void *dest, int width, int code, int pixel_sz) +{ + if (pixel_sz == 4) { + fill_n((uint32_t *)dest, width, code); + } else if (pixel_sz == 2) { + fill_n((uint16_t *)dest, width, (uint16_t)code); + } else { + fill_n((uint8_t *)dest, width, (uint8_t)code); + } +} + +int draw_canvas_raw_buffer2(Canvas_Attr &canvas, vector obj_vec, + uint8_t *obuf) +{ + size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas.format); + //memset(obuf, 0, canvas.height*canvas.width*pixel_sz); + for (int obj_i = 0; obj_i < obj_vec.size(); obj_i++) { + DRAW_OBJ &obj_attr = obj_vec[obj_i]; + if (obj_attr.type == STROKE_RECT) { + uint8_t *dest_ptr; + for (int y = obj_attr.rect.y; + y < (obj_attr.rect.y + obj_attr.rect.thickness); + y++) { + uint8_t *dest_ptr = &obuf[(y * canvas.width + + obj_attr.rect.x) * + pixel_sz]; + fill_n_pixel(dest_ptr, obj_attr.rect.width, + obj_attr.color.code, pixel_sz); + } + int y2 = obj_attr.rect.y + obj_attr.rect.height - + obj_attr.rect.thickness; + for (int y = y2; + y < (obj_attr.rect.y + obj_attr.rect.height); + y++) { + uint8_t *dest_ptr = &obuf[(y * canvas.width + + obj_attr.rect.x) * + pixel_sz]; + fill_n_pixel(dest_ptr, obj_attr.rect.width, + obj_attr.color.code, pixel_sz); + } + dest_ptr = &obuf[(obj_attr.rect.y * canvas.width + + obj_attr.rect.x) * + pixel_sz]; + for (int y = obj_attr.rect.y; + y < (obj_attr.rect.y + obj_attr.rect.height); + y++) { + fill_n_pixel(dest_ptr, obj_attr.rect.thickness, + obj_attr.color.code, pixel_sz); + dest_ptr += (canvas.width * pixel_sz); + } + int x2 = obj_attr.rect.x + obj_attr.rect.width - + obj_attr.rect.thickness; + dest_ptr = &obuf[(obj_attr.rect.y * canvas.width + x2) * + pixel_sz]; + for (int y = obj_attr.rect.y; + y < (obj_attr.rect.y + obj_attr.rect.height); + y++) { + fill_n_pixel(dest_ptr, obj_attr.rect.thickness, + obj_attr.color.code, pixel_sz); + dest_ptr += (canvas.width * pixel_sz); + } + } else if (obj_attr.type == RECT) { + uint8_t *dest_ptr = + &obuf[(obj_attr.rect.y * canvas.width + + obj_attr.rect.x) * + pixel_sz]; + for (int y = 0; y < obj_attr.rect.height; y++) { + fill_n_pixel(dest_ptr, obj_attr.rect.width, + obj_attr.color.code, pixel_sz); + dest_ptr += (canvas.width * pixel_sz); + } + } else if (obj_attr.type == BIT_MAP) { + uint8_t *dest_ptr = + &obuf[(obj_attr.bitmap.rect.y * canvas.width + + obj_attr.bitmap.rect.x) * + pixel_sz]; + uint8_t *src_ptr = obj_attr.color.buf; + for (int y = 0; y < obj_attr.rect.height; y++) { + memcpy(dest_ptr, src_ptr, + obj_attr.rect.width * pixel_sz); + dest_ptr += (canvas.width * pixel_sz); + src_ptr += + (obj_attr.bitmap.rect.width * pixel_sz); + } + } + } +} + +void draw_canvas_raw_line(uint8_t *obuf, Canvas_Attr &canvas, + vector &obj_vec, int y, int pixel_sz, + vector &segment_vec) +{ + uint8_t *dest_ptr = obuf + (y * canvas.width * pixel_sz); + for (int seg_i = 0; seg_i < segment_vec.size(); seg_i++) { + SEGMENT &segment = segment_vec[seg_i]; + if (segment.is_const && segment.color.code != 0) { + fill_n_pixel(dest_ptr, segment.width, + segment.color.code, pixel_sz); + } else if (!segment.is_const) { + int rep_cnt; + uint8_t *src_ptr = segment.color.buf; + if (segment.is_cmpr) { + int pel_cnt = 0; + while (pel_cnt < segment.width) { + rep_cnt = min(src_ptr[0] + 1, + segment.width - pel_cnt); + fill_n_pixel( + &dest_ptr[pel_cnt * pixel_sz], + rep_cnt, + *((uint32_t *)&src_ptr[1]), + pixel_sz); + src_ptr += (1 + pixel_sz); + pel_cnt += rep_cnt; + } + segment.color.buf += *(segment.bs_len); + obj_vec[segment.id].bitmap.bs_offset += + *(segment.bs_len); + segment.bs_len++; + } else { + memcpy(dest_ptr, src_ptr, + segment.width * pixel_sz); + segment.color.buf += + (segment.stride * pixel_sz); + } + } + dest_ptr += (segment.width * pixel_sz); + } +} + +int draw_canvas_raw_buffer(Canvas_Attr &canvas, vector obj_vec, + uint8_t *obuf) +{ + size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas.format); + memset(obuf, 0, canvas.height * canvas.width * pixel_sz); + int y_step; + for (int y = 0; y < canvas.height; y += y_step) { + int next_y = canvas.height; + vector segment_vec; + plot_segments_on_line(obj_vec, canvas.width, canvas.height, y, + pixel_sz, next_y, segment_vec, canvas->bg_color_code); + y_step = next_y - y; + for (int line_i = 0; line_i < y_step; line_i++) { + draw_canvas_raw_line(obuf, canvas, obj_vec, y + line_i, + pixel_sz, segment_vec); + } + recycle_draw_obj(obj_vec, y + y_step - 1); + } + + return 1; +} +#endif + +int cmpr_bitmap(Canvas_Attr *canvas, uint8_t *ibuf, uint8_t *obuf, int width, + int height, int buf_size, uint32_t* p_osize) +{ + size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas->format); + memset(obuf, 0, buf_size); + uint8_t *cur_ptr = ibuf; + uint16_t *meta_ptr = (uint16_t *)obuf; + size_t meta_sz = height << 1; + uint8_t *bs_ptr = &obuf[meta_sz]; + size_t bs_sz_cnt = meta_sz; + int rl_pair_sz = (1 + pixel_sz); + int step; + for (int y = 0; y < height; y++) { + int line_byte_cnt = 0; + for (int x = 0; x < width; x += step) { + int cnt = count_repeat_pixel(cur_ptr, pixel_sz, + width - x); + step = cnt; + while (cnt > 0) { + int new_bs_sz_cnt = bs_sz_cnt + rl_pair_sz; + if (new_bs_sz_cnt > buf_size) { + return -1; + } + int rl = min(cnt, 256); + *bs_ptr = (rl - 1); + memcpy(&bs_ptr[1], cur_ptr, pixel_sz); + bs_ptr += rl_pair_sz; + cnt -= rl; + bs_sz_cnt = new_bs_sz_cnt; + line_byte_cnt += rl_pair_sz; + } + cur_ptr += (step * pixel_sz); + } + meta_ptr[y] = line_byte_cnt; + } + *p_osize = bs_sz_cnt; + + return 1; +} + +uint32_t est_cmpr_canvas_size(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num) +{ + uint8_t *dummy = nullptr; + uint32_t bs_sz = 0; + draw_cmpr_canvas(canvas, objs, obj_num, dummy, 0, &bs_sz); + + return ((bs_sz + BUF_GUARD_SIZE) >> 4) << 4; +} + +void set_rect_position(RECT_ATTR &rect, Canvas_Attr *canvas, int pt_x, int pt_y, + int width, int height) +{ + rect.x = clip(pt_x, 0, canvas->width - 1); + rect.y = clip(pt_y, 0, canvas->height -1); + rect.width = clip(width, 0, canvas->width - rect.x); + rect.height = clip(height, 0, canvas->height - rect.y); +} + +void set_rect_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas, + uint32_t color_code, int pt_x, int pt_y, int width, + int height, bool is_filled, int thickness) +{ + obj_attr->type = (is_filled) ? RECT : STROKE_RECT; + obj_attr->color.code = color_code; + set_rect_position(obj_attr->rect, canvas, pt_x, pt_y, width, height); + thickness = clip(thickness, MIN_THICKNESS, MAX_THICKNESS); + int min_allow_thickness = max((min(obj_attr->rect.height, obj_attr->rect.width)>>1)-1, 0); + obj_attr->rect.thickness = min(min_allow_thickness, thickness); + obj_attr->_max_y = obj_attr->rect.y + obj_attr->rect.height; + obj_attr->_min_y = obj_attr->rect.y; +} + +void set_bitmap_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas, uint8_t *buf, + int pt_x, int pt_y, int width, int height, + bool is_cmpr) +{ + if (is_cmpr) { + obj_attr->type = CMPR_BIT_MAP; + obj_attr->bitmap.bs_offset = height + << 1; // 2B metadata for each line + } else { + obj_attr->type = BIT_MAP; + obj_attr->bitmap.stride = width; + } + set_rect_position(obj_attr->bitmap.rect, canvas, pt_x, pt_y, width, + height); + obj_attr->color.buf = buf; + obj_attr->_max_y = obj_attr->bitmap.rect.y + obj_attr->bitmap.rect.height; + obj_attr->_min_y = obj_attr->bitmap.rect.y; +} + +void set_line_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas, + uint32_t color_code, int pt_x0, int pt_y0, int pt_x1, + int pt_y1, int thickness) +{ + obj_attr->color.code = color_code; + pt_x0 = clip(pt_x0, 0, canvas->width); + pt_x1 = clip(pt_x1, 0, canvas->width); + pt_y0 = clip(pt_y0, 0, canvas->height); + pt_y1 = clip(pt_y1, 0, canvas->height); + thickness = clip(thickness, MIN_THICKNESS, MAX_THICKNESS); + if (pt_x0 == pt_x1 || + pt_y0 == pt_y1) { // horizontal line: degenerate to rect + int x = min(pt_x0, pt_x1) - (thickness >> 1); + int y = min(pt_y0, pt_y1) - (thickness >> 1); + int width = thickness + + ((pt_x0 == pt_x1) ? + 0 : + max(pt_x0, pt_x1) - min(pt_x0, pt_x1)); + int height = thickness + + ((pt_y0 == pt_y1) ? + 0 : + max(pt_y0, pt_y1) - min(pt_y0, pt_y1)); + set_rect_obj_attr(obj_attr, canvas, color_code, x, y, width, + height, true, thickness); + } else { + obj_attr->color.code = color_code; + obj_attr->type = LINE; + int x[2], y[2]; + bool is_y_incr = (pt_y1 > pt_y0); + x[0] = (is_y_incr) ? pt_x0 : pt_x1; + y[0] = (is_y_incr) ? pt_y0 : pt_y1; + x[1] = (is_y_incr) ? pt_x1 : pt_x0; + y[1] = (is_y_incr) ? pt_y1 : pt_y0; + int dx = x[1] - x[0]; + int dy = y[1] - y[0]; + obj_attr->line._mx = (dy != 0) ? dx / ((float)dy) : + FLT_MAX; + float thick_offset = + 0.5 * thickness / pow(dx * dx + dy * dy, 0.5); + float thick_offset_x = thick_offset * dx; + float thick_offset_y = thick_offset * dy; + for (int side_i = 0; side_i < 2; side_i++) { + obj_attr->line._bx[side_i] = + clip(x[0] + ((dx >= 0) ? thick_offset_y : + (-thick_offset_y)), + (float)0., (float)canvas->width); + obj_attr->line._by[side_i] = + clip(y[0] + ((dx >= 0) ? (-thick_offset_x) : + thick_offset_x), + (float)0., (float)canvas->height); + obj_attr->line._ex[side_i] = + clip(x[1] + ((dx >= 0) ? thick_offset_y : + (-thick_offset_y)), + (float)0., (float)canvas->width); + obj_attr->line._ey[side_i] = + clip(y[1] + ((dx >= 0) ? (-thick_offset_x) : + thick_offset_x), + (float)0., (float)canvas->height); + thick_offset_x = -thick_offset_x; + thick_offset_y = -thick_offset_y; + } + obj_attr->line.ts_h = + (obj_attr->line._bx[0] + + obj_attr->line._mx * (obj_attr->line._by[1] - + obj_attr->line._by[0])) - + obj_attr->line._bx[1]; + obj_attr->_min_y = + round(min(obj_attr->line._by[0], obj_attr->line._by[1])); + obj_attr->_max_y = + round(max(obj_attr->line._ey[1], obj_attr->line._ey[1])); + } +} + +//============================================================================================== +//CVI interface +#ifdef __cplusplus +extern "C" +{ +#endif + +uint32_t CVI_OSDC_est_cmpr_canvas_size(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num) +{ + return est_cmpr_canvas_size(canvas, objs, obj_num); +} + +int CVI_OSDC_draw_cmpr_canvas(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num, + uint8_t *obuf, uint32_t buf_size, uint32_t *p_osize) +{ + return draw_cmpr_canvas(canvas, objs, obj_num, obuf, buf_size, p_osize); +} + +void CVI_OSDC_set_rect_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj, uint32_t color_code, int pt_x, int pt_y, int width, + int height, bool is_filled, int thickness) +{ + set_rect_obj_attr(obj, canvas, color_code, pt_x, pt_y, width, height, is_filled, thickness); + +} + +void CVI_OSDC_set_bitmap_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj_attr, uint8_t *buf, + int pt_x, int pt_y, int width, int height, bool is_cmpr) +{ + set_bitmap_obj_attr(obj_attr, canvas, buf, pt_x, pt_y, width, height, is_cmpr); +} + +void CVI_OSDC_set_line_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj, uint32_t color_code, + int pt_x0, int pt_y0, int pt_x1, int pt_y1, int thickness) +{ + set_line_obj_attr(obj, canvas, color_code, pt_x0, pt_y0, pt_x1, pt_y1, thickness); +} + +int CVI_OSDC_cmpr_bitmap(Canvas_Attr *canvas, uint8_t *ibuf, uint8_t *obuf, int width, int height, + int buf_size, uint32_t *p_osize) +{ + return cmpr_bitmap(canvas, ibuf, obuf, width, height, buf_size, p_osize); +} + +#if (CMPR_CANVAS_DBG) +int CVI_OSDC_draw_canvas_raw_buffer(Canvas_Attr &canvas, vector obj_vec, uint8_t *obuf) +int CVI_OSDC_draw_canvas_raw_buffer2(Canvas_Attr &canvas, vector obj_vec, uint8_t *obuf); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/middleware/v2/modules/osdc/src/cvi_osdc.c b/middleware/v2/modules/osdc/src/cvi_osdc.c new file mode 100644 index 000000000..51f98fa54 --- /dev/null +++ b/middleware/v2/modules/osdc/src/cvi_osdc.c @@ -0,0 +1,93 @@ +#include +#include +#include + +uint32_t CVI_OSDC_EstCmprCanvasSize(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *objs, uint32_t obj_num) +{ + return CVI_OSDC_est_cmpr_canvas_size(canvas, objs, obj_num); +} + +int CVI_OSDC_DrawCmprCanvas(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *objs, uint32_t obj_num, + uint8_t *obuf, uint32_t buf_size, uint32_t *p_osize) +{ + return CVI_OSDC_draw_cmpr_canvas(canvas, objs, obj_num, obuf, buf_size, p_osize); +} + +void CVI_OSDC_SetRectObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code, + int pt_x, int pt_y, int width, int height, bool is_filled, int thickness) +{ + CVI_OSDC_set_rect_obj_attr(canvas, obj, color_code, pt_x, pt_y, width, height, is_filled, thickness); + +} + +void CVI_OSDC_SetRectObjAttrEx(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code, + OSDC_RECT_ATTR_S *rects, int num, bool is_filled) +{ + int i = 0; + + for (i = 0; i < num; i++) { + CVI_OSDC_set_rect_obj_attr(canvas, obj, color_code, rects[i].x, rects[i].y, + rects[i].width, rects[i].height, is_filled, rects[i].thickness); + } + +} + +void CVI_OSDC_SetBitmapObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj_attr, uint8_t *buf, + int pt_x, int pt_y, int width, int height, bool is_cmpr) +{ + CVI_OSDC_set_bitmap_obj_attr(canvas, obj_attr, buf, pt_x, pt_y, width, height, is_cmpr); +} + +void CVI_OSDC_SetLineObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code, + int pt_x0, int pt_y0, int pt_x1, int pt_y1, int thickness) +{ + CVI_OSDC_set_line_obj_attr(canvas, obj, color_code, pt_x0, pt_y0, pt_x1, pt_y1, thickness); +} + +void CVI_OSDC_SetLineObjAttrEx(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code, + OSDC_POINT_ATTR_S *points, int num, int thickness) +{ + int i = 0, j = 0, delta_x, delta_y; + OSDC_POINT_ATTR_S *tmp = malloc(sizeof(OSDC_POINT_ATTR_S) * num); + + if (!tmp) + return; + + memcpy(tmp, points, sizeof(OSDC_POINT_ATTR_S) * num); + while (j++ < 5) { + for (i = 0; i < num - 1; ++i) { + delta_x = abs(tmp[i].x - tmp[i + 1].x); + delta_y = abs(tmp[i].y - tmp[i + 1].y); + if (delta_y < thickness) + tmp[i + 1].y = tmp[i].y; + if (delta_x < thickness) + tmp[i + 1].x = tmp[i].x; + } + delta_x = abs(tmp[num - 1].x - tmp[0].x); + delta_y = abs(tmp[num - 1].y - tmp[0].y); + if (delta_y < thickness) + tmp[0].y = tmp[num - 1].y; + if (delta_x < thickness) + tmp[0].x = tmp[num - 1].x; + delta_x = abs(tmp[1].x - tmp[0].x); + delta_y = abs(tmp[1].y - tmp[0].y); + if ((delta_x > thickness || delta_x == 0) && + (delta_y > thickness || delta_y == 0)) + break; + } + + for (i = 0; i < num - 1; ++i) { + CVI_OSDC_set_line_obj_attr(canvas, obj + i, color_code, tmp[i].x, tmp[i].y, + tmp[i + 1].x, tmp[i + 1].y, thickness); + } + + CVI_OSDC_set_line_obj_attr(canvas, obj + num - 1, color_code, tmp[num - 1].x, tmp[num - 1].y, + tmp[0].x, tmp[0].y, thickness); + free(tmp); +} + +int CVI_OSDC_CmprBitmap(OSDC_Canvas_Attr_S *canvas, uint8_t *ibuf, uint8_t *obuf, int width, int height, + int buf_size, uint32_t *p_osize) +{ + return CVI_OSDC_cmpr_bitmap(canvas, ibuf, obuf, width, height, buf_size, p_osize); +} diff --git a/middleware/v2/modules/osdc/src/osd_cmpr.cpp b/middleware/v2/modules/osdc/src/osd_cmpr.cpp new file mode 100644 index 000000000..189e0ae1e --- /dev/null +++ b/middleware/v2/modules/osdc/src/osd_cmpr.cpp @@ -0,0 +1,601 @@ +#include +#include +#include +#include "osd_cmpr.h" + +// -- arithmetic operation -- +uint8_t get_bit_val(uint8_t *buf, int byte_idx, int bit_idx) +{ + return (buf[byte_idx] >> bit_idx) & 0x1; +} + +int min(int data1, int data2) +{ + return (data1 <= data2) ? data1 : data2; +} + +int max(int data1, int data2) +{ + return (data1 >= data2) ? data1 : data2; +} + +int clip(int data, int min, int max) +{ + return (data > max) ? max : (data < min) ? min : data; +} + +// -- streaming operation handler -- +void init_stream(StreamBuffer *bs, const uint8_t *buf, int buf_size, + bool read_only) +{ + bs->bit_pos = 0; + bs->stream = (uint8_t *)buf; + bs->buf_size = buf_size; + bs->status = 1; + if (!read_only) + memset((uint8_t *)buf, 0, sizeof(uint8_t) * buf_size); +} + +void write_multibits(uint8_t *stream, uint8_t *src, int bit_pos, int bit_len) +{ + assert(bit_len <= 8); + int dest_bit_i = bit_pos & 7; + int dest_byte_i = bit_pos >> 3; + uint16_t *dest_ptr_ex = (uint16_t *)&stream[dest_byte_i]; + uint16_t src_data_ex = (*src) << dest_bit_i; + (*dest_ptr_ex) = (*dest_ptr_ex) | src_data_ex; +} + +void write_stream(StreamBuffer *bs, uint8_t *src, int bit_len) +{ + int next_bit_pos = bs->bit_pos + bit_len; + if (next_bit_pos < (bs->buf_size << 3)) { + while (bit_len >= 8) { + write_multibits(bs->stream, src, bs->bit_pos, 8); + bs->bit_pos += 8; + bit_len -= 8; + src++; + }; + if (bit_len > 0) { + write_multibits(bs->stream, src, bs->bit_pos, bit_len); + } + } else { + bs->status = -1; + } + bs->bit_pos = next_bit_pos; +} + +void move_stream_ptr(StreamBuffer *bs, int bit_len) +{ + bs->bit_pos = min(bs->bit_pos + bit_len, (bs->buf_size << 3)); +} + +void parse_stream(StreamBuffer *bs, uint8_t *dest, int bit_len, bool read_only) +{ + memset(dest, 0, sizeof(uint8_t) * (bit_len + 7) >> 3); + for (int bit = 0; bit < bit_len; bit++) { + int dest_byte_i = bit / 8; + int dest_bit_i = bit % 8; + int bs_byte_i = (bs->bit_pos + bit) / 8; + int bs_bit_i = (bs->bit_pos + bit) % 8; + dest[dest_byte_i] |= + (get_bit_val(bs->stream, bs_byte_i, bs_bit_i) + << dest_bit_i); + } + bs->bit_pos = (read_only) ? + bs->bit_pos : + min(bs->bit_pos + bit_len, (bs->buf_size << 3)); +} + +// ------ ARGB format generic function ------ + +// tranform generic ARGB8888 into multiple pixel format +void set_color(uint8_t *ptr, RGBA color, OSD_FORMAT format) +{ + if (format == OSD_ARGB8888) { + memcpy(ptr, &color, sizeof(RGBA)); + } else if (format == OSD_ARGB1555) { + ARGB1555 out_c; + CPY_C(color, out_c) + memcpy(ptr, &out_c.code, sizeof(out_c.code)); + } else if (format == OSD_ARGB4444) { + ARGB4444 out_c; + CPY_C(color, out_c) + memcpy(ptr, &out_c.code, sizeof(out_c.code)); + } else if (format == OSD_LUT8 || format == OSD_LUT4) { + *ptr = color.a; + } +} + +// tranform multiple pixel format into generic ARGB8888 +RGBA get_color(uint8_t *ptr, OSD_FORMAT format) +{ + RGBA out_c; + out_c.code = 0; + if (format == OSD_ARGB8888) { + RGBA in_c = *((RGBA *)ptr); + CPY_C(in_c, out_c) + } else if (format == OSD_ARGB1555) { + ARGB1555 in_c = *((ARGB1555 *)ptr); + CPY_C(in_c, out_c) + } else if (format == OSD_ARGB4444) { + ARGB4444 in_c = *((ARGB4444 *)ptr); + CPY_C(in_c, out_c) + } else if (format == OSD_LUT8 || format == OSD_LUT4) { + out_c.a = *ptr; + } + + return out_c; +} + +bool is_equal_color(RGBA c0, RGBA c1) +{ + return c0.code == c1.code; +} + +// ------ palette_cache ------ +void palette_cache_init(vector &cache, int cache_sz) +{ + int c_incr = 256 / cache_sz; + uint8_t c = 0; + for (int idx = 0; idx < cache_sz; idx++) { + uint32_t code = (c << 24) | (c << 16) | (c << 8) | c; + RGBA color = get_color((uint8_t *)&code); + cache.push_back(color); + c = clip(c + c_incr, 0, 255); + } +} + +int palette_cache_lookup_color(vector &cache, RGBA color) +{ + for (unsigned int idx = 0; idx < cache.size(); idx++) { + if (is_equal_color(cache[idx], color)) { // hit + palette_cache_lru_update(cache, idx); + return idx; + } + } + // miss + palette_cache_push_color(cache, color); + + return -1; +} + +void palette_cache_lru_update(vector &cache, int index) +{ + if (index == 0) + return; + RGBA reg_color = cache[index]; + for (int idx = index; idx > 0; idx--) { + cache[idx] = cache[idx - 1]; + } + cache[0] = reg_color; +} + +void palette_cache_push_color(vector &cache, RGBA color) +{ + for (int idx = cache.size() - 1; idx > 0; idx--) { + cache[idx] = cache[idx - 1]; + } + cache[0] = color; +} + +// ------ syntax enc/dec ------ +void enc_literal(StreamBuffer *bs, RGBA color, OSD_FORMAT format) +{ + if (format == OSD_ARGB8888) { + write_stream(bs, (uint8_t *)(&color), sizeof(RGBA) << 3); + } else if (format == OSD_ARGB1555) { + ARGB1555 out_c; + CPY_C(color, out_c) + write_stream(bs, (uint8_t *)(&out_c.code), + sizeof(out_c.code) << 3); + } else if (format == OSD_ARGB4444) { + ARGB4444 out_c; + CPY_C(color, out_c) + write_stream(bs, (uint8_t *)(&out_c.code), + sizeof(out_c.code) << 3); + } else if (format == OSD_LUT8) { + write_stream(bs, (uint8_t *)(&color.a), 8); + } else if (format == OSD_LUT4) { + write_stream(bs, (uint8_t *)(&color.a), 4); + } +} + +RGBA dec_literal(StreamBuffer *bs, OSD_FORMAT format) +{ + RGBA color; + color.code = 0; + if (format == OSD_ARGB8888) { + parse_stream(bs, (uint8_t *)&color, sizeof(RGBA) * 8, false); + } else if (format == OSD_ARGB1555) { + ARGB1555 in_c; + parse_stream(bs, (uint8_t *)&in_c.code, sizeof(in_c.code) * 8, + false); + CPY_C(in_c, color) + } else if (format == OSD_ARGB4444) { + ARGB4444 in_c; + parse_stream(bs, (uint8_t *)&in_c.code, sizeof(in_c.code) * 8, + false); + CPY_C(in_c, color) + } else if (format == OSD_LUT8) { + parse_stream(bs, &color.a, 8, false); + } else if (format == OSD_LUT4) { + parse_stream(bs, &color.a, 4, false); + } + + return color; +} + +void enc_run_length(StreamBuffer *bs, int run_len, int run_len_bd) +{ + if (run_len > 1) { + uint8_t run_syntax = run_len - 1; + write_stream(bs, &run_syntax, run_len_bd); + } +} + +void enc_mode_syntax(StreamBuffer *bs, MODE_TYPE md, int run_len, CODE code, + OSDCmpr_Ctrl *p_ctrl) +{ + if (p_ctrl->reg_palette_mode_en) { + uint16_t _syntax; + if (md == Palette) { + if (run_len > 1) { + _syntax = (code.palette_idx + << (p_ctrl->reg_run_len_bd + 3)) | + ((run_len - 1) << 3); + write_stream( + bs, (uint8_t *)&_syntax, + 3 + p_ctrl->reg_run_len_bd + + p_ctrl->reg_palette_idx_bd); + } else { + _syntax = (code.palette_idx << 2) | 2; + write_stream(bs, (uint8_t *)&_syntax, + p_ctrl->reg_palette_idx_bd + 2); + } + } else if (md == Literal) { + if (run_len > 1) { + uint16_t _syntax = ((run_len - 1) << 3) | 4; + write_stream(bs, (uint8_t *)&_syntax, + 3 + p_ctrl->reg_run_len_bd); + } else { + uint8_t lit_prefix = 1; + write_stream(bs, &lit_prefix, 1); + } + enc_literal(bs, code.color, p_ctrl->reg_osd_format); + } + } else { + uint8_t prefix = (run_len > 1) ? 0 : 1; + write_stream(bs, &prefix, 1); + enc_run_length(bs, run_len, p_ctrl->reg_run_len_bd); + enc_literal(bs, code.color, p_ctrl->reg_osd_format); + } +} + +MODE_TYPE dec_mode_prefix(StreamBuffer *bs, bool palette_mode_en) +{ + uint8_t prefix; + if (palette_mode_en) { + parse_stream(bs, &prefix, 3, true); + if (prefix == 0) { + move_stream_ptr(bs, 3); + return Palette_RL; + } else if (prefix == 4) { + move_stream_ptr(bs, 3); + return Literal_RL; + } else if ((prefix & 0x3) == 2) { + move_stream_ptr(bs, 2); + return Palette; + } + assert((prefix & 0x1) == 1); + move_stream_ptr(bs, 1); + return Literal; + } else { + parse_stream(bs, &prefix, 1, false); + return (prefix) ? Literal : Literal_RL; + } +} + +CODE dec_code_syntax(StreamBuffer *bs, MODE_TYPE md, OSDCmpr_Ctrl *p_ctrl) +{ + CODE retCode; + if (md == Literal || md == Literal_RL) { + retCode.color = dec_literal(bs, p_ctrl->reg_osd_format); + } else { + uint8_t pal_syntax; + parse_stream(bs, &pal_syntax, p_ctrl->reg_palette_idx_bd, + false); + retCode.palette_idx = pal_syntax; + } + + return retCode; +} + +RGBA pixel_preprocess(uint8_t *ptr, OSDCmpr_Ctrl *p_ctrl) +{ + RGBA color = get_color(ptr, p_ctrl->reg_osd_format); + color.b = (color.b >> p_ctrl->reg_rgb_trunc_bit) + << p_ctrl->reg_rgb_trunc_bit; + color.g = (color.g >> p_ctrl->reg_rgb_trunc_bit) + << p_ctrl->reg_rgb_trunc_bit; + color.r = (color.r >> p_ctrl->reg_rgb_trunc_bit) + << p_ctrl->reg_rgb_trunc_bit; + color.a = (color.a >> p_ctrl->reg_alpha_trunc_bit) + << p_ctrl->reg_alpha_trunc_bit; + if (p_ctrl->reg_zeroize_by_alpha && color.a == 0) { + color.code = 0; + } + set_color(ptr, color, p_ctrl->reg_osd_format); + + return color; +} + +// ---------------------- OSD cmpr main API ---------------------- +int osd_cmpr_enc_one_frame(uint8_t *ibuf, uint8_t *obs, OSDCmpr_Ctrl *p_ctrl) +{ + StreamBuffer bitstream; + size_t width = p_ctrl->reg_image_width, + height = p_ctrl->reg_image_height; + init_stream(&bitstream, p_ctrl->bsbuf, p_ctrl->bs_buf_size, false); + uint8_t *inPtr = ibuf; + RGBA last_color; + int rl_cnt = 1; + CODE code; + MODE_TYPE md = NUM_OF_MODE; + int max_run_len = 1 << p_ctrl->reg_run_len_bd; + for (int line_i = 0; line_i < (int)height; line_i++) { + for (int pos_x = 0; pos_x < (int)width; pos_x++) { + RGBA cur = pixel_preprocess(inPtr, p_ctrl); + if ((pos_x == 0 && line_i == 0) || + rl_cnt >= max_run_len || + (!is_equal_color(cur, last_color))) { // new run + if (!(pos_x == 0 && line_i == 0)) { // write out + enc_mode_syntax(&bitstream, md, rl_cnt, + code, p_ctrl); + } + // mode detection + int cache_idx = + (p_ctrl->reg_palette_mode_en) ? + palette_cache_lookup_color( + p_ctrl->palette_cache, + cur) : + -1; + if (cache_idx >= 0) { // cache hit + code.palette_idx = cache_idx; + md = Palette; + } else { // cache miss + code.color = cur; + md = Literal; + } + rl_cnt = 1; + } else { // still within a run + rl_cnt++; + } + last_color = cur; + inPtr += p_ctrl->pel_sz; + } + } + enc_mode_syntax(&bitstream, md, rl_cnt, code, p_ctrl); + int blk_bs_size = ((bitstream.bit_pos + 127) >> 7) + << 4; // in byte, 16byte align + memcpy(obs, p_ctrl->bsbuf, blk_bs_size * sizeof(uint8_t)); + + return blk_bs_size; +} + +void osd_cmpr_dec_one_frame(uint8_t *bsbuf, size_t bs_size, uint8_t *obuf, + OSDCmpr_Ctrl *p_ctrl) +{ + StreamBuffer bitstream; + init_stream(&bitstream, bsbuf, bs_size, true); + int remain_pix_cnt = p_ctrl->reg_image_width * p_ctrl->reg_image_height; + uint8_t *outPtr = obuf; + int run_len; + RGBA color; + while (remain_pix_cnt > 0) { + MODE_TYPE md = dec_mode_prefix(&bitstream, + p_ctrl->reg_palette_mode_en); + // decode run len + if (md == Literal_RL || md == Palette_RL) { + uint8_t run_syntax = 0; + parse_stream(&bitstream, &run_syntax, + p_ctrl->reg_run_len_bd, false); + run_len = run_syntax + 1; + } else { + run_len = 1; + } + + CODE code = dec_code_syntax(&bitstream, md, p_ctrl); + if (md == Literal || md == Literal_RL) { + color = code.color; + palette_cache_push_color(p_ctrl->palette_cache, color); + } else if (md == Palette || md == Palette_RL) { + color = p_ctrl->palette_cache[code.palette_idx]; + palette_cache_lru_update(p_ctrl->palette_cache, + code.palette_idx); + } + + // reconstruct pixels + for (int idx = 0; idx < run_len; idx++) { + set_color(outPtr, color, p_ctrl->reg_osd_format); + outPtr += p_ctrl->pel_sz; + remain_pix_cnt--; + } + } +} + +void osd_cmpr_enc_header(uint8_t *hdrbuf, OSDCmpr_Ctrl *p_ctrl) +{ + StreamBuffer bs_header; + size_t width_m1 = p_ctrl->reg_image_width - 1, + height_m1 = p_ctrl->reg_image_height - 1; + init_stream(&bs_header, hdrbuf, HDR_SZ, false); + move_stream_ptr(&bs_header, 8); // bit[0:7] version + write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_osd_format, + 4); // bit[8:11] osd_format + move_stream_ptr(&bs_header, 3); // bit[12:14] reserved + size_t palette_cache_size = 1 << p_ctrl->reg_palette_idx_bd; + write_stream(&bs_header, (uint8_t *)&palette_cache_size, + 8); // bit[15:22] palette_cache_size + write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_alpha_trunc_bit, + 2); // bit[23:24] alpha truncate + move_stream_ptr(&bs_header, 2); // bit[25:26] reserved + write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_rgb_trunc_bit, + 2); // bit[27:28] alpha truncate + move_stream_ptr(&bs_header, 2); // bit[29:30] reserved + write_stream(&bs_header, (uint8_t *)&width_m1, + 16); // bit[31:46] image_width minus 1 + write_stream(&bs_header, (uint8_t *)&height_m1, + 16); // bit[47:62] image_height minus 1 +} + +void osd_cmpr_dec_header(uint8_t *hdrbuf, OSDCmpr_Ctrl *p_ctrl) +{ + StreamBuffer bs_header; + init_stream(&bs_header, hdrbuf, HDR_SZ, true); + uint8_t palette_cache_size; + uint16_t width_m1, height_m1; + p_ctrl->reg_osd_format = OSD_ARGB8888; + p_ctrl->reg_alpha_trunc_bit = 0; + p_ctrl->reg_rgb_trunc_bit = 0; + + move_stream_ptr(&bs_header, 8); // bit[0:7] version + parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_osd_format, 4, + false); // bit[8:11] osd_format + move_stream_ptr(&bs_header, 3); // bit[12:14] reserved + parse_stream(&bs_header, &palette_cache_size, 8, + false); // bit[15:22] palette_cache_size + parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_alpha_trunc_bit, 2, + false); // bit[23:24] alpha truncate + move_stream_ptr(&bs_header, 2); // bit[25:26] reserved + parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_rgb_trunc_bit, 2, + false); // bit[27:28] alpha truncate + move_stream_ptr(&bs_header, 2); // bit[29:30] reserved + parse_stream(&bs_header, (uint8_t *)&width_m1, 16, + false); // bit[31:46] image_width minus 1 + parse_stream(&bs_header, (uint8_t *)&height_m1, 16, + false); // bit[47:62] image_height minus 1 + p_ctrl->reg_palette_mode_en = palette_cache_size > 1; + if (p_ctrl->reg_palette_mode_en) { + int palette_idx_bd = 0; + while ((1 << palette_idx_bd) < palette_cache_size) { + palette_idx_bd++; + } + p_ctrl->reg_palette_idx_bd = palette_idx_bd; + } + p_ctrl->reg_image_width = width_m1 + 1; + p_ctrl->reg_image_height = height_m1 + 1; +} + +void osd_cmpr_enc_followed_run(RGBA cur_c, int &rl_cnt, MODE_TYPE &md, + CODE &code, int &length, int max_run_len, + OSDCmpr_Ctrl *p_ctrl, StreamBuffer *bitstream) +{ + enc_mode_syntax(bitstream, md, rl_cnt, code, p_ctrl); + rl_cnt = min(length, max_run_len); + length -= rl_cnt; + // followed run must select Palette idx 0 + if (md != Palette || (md == Palette && code.palette_idx != 0)) { + if (p_ctrl->reg_palette_mode_en) { + code.palette_idx = 0; + md = Palette; + } else { + code.color = cur_c; + md = Literal; + } + } +} + +void osd_cmpr_enc_const_pixel(RGBA cur_c, RGBA &last_c, int &rl_cnt, + MODE_TYPE &md, CODE &code, int &length, + bool is_force_new_run, int max_run_len, + OSDCmpr_Ctrl *p_ctrl, StreamBuffer *bitstream) +{ + if ((!is_equal_color(cur_c, last_c)) || is_force_new_run || + (rl_cnt == max_run_len)) { + // new run + enc_mode_syntax(bitstream, md, rl_cnt, code, p_ctrl); + // mode detection + int cache_idx = (p_ctrl->reg_palette_mode_en) ? + palette_cache_lookup_color( + p_ctrl->palette_cache, cur_c) : + -1; + if (cache_idx >= 0) { // cache hit + code.palette_idx = cache_idx; + md = Palette; + } else { // cache miss + code.color = cur_c; + md = Literal; + } + rl_cnt = min(length, max_run_len); + length -= rl_cnt; + last_c = cur_c; + } else { // still within a run + int new_rl_cnt = min(rl_cnt + length, max_run_len); + length -= (new_rl_cnt - rl_cnt); + rl_cnt = new_rl_cnt; + } +} + +void osd_cmpr_debug_frame_compare(OSDCmpr_Ctrl *p_ctrl, uint8_t *buf0, + uint8_t *buf1) +{ + int frame_pel_num = p_ctrl->reg_image_width * p_ctrl->reg_image_height; + uint8_t *ptr0 = buf0, *ptr1 = buf1; + for (int pel_i = 0; pel_i < frame_pel_num; pel_i++) { + RGBA color0 = get_color(ptr0, p_ctrl->reg_osd_format); + RGBA color1 = get_color(ptr1, p_ctrl->reg_osd_format); + if (!is_equal_color(color0, color1)) { + printf("pel idx %d %d %d\n", pel_i, color0.code, + color1.code); + break; + } + ptr0 += p_ctrl->pel_sz; + ptr1 += p_ctrl->pel_sz; + } +} + +void osd_cmpr_frame_init(OSDCmpr_Ctrl *p_ctrl) +{ + p_ctrl->palette_cache.clear(); + palette_cache_init(p_ctrl->palette_cache, + 1 << p_ctrl->reg_palette_idx_bd); +} + +void osd_cmpr_setup(OSDCmpr_Ctrl *p_ctrl, OSDCmpr_Cfg *p_cfg) +{ + p_ctrl->reg_image_width = p_cfg->img_width; + p_ctrl->reg_image_height = p_cfg->img_height; + p_ctrl->reg_zeroize_by_alpha = p_cfg->zeroize_by_alpha; + p_ctrl->reg_rgb_trunc_bit = p_cfg->rgb_trunc_bit; + p_ctrl->reg_alpha_trunc_bit = p_cfg->alpha_trunc_bit; + p_ctrl->reg_palette_mode_en = p_cfg->palette_mode_en; + p_ctrl->reg_run_len_bd = p_cfg->run_len_bd; + p_ctrl->reg_palette_idx_bd = + (p_cfg->palette_mode_en) ? p_cfg->palette_idx_bd : 0; + p_ctrl->reg_osd_format = p_cfg->osd_format; + p_ctrl->pel_sz = osd_cmpr_get_pixel_sz(p_cfg->osd_format); + p_ctrl->bs_buf_size = osd_cmpr_get_bs_buf_max_sz( + p_cfg->img_width * p_cfg->img_height, p_ctrl->pel_sz); + p_ctrl->bsbuf = (uint8_t *)calloc(p_ctrl->bs_buf_size, sizeof(uint8_t)); +} + +size_t osd_cmpr_get_pixel_sz(OSD_FORMAT format) +{ + return (format == OSD_ARGB8888) ? + 4 : + (format == OSD_ARGB1555 || format == OSD_ARGB4444) ? + 2 : + 1; // (OSD_LUT8, OSD_LUT4) +}; + +size_t osd_cmpr_get_bs_buf_max_sz(int pel_num, int pel_sz) +{ + return HDR_SZ + ((((pel_num * (pel_sz * 8 + 1)) + 127) >> 7) + << 4); // in bytes, 16byte align +} + +size_t osd_cmpr_get_header_sz() +{ + return HDR_SZ; +} diff --git a/middleware/v2/modules/sys/Makefile b/middleware/v2/modules/sys/Makefile new file mode 100644 index 000000000..4f5b749f3 --- /dev/null +++ b/middleware/v2/modules/sys/Makefile @@ -0,0 +1,63 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS := $(wildcard $(SDIR)/*.c) +ifneq ($(MULTI_PROCESS_SUPPORT), 1) +SRCS := $(filter-out $(SDIR)/cvi_rpc.c, $(SRCS)) +endif +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) + +ifeq ($(SDK_VER), 32bit) +SRCS_ASM = $(wildcard $(SDIR)/*.S) +else ifeq ($(SDK_VER), 64bit) +SRCS_ASM = $(wildcard $(SDIR)/*.S) +else +SRCS_ASM = +endif + +OBJS_ASM = $(SRCS_ASM:.S=.o) +DEPS_ASM = $(SRCS_ASM:.S=.d) + +TARGET_A = $(MW_LIB)/libsys.a +TARGET_SO = $(MW_LIB)/libsys.so + +INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(VPU_INC) + +EXTRA_CFLAGS = $(INCS) -fpack-struct=8 +EXTRA_CFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\" +EXTRA_CFLAGS += -DSDK_VER=\"$(SDK_VER)\" +ifeq ($(SDK_VER), 32bit) +EXTRA_CFLAGS += -D_FILE_OFFSET_BITS=64 +endif + +LDFLAGS = -shared -fPIC -Wl,--gc-sections -export-dynamic -L$(MW_LIB) -L$(MW_3RD_LIB) --sysroot $(SYSROOT) $(CVI_TARGET_PACKAGES_LIBDIR) + +.PHONY : clean all +all : $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(SDIR)/%.o: $(SDIR)/%.S + $(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) $(OBJS_ASM) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) $(OBJS_ASM) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + @echo "$$AR_MRI" | $(AR) -M + +$(TARGET_SO): $(OBJS) $(OBJS_ASM) + @$(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $(TARGET_SO) -Wl,--start-group $(OBJS) $(OBJS_ASM) $(LIBS) -Wl,--end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(OBJS_ASM) $(DEPS) $(DEPS_ASM) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/sys/src/cvi_base.c b/middleware/v2/modules/sys/src/cvi_base.c new file mode 100644 index 000000000..8afcb0b58 --- /dev/null +++ b/middleware/v2/modules/sys/src/cvi_base.c @@ -0,0 +1,418 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* getopt_long() */ + +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cvi_base.h" +#include "cvi_buffer.h" +#include + + +struct vdev dev_isp, dev_vpss, dev_disp, dev_dwa, dev_rgn; + +static CVI_S32 base_fd = -1, sys_fd = -1; +static void *shared_mem; +static int shared_mem_usr_cnt; + +/* + * @param type: 0(isp) 1(img) 2(sc) 3(disp) + * @param dev_id: dev id + */ +struct vdev *get_dev_info(CVI_U8 type, CVI_U8 dev_id) +{ + UNUSED(dev_id); + + if (type == VDEV_TYPE_ISP) + return &dev_isp; + else if (type == VDEV_TYPE_VPSS) + return &dev_vpss; + else if (type == VDEV_TYPE_DISP) + return &dev_disp; + else if (type == VDEV_TYPE_DWA) + return &dev_dwa; + else if (type == VDEV_TYPE_RGN) + return &dev_rgn; + + return NULL; +} + +int open_device(const char *dev_name, CVI_S32 *fd) +{ + struct stat st; + + *fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK | O_CLOEXEC, 0); + if (-1 == *fd) { + fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, + strerror(errno)); + return -1; + } + + if (-1 == fstat(*fd, &st)) { + close(*fd); + fprintf(stderr, "Cannot identify '%s': %d, %s\n", dev_name, + errno, strerror(errno)); + return -1; + } + + if (!S_ISCHR(st.st_mode)) { + close(*fd); + fprintf(stderr, "%s is no device\n", dev_name); + return -ENODEV; + } + return 0; +} + +CVI_S32 close_device(CVI_S32 *fd) +{ + if (*fd == -1) + return -1; + + if (-1 == close(*fd)) { + fprintf(stderr, "%s: fd(%d) failure\n", __func__, *fd); + return -1; + } + + *fd = -1; + + return CVI_SUCCESS; +} + +CVI_S32 get_rgn_fd(CVI_VOID) +{ + if (dev_rgn.fd <= 0) + rgn_dev_open(); + + return dev_rgn.fd; +} + +CVI_S32 rgn_dev_open(CVI_VOID) +{ + if (dev_rgn.state != VDEV_STATE_OPEN) { + dev_rgn.state = VDEV_STATE_CLOSED; + if (open_device(RGN_DEV_NAME, &dev_rgn.fd) == -1) { + perror("RGN open failed\n"); + dev_rgn.fd = -1; + return CVI_FAILURE; + } + + dev_rgn.state = VDEV_STATE_OPEN; + } + + return CVI_SUCCESS; +} + +CVI_S32 rgn_dev_close(CVI_VOID) +{ + if (dev_rgn.state != VDEV_STATE_CLOSED) { + if (close_device(&dev_rgn.fd) == -1) { + perror("RGN close failed\n"); + dev_rgn.fd = -1; + return CVI_FAILURE; + } + dev_rgn.state = VDEV_STATE_CLOSED; + dev_rgn.fd = -1; + } + + return CVI_SUCCESS; +} + +CVI_S32 get_vo_fd(CVI_VOID) +{ + if (dev_disp.fd <= 0) + vo_dev_open(); + + return dev_disp.fd; +} + +CVI_S32 vo_dev_open(CVI_VOID) +{ + if (dev_disp.state != VDEV_STATE_OPEN) { + // disp + strncpy(dev_disp.name, "VO", sizeof(dev_disp.name)); + + if (open_device(VO_DEV_NAME, &dev_disp.fd) == -1) { + CVI_TRACE_SYS(CVI_DBG_WARN, "Warning: Maybe no VO dev?\n"); + dev_disp.fd = -1; + return CVI_FAILURE; + } + + dev_disp.state = VDEV_STATE_OPEN; + } + + return CVI_SUCCESS; +} + +CVI_S32 vo_dev_close(CVI_VOID) +{ + if (dev_disp.state != VDEV_STATE_CLOSED) { + if (close_device(&dev_disp.fd) == -1) { + perror("VO close failed\n"); + dev_disp.fd = -1; + return CVI_FAILURE; + } + dev_disp.state = VDEV_STATE_CLOSED; + dev_disp.fd = -1; + } + + return CVI_SUCCESS; +} + +CVI_S32 get_vpss_fd(void) +{ + if (dev_vpss.fd <= 0) + vpss_dev_open(); + + return dev_vpss.fd; +} + +CVI_S32 vpss_dev_open(CVI_VOID) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (dev_vpss.state != VDEV_STATE_OPEN) { + snprintf(dev_vpss.name, sizeof(dev_vpss.name) - 1, + "/dev/cvi-vpss"); + if (open_device(dev_vpss.name, &dev_vpss.fd) == -1) { + perror("VPSS open fail\n"); + s32Ret = CVI_FAILURE; + return s32Ret; + } + + dev_vpss.state = VDEV_STATE_OPEN; + } + + return s32Ret; +} + +CVI_S32 vpss_dev_close(CVI_VOID) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (dev_vpss.state != VDEV_STATE_CLOSED) { + s32Ret = close_device(&dev_vpss.fd); + if (s32Ret != CVI_SUCCESS) { + perror("VPSS close failed\n"); + s32Ret = CVI_FAILURE; + return s32Ret; + } + dev_vpss.fd = -1; + dev_vpss.state = VDEV_STATE_CLOSED; + } + + return s32Ret; +} + +CVI_S32 get_vi_fd(CVI_VOID) +{ + if (dev_isp.fd <= 0) + vi_dev_open(); + + return dev_isp.fd; +} + +CVI_S32 vi_dev_open(CVI_VOID) +{ + if (dev_isp.state != VDEV_STATE_OPEN) { + // isp + strncpy(dev_isp.name, "VI", sizeof(dev_isp.name)); + dev_isp.state = VDEV_STATE_CLOSED; + + if (open_device(VI_DEV_NAME, &dev_isp.fd) == -1) { + perror("VI open failed\n"); + dev_isp.fd = -1; + return CVI_FAILURE; + } + + dev_isp.state = VDEV_STATE_OPEN; + } + + return CVI_SUCCESS; +} + +CVI_S32 vi_dev_close(CVI_VOID) +{ + if (dev_isp.state != VDEV_STATE_CLOSED) { + if (close_device(&dev_isp.fd) == -1) { + perror("VI close failed\n"); + dev_isp.fd = -1; + return CVI_FAILURE; + } + dev_isp.state = VDEV_STATE_CLOSED; + dev_isp.fd = -1; + } + + return CVI_SUCCESS; +} + +CVI_S32 sys_dev_open(CVI_VOID) +{ + if (sys_fd != -1) { + CVI_TRACE_SYS(CVI_DBG_INFO, "sys dev has already opened\n"); + return CVI_SUCCESS; + } + + if (open_device(SYS_DEV_NAME, &sys_fd) != 0) { + perror("sys open failed"); + sys_fd = -1; + return CVI_ERR_SYS_NOTREADY; + } + return CVI_SUCCESS; +} + +CVI_S32 sys_dev_close(CVI_VOID) +{ + if (sys_fd == -1) { + CVI_TRACE_SYS(CVI_DBG_INFO, "sys dev is not opened\n"); + return CVI_SUCCESS; + } + + close_device(&sys_fd); + sys_fd = -1; + return CVI_SUCCESS; +} + +CVI_S32 get_sys_fd(CVI_VOID) +{ + if (sys_fd == -1) + sys_dev_open(); + return sys_fd; +} + +CVI_S32 dwa_dev_open(CVI_VOID) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + dwa_dev_close(); + + snprintf(dev_dwa.name, sizeof(dev_dwa.name) - 1, "/dev/cvi-dwa"); + if (open_device(dev_dwa.name, &dev_dwa.fd) == -1) { + perror("dwa open failed"); + return CVI_FAILURE; + } + dev_dwa.state = VDEV_STATE_OPEN; + + return s32Ret; +} + +CVI_S32 dwa_dev_close(CVI_VOID) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (dev_dwa.state != VDEV_STATE_CLOSED) { + close_device(&dev_dwa.fd); + dev_dwa.fd = -1; + dev_dwa.state = VDEV_STATE_CLOSED; + } + + return s32Ret; +} + +CVI_S32 base_dev_open(CVI_VOID) +{ + if (base_fd != -1) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base dev has already opened\n"); + return CVI_SUCCESS; + } + + if (open_device(BASE_DEV_NAME, &base_fd) != 0) { + perror("base open failed"); + base_fd = -1; + return CVI_ERR_SYS_NOTREADY; + } + return CVI_SUCCESS; +} + +CVI_S32 base_dev_close(CVI_VOID) +{ + if (base_fd == -1) { + CVI_TRACE_SYS(CVI_DBG_INFO, "base dev is not opened\n"); + return CVI_SUCCESS; + } + + close_device(&base_fd); + base_fd = -1; + return CVI_SUCCESS; +} + +CVI_S32 get_base_fd(CVI_VOID) +{ + if (base_fd == -1) + base_dev_open(); + return base_fd; +} + +CVI_S32 vpss_close(void) +{ + if (dev_vpss.state != VDEV_STATE_CLOSED) { + close_device(&dev_vpss.fd); + dev_vpss.state = VDEV_STATE_CLOSED; + } + return CVI_SUCCESS; +} + +CVI_S32 vo_close(void) +{ + if (dev_disp.state != VDEV_STATE_CLOSED) { + close_device(&dev_disp.fd); + dev_disp.state = VDEV_STATE_CLOSED; + } + return CVI_SUCCESS; +} + +long get_diff_in_us(struct timespec t1, struct timespec t2) +{ + struct timespec diff; + + if (t2.tv_nsec-t1.tv_nsec < 0) { + diff.tv_sec = t2.tv_sec - t1.tv_sec - 1; + diff.tv_nsec = t2.tv_nsec - t1.tv_nsec + 1000000000; + } else { + diff.tv_sec = t2.tv_sec - t1.tv_sec; + diff.tv_nsec = t2.tv_nsec - t1.tv_nsec; + } + return (diff.tv_sec * 1000000.0 + diff.tv_nsec / 1000.0); +} + +void *base_get_shm(void) +{ + base_dev_open(); + if (shared_mem == NULL) { + shared_mem = mmap(NULL, BASE_SHARE_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, base_fd, 0); + if (shared_mem == MAP_FAILED) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base dev mmap fail!\n"); + return NULL; + } + } + + shared_mem_usr_cnt++; + return shared_mem; +} + +void base_release_shm(void) +{ + shared_mem_usr_cnt--; + + if (shared_mem_usr_cnt == 0 && shared_mem != NULL) { + munmap((void *)shared_mem, BASE_SHARE_MEM_SIZE); + shared_mem = NULL; + } +} diff --git a/middleware/v2/modules/sys/src/cvi_sys.c b/middleware/v2/modules/sys/src/cvi_sys.c new file mode 100644 index 000000000..c10138ddc --- /dev/null +++ b/middleware/v2/modules/sys/src/cvi_sys.c @@ -0,0 +1,1009 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include "devmem.h" +#include "cvi_base.h" +#include "cvi_sys.h" +#include "hashmap.h" +#include +#include +#include "sys_ioctl.h" + + +#define TPUDEVNAME "/dev/cvi-tpu0" + +struct bind_t { + TAILQ_ENTRY(bind_t) tailq; + BIND_NODE_S *node; +}; + +TAILQ_HEAD(bind_head, bind_t) binds; +pthread_rwlock_t bind_lock; + +static int devm_fd = -1, devm_cached_fd = -1; +static int ionFd = -1; +static Hashmap *ionHashmap = NULL; +static void *shared_mem; +static MMF_VERSION_S *mmf_version; +CVI_S32 *log_levels; +CVI_CHAR const *log_name[8] = { + (CVI_CHAR *)"EMG", (CVI_CHAR *)"ALT", (CVI_CHAR *)"CRI", (CVI_CHAR *)"ERR", + (CVI_CHAR *)"WRN", (CVI_CHAR *)"NOT", (CVI_CHAR *)"INF", (CVI_CHAR *)"DBG" +}; + +pthread_mutex_t tdma_pio_seq_lock = PTHREAD_MUTEX_INITIALIZER; +static uint32_t tdma_pio_seq; +static pthread_once_t lp_off_once = PTHREAD_ONCE_INIT; + +static void _sys_low_power_off(void) +{ + // disable fab lowpower/slowdown + // sys_ctrl clklp + system("devmem 0x03002A50 32 0xFFFFFFFF"); + system("devmem 0x03002A60 32 0xFFFFFFFF"); + system("devmem 0x03002A00 32 0x003F5500"); + system("devmem 0x03002A04 32 0x003F5500"); + system("devmem 0x03002A0C 32 0x003F5500"); + system("devmem 0x03002A10 32 0x003F5500"); + system("devmem 0x03002A14 32 0x003F5500"); + system("devmem 0x03002A18 32 0x003F5500"); + system("devmem 0x03002A1C 32 0x003F5500"); + system("devmem 0x03002A20 32 0x003F5500"); + system("devmem 0x03002A24 32 0x003F5500"); + system("devmem 0x03002A28 32 0x003F5500"); + system("devmem 0x03002A2C 32 0x003F5500"); + system("devmem 0x03002A30 32 0x003F5500"); + // ddrsys clklp + system("devmem 0x0800A014 32 0x00000FFF"); + // vipsys clklp + system("devmem 0X0A0C8020 32 0x00000C01"); + system("devmem 0x0A0C8024 32 0x00000C01"); + system("devmem 0x0A0C8028 32 0x00000C01"); + system("devmem 0x0A0C802C 32 0x0C010C01"); + system("devmem 0x0A0C8038 32 0x001F0500"); + system("devmem 0x0A0C803C 32 0x001F0500"); + system("devmem 0x0A0C8040 32 0x001F0500"); + system("devmem 0x0A0C8044 32 0x001F0500"); + system("devmem 0x0A0C8048 32 0x001F0500"); + system("devmem 0x0A0C80C4 32 0x001F0500"); + system("devmem 0x0A0C80C8 32 0x001F0500"); + system("devmem 0x0A0C80CC 32 0x001F0500"); + // vc fab + // system("devmem 0x0B030028 32 0x07"); + + CVI_TRACE_SYS(CVI_DBG_INFO, "low_power_off\n"); +} + +static int _ion_hash_key(void *key) +{ + return (((uintptr_t)key) >> 10); +} + +static bool _ion_hash_equals(void *keyA, void *keyB) +{ + return (keyA == keyB); +} + +static CVI_S32 _SYS_MMAP(void) +{ + if (shared_mem != NULL) { + CVI_TRACE_SYS(CVI_DBG_INFO, "already done mmap\n"); + return CVI_SUCCESS; + } + + shared_mem = base_get_shm(); + if (shared_mem == NULL) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_get_shm failed!\n"); + return CVI_ERR_SYS_NOMEM; + } + + log_levels = (CVI_S32 *)(shared_mem + BASE_LOG_LEVEL_OFFSET); + + mmf_version = (MMF_VERSION_S *)(shared_mem + BASE_VERSION_INFO_OFFSET); + memset(mmf_version, 0, VERSION_INFO_RSV_SIZE); + CVI_SYS_GetVersion(mmf_version); + + return CVI_SUCCESS; +} + +static CVI_S32 _SYS_UNMMAP(void) +{ + if (shared_mem == NULL) { + CVI_TRACE_SYS(CVI_DBG_INFO, "No need to unmap\n"); + return CVI_SUCCESS; + } + + base_release_shm(); + shared_mem = NULL; + log_levels = NULL; + mmf_version = NULL; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_DevMem_Open(void) +{ + if (devm_fd < 0) + devm_fd = devm_open(); + + if (devm_cached_fd < 0) + devm_cached_fd = devm_open_cached(); + + if (devm_fd < 0 || devm_cached_fd < 0) { + perror("devmem open failed\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_DevMem_Close(void) +{ + if (devm_fd < 0 || devm_cached_fd < 0) + return CVI_SUCCESS; + + devm_close(devm_fd); + devm_fd = -1; + devm_close(devm_cached_fd); + devm_cached_fd = -1; + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_VI_Open(void) +{ + CVI_S32 s32ret = CVI_SUCCESS; + + s32ret = vi_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_vi_open failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + return s32ret; +} + +CVI_S32 CVI_SYS_VI_Close(void) +{ + CVI_S32 s32ret = CVI_SUCCESS; + + s32ret = vi_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_vi_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + return s32ret; +} + +CVI_S32 CVI_SYS_Init(void) +{ + CVI_S32 s32ret = CVI_SUCCESS, _sys_fd = -1; + CVI_U32 sys_init = 0; + VI_VPSS_MODE_S stVIVPSSMode; + VPSS_MODE_S stVPSSMode; + + pthread_once(&lp_off_once, _sys_low_power_off); + + s32ret = base_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_dev_open failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + s32ret = sys_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "sys_dev_open failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + CVI_TRACE_SYS(CVI_DBG_INFO, "+\n"); + + if (CVI_SYS_DevMem_Open() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "devmem open failed.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (_SYS_MMAP() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "_SYS_MMAP failed.\n"); + return CVI_ERR_SYS_NOMEM; + } + + s32ret = vi_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base_vi_open failed\n"); + s32ret = CVI_SUCCESS; + //If ko is not insmod, means no need this function. + //return CVI_ERR_SYS_NOTREADY; + } + + s32ret = vpss_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base_vpss_open failed\n"); + s32ret = CVI_SUCCESS; + //If ko is not insmod, means no need this function. + //return CVI_ERR_SYS_NOTREADY; + } + +#ifndef __SOC_PHOBOS__ + s32ret = vo_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base_vo_open failed\n"); + s32ret = CVI_SUCCESS; + //If ko is not insmod, means no need this function. + //return CVI_ERR_SYS_NOTREADY; + } +#endif + + s32ret = dwa_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base_dwa_open failed\n"); + //If ko is not insmod, means no need this function. + //return CVI_ERR_SYS_NOTREADY; + s32ret = CVI_SUCCESS; + } + + s32ret = rgn_dev_open(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_DEBUG, "base_rgn_open failed\n"); + //If ko is not insmod, means no need this function. + //return CVI_ERR_SYS_NOTREADY; + s32ret = CVI_SUCCESS; + } + +#if 0 //TODO: need remove to vo module + // check fb parameters to see if fb on vpss or vo. + memset(&vo_ctx, 0, sizeof(vo_ctx)); + file = fopen("/sys/module/cvi_fb/parameters/option", "r"); + if (file == NULL) + vo_ctx.fb_on_vpss = CVI_FALSE; + else { + CVI_S32 option = 0; + + fscanf(file, "%d", &option); + vo_ctx.fb_on_vpss = option & BIT(1); + fclose(file); + } +#endif + _sys_fd = get_sys_fd(); + sys_get_sys_init(_sys_fd, &sys_init); + if (sys_init == 0) { + for (CVI_U8 i = 0; i < VI_MAX_PIPE_NUM; ++i) + stVIVPSSMode.aenMode[i] = VI_OFFLINE_VPSS_OFFLINE; + CVI_SYS_SetVIVPSSMode(&stVIVPSSMode); + stVPSSMode.enMode = VPSS_MODE_SINGLE; + for (CVI_U8 i = 0; i < VPSS_IP_NUM; ++i) + stVPSSMode.aenInput[i] = VPSS_INPUT_MEM; + CVI_SYS_SetVPSSModeEx(&stVPSSMode); + + CVI_SYS_StartThermalThread(); + } + + sys_set_sys_init(_sys_fd); + + CVI_TRACE_SYS(CVI_DBG_INFO, "-\n"); + + return s32ret; +} + +CVI_S32 CVI_SYS_Exit(void) +{ + CVI_S32 s32ret = CVI_SUCCESS, _sys_fd = -1; + CVI_U32 sys_init = 0; + + CVI_TRACE_SYS(CVI_DBG_INFO, "+\n"); + + _sys_fd = get_sys_fd(); + sys_get_sys_init(_sys_fd, &sys_init); + if (sys_init == 1) { + CVI_SYS_StopThermalThread(); + } + + s32ret = vi_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_vi_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + s32ret = vpss_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_vpss_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + +#ifndef __SOC_PHOBOS__ + s32ret = vo_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_vo_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } +#endif + + s32ret = dwa_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_dwa_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + s32ret = rgn_dev_close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "base_rgn_close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (ionFd > 0) { + close(ionFd); + ionFd = -1; + } + + _SYS_UNMMAP(); + s32ret = CVI_SYS_DevMem_Close(); + if (s32ret != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "devmem close failed\n"); + return CVI_ERR_SYS_NOTREADY; + } + sys_dev_close(); + base_dev_close(); + + CVI_TRACE_SYS(CVI_DBG_INFO, "-\n"); + + return s32ret; +} + +CVI_S32 _CVI_SYS_BindIOCtl(const MMF_CHN_S *pstSrcChn, const MMF_CHN_S *pstDestChn, CVI_U8 is_bind) +{ + CVI_S32 fd = 0; + CVI_S32 ret = 0; + struct sys_bind_cfg bind_cfg; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + memset(&bind_cfg, 0, sizeof(struct sys_bind_cfg)); + bind_cfg.is_bind = is_bind; + bind_cfg.mmf_chn_src = *pstSrcChn; + bind_cfg.mmf_chn_dst = *pstDestChn; + + ret = ioctl(fd, SYS_SET_BINDCFG, &bind_cfg); + + if (ret) + CVI_TRACE_SYS(CVI_DBG_ERR, "_CVI_SYS_BindIOCtl()failed\n"); + + return ret; +} + +CVI_S32 CVI_SYS_Bind(const MMF_CHN_S *pstSrcChn, const MMF_CHN_S *pstDestChn) +{ +#ifdef __SOC_PHOBOS__ + if (pstDestChn && (pstDestChn->enModId == CVI_ID_VO)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "No vo device, vo cannot be bind!\n"); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } +#endif + return _CVI_SYS_BindIOCtl(pstSrcChn, pstDestChn, 1); +} + +CVI_S32 CVI_SYS_UnBind(const MMF_CHN_S *pstSrcChn, const MMF_CHN_S *pstDestChn) +{ +#ifdef __SOC_PHOBOS__ + if (pstDestChn && (pstDestChn->enModId == CVI_ID_VO)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "No vo device, cannot unbind vo!\n"); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } +#endif + return _CVI_SYS_BindIOCtl(pstSrcChn, pstDestChn, 0); +} + +CVI_S32 CVI_SYS_GetBindbyDest(const MMF_CHN_S *pstDestChn, MMF_CHN_S *pstSrcChn) +{ + CVI_S32 fd = 0; + CVI_S32 ret = 0; + struct sys_bind_cfg bind_cfg; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + memset(&bind_cfg, 0, sizeof(struct sys_bind_cfg)); + bind_cfg.get_by_src = 0; + bind_cfg.mmf_chn_dst = *pstDestChn; + + ret = ioctl(fd, SYS_GET_BINDCFG, &bind_cfg); + + if (ret) { + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_GetBindbyDest() failed\n"); + return ret; + } + + memcpy(pstSrcChn, &bind_cfg.mmf_chn_src, sizeof(MMF_CHN_S)); + return CVI_SUCCESS; + +} + +CVI_S32 CVI_SYS_GetBindbySrc(const MMF_CHN_S *pstSrcChn, MMF_BIND_DEST_S *pstBindDest) +{ + CVI_S32 fd = 0; + CVI_S32 ret = 0; + struct sys_bind_cfg bind_cfg; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + memset(&bind_cfg, 0, sizeof(struct sys_bind_cfg)); + bind_cfg.get_by_src = 1; + bind_cfg.mmf_chn_src = *pstSrcChn; + + ret = ioctl(fd, SYS_GET_BINDCFG, &bind_cfg); + + if (ret) { + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_GetBindbySrc() failed\n"); + return ret; + } + + memcpy(pstBindDest, &bind_cfg.bind_dst, sizeof(MMF_BIND_DEST_S)); + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_GetVersion(MMF_VERSION_S *pstVersion) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pstVersion); + +#ifndef MMF_VERSION +#define MMF_VERSION (CVI_CHIP_NAME MMF_VER_PRIX MK_VERSION(VER_X, VER_Y, VER_Z) VER_D) +#endif + snprintf(pstVersion->version, VERSION_NAME_MAXLEN, "%s-%s", MMF_VERSION, SDK_VER); + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_GetChipId(CVI_U32 *pu32ChipId) +{ + static CVI_U32 id = 0xffffffff; + int fd; + + if (id == 0xffffffff) { + CVI_U32 tmp = 0; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Can't open device, cvi-base.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (ioctl(fd, IOCTL_READ_CHIP_ID, &tmp) < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ioctl IOCTL_READ_CHIP_ID failed\n"); + return CVI_FAILURE; + } + + id = tmp; + } + + *pu32ChipId = id; + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_GetPowerOnReason(CVI_U32 *pu32PowerOnReason) +{ + int fd; + CVI_U32 ret_val = 0x0; + CVI_U32 reason = 0x0; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Can't open device, cvi-base.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (ioctl(fd, IOCTL_READ_CHIP_PWR_ON_REASON, &reason) < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "IOCTL_READ_CHIP_PWR_ON_REASON failed\n"); + return CVI_FAILURE; + } + + switch (reason) { + case E_CHIP_PWR_ON_COLDBOOT: + ret_val = CVI_COLDBOOT; + break; + case E_CHIP_PWR_ON_WDT: + ret_val = CVI_WDTBOOT; + break; + case E_CHIP_PWR_ON_SUSPEND: + ret_val = CVI_SUSPENDBOOT; + break; + case E_CHIP_PWR_ON_WARM_RST: + ret_val = CVI_WARMBOOT; + break; + default: + CVI_TRACE_SYS(CVI_DBG_ERR, "unknown reason (%#x)\n", reason); + return CVI_ERR_SYS_NOT_PERM; + break; + } + + *pu32PowerOnReason = ret_val; + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_GetChipVersion(CVI_U32 *pu32ChipVersion) +{ + static CVI_U32 version = 0xffffffff; + int fd; + + if (version == 0xffffffff) { + CVI_U32 tmp = 0; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Can't open device, cvi-base.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + if (ioctl(fd, IOCTL_READ_CHIP_VERSION, &tmp) < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ioctl IOCTL_READ_CHIP_VERSION failed\n"); + return CVI_FAILURE; + } + + switch (tmp) { + case E_CHIPVERSION_U01: + version = CVIU01; + break; + case E_CHIPVERSION_U02: + version = CVIU02; + break; + default: + CVI_TRACE_SYS(CVI_DBG_ERR, "unknown version(%#x)\n", tmp); + return CVI_ERR_SYS_NOT_PERM; + break; + } + } + + *pu32ChipVersion = version; + return CVI_SUCCESS; +} + +void *CVI_SYS_Mmap(CVI_U64 u64PhyAddr, CVI_U32 u32Size) +{ + CVI_SYS_DevMem_Open(); + + return devm_map(devm_fd, u64PhyAddr, u32Size); +} + +/* CVI_SYS_MmapCache - mmap the physical address to cached virtual-address + * + * @param pu64PhyAddr: the phy-address of the buffer + * @param u32Size: the length of the buffer + * @return virtual-address if success; 0 if fail. + */ +void *CVI_SYS_MmapCache(CVI_U64 u64PhyAddr, CVI_U32 u32Size) +{ + CVI_SYS_DevMem_Open(); + + void *addr = devm_map(devm_cached_fd, u64PhyAddr, u32Size); + + if (addr) + CVI_SYS_IonInvalidateCache(u64PhyAddr, addr, u32Size); + return addr; +} + +CVI_S32 CVI_SYS_Munmap(void *pVirAddr, CVI_U32 u32Size) +{ + devm_unmap(pVirAddr, u32Size); + return CVI_SUCCESS; +} + +int ionMalloc(int devFd, struct sys_ion_data *para, bool isCache) +{ + CVI_S32 ret; + + para->cached = isCache; + ret = ioctl(devFd, SYS_ION_ALLOC, para); + if (ret < 0) { + printf("ioctl SYS_ION_ALLOC failed\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +int ionFree(struct sys_ion_data *para) +{ + CVI_S32 fd = -1; + CVI_S32 ret = CVI_SUCCESS; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + ret = ioctl(fd, SYS_ION_FREE, para); + if (ret < 0) { + printf("ioctl SYS_ION_ALLOC failed\n"); + } + + return CVI_SUCCESS; +} + +static CVI_S32 _SYS_IonAlloc(CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr, + CVI_U32 u32Len, CVI_BOOL cached, const CVI_CHAR *name) +{ + CVI_S32 fd = -1; + struct sys_ion_data *ion_data; + + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pu64PhyAddr); + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + if (!ionHashmap) + ionHashmap = hashmapCreate(20, _ion_hash_key, _ion_hash_equals); + + ion_data = malloc(sizeof(*ion_data)); + ion_data->size = u32Len; + // Set buffer as "anonymous" when user is passing null pointer. + if (name) + strncpy((char *)(ion_data->name), name, MAX_ION_BUFFER_NAME); + else + strncpy((char *)(ion_data->name), "anonymous", MAX_ION_BUFFER_NAME); + + if (ionMalloc(fd, ion_data, cached) != CVI_SUCCESS) { + free(ion_data); + CVI_TRACE_SYS(CVI_DBG_ERR, "alloc failed.\n"); + return CVI_ERR_SYS_NOMEM; + } + + *pu64PhyAddr = ion_data->addr_p; + hashmapPut(ionHashmap, (void *)(uintptr_t)*pu64PhyAddr, ion_data); + + if (ppVirAddr) { + if (cached) + *ppVirAddr = CVI_SYS_MmapCache(*pu64PhyAddr, u32Len); + else + *ppVirAddr = CVI_SYS_Mmap(*pu64PhyAddr, u32Len); + if (*ppVirAddr == NULL) { + hashmapGet(ionHashmap, (void *)(uintptr_t)*pu64PhyAddr); + ionFree(ion_data); + free(ion_data); + CVI_TRACE_SYS(CVI_DBG_ERR, "mmap failed. (%s)\n", strerror(errno)); + return CVI_ERR_SYS_REMAPPING; + } + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_IonAlloc(CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr, const CVI_CHAR *strName, CVI_U32 u32Len) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pu64PhyAddr); + + return _SYS_IonAlloc(pu64PhyAddr, ppVirAddr, u32Len, CVI_FALSE, strName); +} + +/* CVI_SYS_IonAlloc_Cached - acquire buffer of u32Len from ion + * + * @param pu64PhyAddr: the phy-address of the buffer + * @param ppVirAddr: the cached vir-address of the buffer + * @param strName: the name of the buffer + * @param u32Len: the length of the buffer acquire + * @return CVI_SUCCES if ok + */ +CVI_S32 CVI_SYS_IonAlloc_Cached(CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr, + const CVI_CHAR *strName, CVI_U32 u32Len) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pu64PhyAddr); + return _SYS_IonAlloc(pu64PhyAddr, ppVirAddr, u32Len, CVI_TRUE, strName); +} + +CVI_S32 CVI_SYS_IonFree(CVI_U64 u64PhyAddr, CVI_VOID *pVirAddr) +{ + struct sys_ion_data *ion_data; + + if (ionHashmap == NULL) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ion not alloc before.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + ion_data = hashmapGet(ionHashmap, (void *)(uintptr_t)u64PhyAddr); + if (ion_data == NULL) { + CVI_TRACE_SYS(CVI_DBG_ERR, "u64PhyAddr(0x%"PRIx64") not found in ion.\n", u64PhyAddr); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } + hashmapRemove(ionHashmap, (void *)(uintptr_t)u64PhyAddr); + if (pVirAddr) + devm_unmap(pVirAddr, ion_data->size); + ionFree(ion_data); + free(ion_data); + + if (hashmapSize(ionHashmap) == 0) { + hashmapFree(ionHashmap); + ionHashmap = NULL; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_IonFlushCache(CVI_U64 u64PhyAddr, CVI_VOID *pVirAddr, CVI_U32 u32Len) +{ + CVI_S32 fd = -1; + CVI_S32 ret = CVI_SUCCESS; + struct sys_cache_op cache_cfg; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + if (pVirAddr == NULL) { + CVI_TRACE_SYS(CVI_DBG_ERR, "pVirAddr Null.\n"); + return CVI_ERR_SYS_NULL_PTR; + } + + cache_cfg.addr_p = u64PhyAddr; + cache_cfg.addr_v = pVirAddr; + cache_cfg.size = u32Len; + + ret = ioctl(fd, SYS_CACHE_FLUSH, &cache_cfg); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ion flush err.\n"); + ret = CVI_ERR_SYS_NOTREADY; + } + return ret; +} + +CVI_S32 CVI_SYS_IonInvalidateCache(CVI_U64 u64PhyAddr, CVI_VOID *pVirAddr, CVI_U32 u32Len) +{ + CVI_S32 fd = -1; + CVI_S32 ret = CVI_SUCCESS; + struct sys_cache_op cache_cfg; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + if (pVirAddr == NULL) { + CVI_TRACE_SYS(CVI_DBG_ERR, "pVirAddr Null.\n"); + return CVI_ERR_SYS_NULL_PTR; + } + + cache_cfg.addr_p = u64PhyAddr; + cache_cfg.addr_v = pVirAddr; + cache_cfg.size = u32Len; + + ret = ioctl(fd, SYS_CACHE_INVLD, &cache_cfg); + if (ret < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ion flush err.\n"); + ret = CVI_ERR_SYS_NOTREADY; + } + return ret; +} + +CVI_S32 CVI_SYS_IonGetFd(CVI_VOID) +{ + if (ionFd < 0) { + ionFd = open("/dev/ion", O_RDWR | O_DSYNC); + if (ionFd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "ion fd open failed.\n"); + return -1; + } + ionHashmap = hashmapCreate(20, _ion_hash_key, _ion_hash_equals); + } + return ionFd; +} + +CVI_S32 CVI_SYS_SetVIVPSSMode(const VI_VPSS_MODE_S *pstVIVPSSMode) +{ + CVI_S32 fd = 0; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + return sys_set_vivpssmode(fd, pstVIVPSSMode); +} + +CVI_S32 CVI_SYS_GetVIVPSSMode(VI_VPSS_MODE_S *pstVIVPSSMode) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pstVIVPSSMode); + CVI_S32 fd = 0; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + return sys_get_vivpssmode(fd, pstVIVPSSMode); +} + +CVI_S32 CVI_SYS_SetVPSSMode(VPSS_MODE_E enVPSSMode) +{ + CVI_S32 fd = 0; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + return sys_set_vpssmode(fd, enVPSSMode); +} + +VPSS_MODE_E CVI_SYS_GetVPSSMode(void) +{ + CVI_S32 fd = 0; + VPSS_MODE_E enMode; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + sys_get_vpssmode(fd, &enMode); + + return enMode; +} + +CVI_S32 CVI_SYS_SetVPSSModeEx(const VPSS_MODE_S *pstVPSSMode) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pstVPSSMode); + CVI_S32 fd = 0; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + return sys_set_vpssmodeex(fd, pstVPSSMode); +} + +CVI_S32 CVI_SYS_GetVPSSModeEx(VPSS_MODE_S *pstVPSSMode) +{ + CVI_S32 fd = 0; + VPSS_MODE_S vpss_mode; + + if ((fd = get_sys_fd()) == -1) + return CVI_ERR_SYS_NOTREADY; + + sys_get_vpssmodeex(fd, &vpss_mode); + + *pstVPSSMode = vpss_mode; + + return CVI_SUCCESS; +} + +const CVI_CHAR *CVI_SYS_GetModName(MOD_ID_E id) +{ + return CVI_GET_MOD_NAME(id); +} + +CVI_S32 CVI_LOG_SetLevelConf(LOG_LEVEL_CONF_S *pstConf) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pstConf); + + if (pstConf->enModId >= CVI_ID_BUTT) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Invalid ModId(%d)\n", pstConf->enModId); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } + + if (_SYS_MMAP() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "_SYS_MMAP failed.\n"); + return CVI_FAILURE; + } + + log_levels[pstConf->enModId] = pstConf->s32Level; + return CVI_SUCCESS; +} + +CVI_S32 CVI_LOG_GetLevelConf(LOG_LEVEL_CONF_S *pstConf) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pstConf); + + if (pstConf->enModId >= CVI_ID_BUTT) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Invalid ModId(%d)\n", pstConf->enModId); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } + + if (_SYS_MMAP() != CVI_SUCCESS) { + CVI_TRACE_SYS(CVI_DBG_ERR, "_SYS_MMAP failed.\n"); + return CVI_FAILURE; + } + + pstConf->s32Level = log_levels[pstConf->enModId]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_GetCurPTS(CVI_U64 *pu64CurPTS) +{ + MOD_CHECK_NULL_PTR(CVI_ID_SYS, pu64CurPTS); + + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + *pu64CurPTS = ts.tv_sec*1000000 + ts.tv_nsec/1000; + + return CVI_SUCCESS; + +} + +CVI_S32 CVI_SYS_TDMACopy(CVI_U64 u64PhyDst, CVI_U64 u64PhySrc, CVI_U32 u32Len) +{ +#define TDMA2D_LEN_LIMIT 0xFFFFFFFF + + static int tpu_fd = -1; + struct cvi_tdma_copy_arg tdma_ioctl; + struct cvi_tdma_wait_arg wait_ioctl; + + if (u32Len >= TDMA2D_LEN_LIMIT) { + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_TDMACopy() input param can't be supported\n"); + return CVI_ERR_SYS_NOT_SUPPORT; + } + + tpu_fd = open(TPUDEVNAME, O_RDWR | O_DSYNC); + if (tpu_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "tpu fd open failed.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + memset(&tdma_ioctl, 0, sizeof(struct cvi_tdma_copy_arg)); + + pthread_mutex_lock(&tdma_pio_seq_lock); + tdma_pio_seq++; + tdma_ioctl.seq_no = tdma_pio_seq; + pthread_mutex_unlock(&tdma_pio_seq_lock); + + tdma_ioctl.paddr_src = u64PhySrc; + tdma_ioctl.paddr_dst = u64PhyDst; + tdma_ioctl.leng_bytes = u32Len; + ioctl(tpu_fd, CVITPU_SUBMIT_PIO, &tdma_ioctl); + + //wait finished + wait_ioctl.seq_no = tdma_ioctl.seq_no; + ioctl(tpu_fd, CVITPU_WAIT_PIO, &wait_ioctl); + + if (wait_ioctl.ret) + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_TDMACopy wait failed\n"); + + close(tpu_fd); + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_TDMACopy2D(CVI_TDMA_2D_S *param) +{ +#define TDMA2D_W_LIMIT 0x10000 +#define TDMA2D_H_LIMIT 0x10000 + + static int tpu_fd = -1; + struct cvi_tdma_copy_arg tdma_ioctl; + struct cvi_tdma_wait_arg wait_ioctl; + + if (param->stride_bytes_src < param->w_bytes || + param->stride_bytes_dst < param->w_bytes || + param->w_bytes >= TDMA2D_W_LIMIT || + param->h >= TDMA2D_H_LIMIT) { + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_TDMACopy2D() input param can't be supported\n"); + return CVI_ERR_SYS_NOT_SUPPORT; + } + + tpu_fd = open(TPUDEVNAME, O_RDWR | O_DSYNC); + if (tpu_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "tpu fd open failed.\n"); + return CVI_ERR_SYS_NOTREADY; + } + + memset(&tdma_ioctl, 0, sizeof(struct cvi_tdma_copy_arg)); + + pthread_mutex_lock(&tdma_pio_seq_lock); + tdma_pio_seq++; + tdma_ioctl.seq_no = tdma_pio_seq; + pthread_mutex_unlock(&tdma_pio_seq_lock); + + tdma_ioctl.enable_2d = 1; + tdma_ioctl.paddr_src = param->paddr_src; + tdma_ioctl.paddr_dst = param->paddr_dst; + tdma_ioctl.h = param->h; + tdma_ioctl.w_bytes = param->w_bytes; + tdma_ioctl.stride_bytes_src = param->stride_bytes_src; + tdma_ioctl.stride_bytes_dst = param->stride_bytes_dst; + ioctl(tpu_fd, CVITPU_SUBMIT_PIO, &tdma_ioctl); + + //wait finished + wait_ioctl.seq_no = tdma_ioctl.seq_no; + ioctl(tpu_fd, CVITPU_WAIT_PIO, &wait_ioctl); + + if (wait_ioctl.ret) + CVI_TRACE_SYS(CVI_DBG_ERR, "CVI_SYS_TDMACopy2D wait failed\n"); + + close(tpu_fd); + return CVI_SUCCESS; +} + diff --git a/middleware/v2/modules/sys/src/cvi_thermal.c b/middleware/v2/modules/sys/src/cvi_thermal.c new file mode 100644 index 000000000..c217745c6 --- /dev/null +++ b/middleware/v2/modules/sys/src/cvi_thermal.c @@ -0,0 +1,675 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_sys.h" + +/* Generic macros for dealing with netlink sockets. Might be duplicated + * elsewhere. It is recommended that commercial grade applications use + * libnl or libnetlink and use the interfaces provided by the library + */ +#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) +#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN) +#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN)) +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +//Variables used for netlink +struct sockaddr_nl nl_address; //netlink socket address + +struct nlattr *nl_na; //pointer to netlink attributes structure within the payload +struct { //memory for netlink request and response messages - headers are included + struct nlmsghdr n; + struct genlmsghdr g; + char buf[256]; +} nl_request_msg, nl_response_msg; + +struct thermal_event { + int orig; + unsigned short up_down; + unsigned short trip_id; +} thermal_event; +struct thermal_event *tz_evt; + +typedef void (*event_cb_t)(int fps); + +pthread_t thermal_thread; +CVI_BOOL g_is_thermal_running = CVI_FALSE; +event_cb_t callbackFunc; +int therm_sockets[2]; + +static int _init_bind_genl_socket(void) +{ + //Step 1: Open the socket. Note that protocol = NETLINK_GENERIC + int nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + + if (nl_fd < 0) { + perror("socket()"); + return -1; + } + + //Step 2: Bind the socket. + memset(&nl_address, 0, sizeof(nl_address)); + nl_address.nl_family = AF_NETLINK; + nl_address.nl_groups = 0; + + if (bind(nl_fd, (struct sockaddr *) &nl_address, sizeof(nl_address)) < 0) { + perror("bind()"); + close(nl_fd); + return -1; + } + return nl_fd; +} + +static int _get_mcast_grpid_genl_socket(int nl_fd, const char *family_name) +{ + int nl_group_id = 0; + int nl_rxtx_length; + + //Step 3. Resolve the family ID corresponding to the string "thermal_event" + //Populate the netlink header + nl_request_msg.n.nlmsg_type = GENL_ID_CTRL; + nl_request_msg.n.nlmsg_flags = NLM_F_REQUEST; + nl_request_msg.n.nlmsg_seq = 0; + nl_request_msg.n.nlmsg_pid = getpid(); + nl_request_msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); + //Populate the payload's "family header" : which in our case is genlmsghdr + nl_request_msg.g.cmd = CTRL_CMD_GETFAMILY; + nl_request_msg.g.version = 0x1; + //Populate the payload's "netlink attributes" + nl_na = (struct nlattr *) GENLMSG_DATA(&nl_request_msg); + nl_na->nla_type = CTRL_ATTR_FAMILY_NAME; + nl_na->nla_len = strlen(family_name) + 1 + NLA_HDRLEN; + strcpy(NLA_DATA(nl_na), family_name); //Family name length can be upto 16 chars including \0 + + nl_request_msg.n.nlmsg_len += NLMSG_ALIGN(nl_na->nla_len); + + memset(&nl_address, 0, sizeof(nl_address)); + nl_address.nl_family = AF_NETLINK; + + //Send the family ID request message to the netlink controller + nl_rxtx_length = sendto(nl_fd, (char *) &nl_request_msg, nl_request_msg.n.nlmsg_len, + 0, (struct sockaddr *) &nl_address, sizeof(nl_address)); + if (nl_rxtx_length != (int) nl_request_msg.n.nlmsg_len) { + perror("sendto()"); + close(nl_fd); + return -1; + } + //Wait for the response message + nl_rxtx_length = recv(nl_fd, &nl_response_msg, sizeof(nl_response_msg), 0); + if (nl_rxtx_length < 0) { + perror("recv()"); + return -1; + } + + //Validate response message + if (!NLMSG_OK((&nl_response_msg.n), (unsigned int) nl_rxtx_length)) { + fprintf(stderr, "family ID request : invalid message\n"); + return -1; + } + if (nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //error + fprintf(stderr, "family ID request : receive error\n"); + return -1; + } + + //Extract family ID + nl_na = (struct nlattr *) GENLMSG_DATA(&nl_response_msg); + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + +#if 0 + if (nl_na->nla_type == CTRL_ATTR_FAMILY_ID) { + int nl_family_id = *(__u16 *) NLA_DATA(nl_na); + + fprintf(stderr, "family ID get : %u\n", nl_family_id); + } +#endif + + do { + //CTRL_ATTR_VERSION + //CTRL_ATTR_HDRSIZE + //CTRL_ATTR_MAXATTR + //CTRL_ATTR_MCAST_GROUPS + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + } while (*((char *) nl_na) != 0 && nl_na->nla_type != CTRL_ATTR_MCAST_GROUPS); + + // fprintf(stderr, "family Mcast group get : %d len %u\n", nl_na->nla_type, nl_na->nla_len); + // for (unsigned short i = 0;i < nl_na->nla_len;i++) + // { + // printf("%02x ", *(((char *) nl_na)+i)); + // if (i % 16 == 15) printf("\n"); + // } + // printf("\n"); + if (nl_na->nla_type == CTRL_ATTR_MCAST_GROUPS) { + nl_na = (struct nlattr *) NLA_DATA(nl_na); + // fprintf(stderr, "family Mcast group get NLA : %d len %u\n", nl_na->nla_type, nl_na->nla_len); + nl_na = (struct nlattr *) NLA_DATA(nl_na); + if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_ID) { + nl_group_id = *(__u32 *) NLA_DATA(nl_na); + // fprintf(stderr, "family Mcast grp id get : %d\n", nl_group_id); + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + } + if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_NAME) { + // fprintf(stderr, "family Mcast grp name get : %s\n", (char *) NLA_DATA(nl_na)); + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + } +#ifdef THERMAL_GENL_EVENT_GROUP_NAME + nl_na = (struct nlattr *) NLA_DATA(nl_na); + if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_ID) { + nl_group_id = *(__u32 *) NLA_DATA(nl_na); + // fprintf(stderr, "family Mcast grp id get : %d\n", nl_group_id); + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + } + if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_NAME) { + // fprintf(stderr, "family Mcast grp name get : %s\n", (char *) NLA_DATA(nl_na)); + } +#endif + } + return nl_group_id; +} + +static int _get_notify_genl_socket(int nl_fd, int *trip_id, int *up_down) +{ + int nl_rxtx_length; //Number of bytes sent or received via send() or recv() + + //Step 4. Send own custom message + memset(&nl_response_msg, 0, sizeof(nl_response_msg)); + + //Receive reply from kernel + nl_rxtx_length = recv(nl_fd, &nl_response_msg, sizeof(nl_response_msg), 0); + if (nl_rxtx_length < 0) { + perror("recv()"); + return -1; + } + + //Validate response message + if (nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //Error + CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel: NACK Received\n"); + return -1; + } + if (nl_rxtx_length < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel\n"); + return -1; + } + if (!NLMSG_OK((&nl_response_msg.n), (unsigned int) nl_rxtx_length)) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel: Invalid Message\n"); + return -1; + } + + //Parse the reply message + nl_rxtx_length = GENLMSG_PAYLOAD(&nl_response_msg.n); + nl_na = (struct nlattr *) GENLMSG_DATA(&nl_response_msg); + // fprintf(stderr, "Recv Response: type %d len %u\n", nl_na->nla_type, nl_na->nla_len); + +#ifdef THERMAL_GENL_EVENT_GROUP_NAME + if ((nl_response_msg.g.cmd != THERMAL_GENL_EVENT_TZ_TRIP_UP) && + (nl_response_msg.g.cmd != THERMAL_GENL_EVENT_TZ_TRIP_DOWN)) + return -1; + + if (nl_na->nla_type != THERMAL_GENL_ATTR_TZ_TRIP_ID) { + // fprintf(stderr, "Response: type %d len %u\n", nl_na->nla_type, nl_na->nla_len); + // for (unsigned short i = 0;i < nl_na->nla_len;i++) + // { + // printf("%02x ", *(((char *) nl_na)+i)); + // if (i % 16 == 15) printf("\n"); + // } + // printf("\n"); + nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len)); + } + + *trip_id = *(__u32 *) NLA_DATA(nl_na); + *up_down = (nl_response_msg.g.cmd == THERMAL_GENL_EVENT_TZ_TRIP_UP) ? 0 : 1; +#else + tz_evt = (struct thermal_event *) NLA_DATA(nl_na); + *trip_id = tz_evt->trip_id; + *up_down = tz_evt->up_down; +#endif + return 0; +} + +static int _read_cooling_maxstate(void) +{ + CVI_CHAR buf[32]; + char temp_path[128] = "/sys/class/thermal/cooling_device0/max_state"; + int fd = open(temp_path, O_RDONLY); + + if (fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open cooling max_state failed\n"); + return -1; + } + + read(fd, buf, sizeof(buf)); + close(fd); + return atoi(buf); +} + +static int _write_cooling_curstate(int cur_state) +{ + CVI_CHAR buf[32]; + char temp_path[128] = "/sys/class/thermal/cooling_device0/cur_state"; + int fd = open(temp_path, O_WRONLY); + + if (fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open cooling cur_state failed\n"); + return -1; + } + + snprintf(buf, sizeof(buf), "%d", cur_state); + write(fd, buf, sizeof(buf)); + close(fd); + return 0; +} + +static int _write_trip_pointers(int trip_id, int trip_temps, const char *target) +{ + CVI_CHAR buf[32]; + CVI_S32 trip_point_fd = 0; + char temp_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_"; + + strcat(temp_path, target); + temp_path[44] = 0x30 + trip_id; + trip_point_fd = open(temp_path, O_WRONLY); + if (trip_point_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point temp failed\n"); + return -1; + } + snprintf(buf, sizeof(buf), "%d", trip_temps); + write(trip_point_fd, buf, sizeof(buf)); + close(trip_point_fd); + return 0; +} + +static unsigned int _read_trip_pointers(int trip_temps[], unsigned int uplimit) +{ + CVI_CHAR buf[32]; + CVI_S32 trip_point_fd = 0; + char temp_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_temp"; + char type_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_type"; + unsigned int trip_id; + + for (trip_id = 0; trip_id < uplimit; trip_id++) { + temp_path[44] = 0x30 + trip_id; + type_path[44] = 0x30 + trip_id; + trip_point_fd = open(temp_path, O_RDONLY); + if (trip_point_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point temp failed\n"); + break; + } + + read(trip_point_fd, buf, sizeof(buf)); + close(trip_point_fd); + trip_temps[trip_id] = strtol(buf, NULL, 10); + trip_point_fd = open(type_path, O_RDONLY); + if (trip_point_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point type failed\n"); + break; + } + read(trip_point_fd, buf, sizeof(buf)); + close(trip_point_fd); + if (strncmp(buf, "critical", 8) == 0) { + trip_temps[trip_id] = 0; + break; + } + } + + return trip_id; +} + +static int _read_chip_temp(CVI_S32 *temp) +{ + CVI_CHAR buf[32]; + CVI_S32 thermal_fd = 0; + + thermal_fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY); + if (thermal_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "open thermal failed\n"); + return -1; + } + + read(thermal_fd, buf, sizeof(buf)); + close(thermal_fd); + + *temp = strtol(buf, NULL, 10); + return 0; +} + +static void _log_event(FILE *fpEvtlog, int trip_id, int up_down, int fps, int state) +{ + time_t rawtime; + struct tm *info; + char buffer[80]; + char str_buffer[128]; + int ret; + CVI_S32 temp = 0; + + if (!fpEvtlog) + return; + + _read_chip_temp(&temp); + time(&rawtime); + info = localtime(&rawtime); + strftime(buffer, 80, "%y/%m/%d %X", info); + if (trip_id < 0) { + ret = snprintf(str_buffer, 128, "[%s] temp %d\n", buffer, temp); + } else if (fps <= 0) { + ret = snprintf(str_buffer, 128, "[%s] temp %d trip_id %d %s. %sCoolingState %d\n" + , buffer, temp, trip_id, (up_down) ? "down" : "up" + , (fps == 0) ? "Restore FPS, " : "", state); + } else { + ret = snprintf(str_buffer, 128, "[%s] temp %d trip_id %d %s. Set FPS:%d CoolingState %d\n" + , buffer, temp, trip_id, (up_down) ? "down" : "up" + , fps, state); + } + fwrite(str_buffer, ret, 1, fpEvtlog); + fflush(fpEvtlog); +} + +static void _dump_register(FILE *fpEvtlog) +{ + FILE *fpReadReg = NULL; + + if (!fpEvtlog) + return; + + fpReadReg = fopen("/sys/class/cvi-base/base_efuse_shadow", "r"); + if (fpReadReg) { + char str_buffer[128] = "dump register:\n"; + int ahead = 0, read; + + fwrite(str_buffer, strlen(str_buffer), 1, fpEvtlog); + do { + char out_buffer[128]; + int out = 0; + + read = fread(str_buffer, 1, sizeof(str_buffer), fpReadReg); + // printf("fread %d byte\n", read); + for (int j = 0; j < read; j++) { + if ((j%16) == 0) + out = snprintf(out_buffer, 128, "%04X ", j + ahead); + out += snprintf(out_buffer + out, 128 - out, "%02X ", str_buffer[j]); + if ((j%16) == 15) { + out += snprintf(out_buffer + out, 128 - out, "\n"); + fwrite(out_buffer, out, 1, fpEvtlog); + out = 0; + } + } + ahead = read; + } while (read == sizeof(str_buffer)); + fclose(fpReadReg); + fflush(fpEvtlog); + } +} + +void CVI_SYS_RegisterThermalCallback(void (*setFPS)(int)) +{ + callbackFunc = setFPS; +} + +static CVI_VOID *tz_event_handler(CVI_VOID *data) +{ + int nl_fd; //netlink socket's file descriptor + int nl_group_id; + int err; + int trip_temps[10]; + CVI_U32 trip_num; + CVI_S32 init_temp = 0; + int FPS_ARRAY[4] = {0, 15, 5, 1}; + int COOLING_ARRAY[4] = {0, 1, 2, 3}; + int FPS; + CVI_U32 zone; + CVI_U32 i; + int max_state; + char *CtrlEnv = getenv("cvitherm_ctl"); + char *EvtlogEnv = getenv("cvitherm_log"); + char *EvtlogInterval = getenv("cvitherm_interval"); + FILE *fpEvtlog = NULL; + int iEvtlogInterval = (EvtlogInterval) ? atoi(EvtlogInterval) : 10; + + prctl(PR_SET_NAME, "tz_event_handler"); + (void)(data); + + nl_fd = _init_bind_genl_socket(); + if (nl_fd < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "init netlink socket fail\n"); + goto exit_loop; + } + + nl_group_id = _get_mcast_grpid_genl_socket(nl_fd, THERMAL_GENL_FAMILY_NAME); + if (nl_group_id == 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "get mcast grp id fail\n"); + close(nl_fd); + goto exit_loop; + } + + err = setsockopt(nl_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group_id, sizeof(nl_group_id)); + if (err < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "NETLINK_ADD_MEMBERSHIP fail\n"); + close(nl_fd); + goto exit_loop; + } + + if (_read_chip_temp(&init_temp) < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "Read init temp fail\n"); + close(nl_fd); + goto exit_loop; + } + + max_state = _read_cooling_maxstate(); + trip_num = _read_trip_pointers(trip_temps, sizeof(trip_temps)/sizeof(int)); + + if (EvtlogEnv) { + fpEvtlog = fopen(EvtlogEnv, "a"); + _dump_register(fpEvtlog); + } + if (CtrlEnv) { + char *colon = strchr(CtrlEnv, ':'); + char *newString = NULL, *newString2 = NULL; + char *comma = CtrlEnv; + + if (colon) { + newString = strndup(CtrlEnv, colon - CtrlEnv); + comma = colon; + colon = strchr(colon+1, ':'); + if (colon) { + newString2 = strndup(comma, colon - comma); + comma = colon+1; + for (i = 1; comma && (*comma) && i < sizeof(COOLING_ARRAY)/sizeof(int); i++) { + COOLING_ARRAY[i] = atoi(comma); + comma = strchr(comma, ','); + if (comma) + comma++; + } + comma = newString2; + } + comma++; + for (i = 1; comma && (*comma) && i < sizeof(FPS_ARRAY)/sizeof(int); i++) { + FPS_ARRAY[i] = atoi(comma); + comma = strchr(comma, ','); + if (comma) + comma++; + } + comma = newString; + } + for (i = 0; comma && (*comma) && i < trip_num; i++) { + int hyst; + + trip_temps[i] = atoi(comma)*1000; + _write_trip_pointers(i, trip_temps[i], "temp"); + comma = strchr(comma, ','); + if (comma) + comma++; + hyst = atoi(comma)*1000; + _write_trip_pointers(i, hyst, "hyst"); + comma = strchr(comma, ','); + if (comma) + comma++; + } + if (newString) + free(newString); + if (newString2) + free(newString2); + } +#if 0 + printf("FPS: "); + for (i = 0; i < sizeof(FPS_ARRAY)/sizeof(int); i++) { + printf("[%d] ", FPS_ARRAY[i]); + } + printf("\n"); + printf("TRIPs: "); + for (i = 0; i < trip_num; i++) { + printf("[%d] ", trip_temps[i]); + } + printf("\n"); + printf("COOLINGs: "); + for (i = 0; i < sizeof(COOLING_ARRAY)/sizeof(int); i++) { + printf("[%d] ", COOLING_ARRAY[i]); + } + printf("\n"); +#endif + for (zone = 0; zone < trip_num; zone++) { + if (init_temp < trip_temps[zone]) { + break; + } + } + //Not zero zone + if (zone > 1) { + FPS = FPS_ARRAY[zone]; + if (callbackFunc) + callbackFunc(FPS); + } + _write_cooling_curstate((COOLING_ARRAY[zone] > max_state) ? max_state : COOLING_ARRAY[zone]); + CVI_TRACE_SYS(CVI_DBG_INFO, "Read init_temp %d max_state %d trip_point_num %d zone %d\n" + , init_temp, max_state, trip_num, zone); + + while (g_is_thermal_running) { + int trip_id, up_down; + int up_check, down_check; + CVI_U32 next_zone = zone; + int r; + int max_fd = nl_fd; + fd_set readfds; + struct timeval tv; + + FD_ZERO(&readfds); + FD_SET(nl_fd, &readfds); + FD_SET(therm_sockets[1], &readfds); + tv.tv_sec = iEvtlogInterval; + tv.tv_usec = 0; + if (therm_sockets[1] > max_fd) + max_fd = therm_sockets[1]; + r = select(max_fd + 1, &readfds, NULL, NULL, &tv); + + if (r == -1) { + if (errno == EINTR) + continue; + continue; + } else if (r == 0) { + //fprintf(stderr, "%s: select timeout\n", __func__); + _log_event(fpEvtlog, -1, -1, -1, -1); + continue; + } else if (FD_ISSET(therm_sockets[1], &readfds)) { + break; + } + + if (_get_notify_genl_socket(nl_fd, &trip_id, &up_down) < 0) { + CVI_TRACE_SYS(CVI_DBG_ERR, "_get_notify_genl_socket fail\n"); + continue; + } + CVI_TRACE_SYS(CVI_DBG_INFO, "Got trip %d %s\n", trip_id, (up_down) ? "down" : "up"); + down_check = zone - 1; + up_check = zone; + if (down_check == trip_id && up_down == 1) { + next_zone = zone - 1; + } else if (trip_id < down_check && up_down == 1) { + next_zone = trip_id; + } else if (up_check == trip_id && up_down == 0) { + next_zone = zone + 1; + } else if (trip_id > up_check && up_down == 0) { + next_zone = trip_id + 1; + } + if (next_zone != zone && next_zone < sizeof(COOLING_ARRAY)/sizeof(int)) { + int next_state = COOLING_ARRAY[next_zone]; + + if (next_state > max_state) + next_state = max_state; + _write_cooling_curstate(next_state); + FPS = FPS_ARRAY[next_zone]; + if (callbackFunc) { + callbackFunc(FPS); + _log_event(fpEvtlog, trip_id, up_down, FPS, next_state); + } else { + _log_event(fpEvtlog, trip_id, up_down, -1, next_state); + } + zone = next_zone; + } + } + if (fpEvtlog) { + fclose(fpEvtlog); + fpEvtlog = NULL; + } + close(nl_fd); + +exit_loop: + g_is_thermal_running = CVI_FALSE; + pthread_exit(NULL); +} + +CVI_S32 CVI_SYS_StartThermalThread(void) +{ + struct sched_param param; + pthread_attr_t attr; + + if (g_is_thermal_running == CVI_TRUE) { + CVI_TRACE_SYS(CVI_DBG_WARN, "already started\n"); + return CVI_FAILURE; + } + g_is_thermal_running = CVI_TRUE; + socketpair(AF_UNIX, SOCK_SEQPACKET, 0, therm_sockets); + + param.sched_priority = 85; + + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + + pthread_create(&thermal_thread, &attr, (void *)tz_event_handler, NULL); + CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StartThermalThread\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_SYS_StopThermalThread(void) +{ + if (g_is_thermal_running == CVI_FALSE) { + CVI_TRACE_SYS(CVI_DBG_WARN, "not start yet\n"); + return CVI_FAILURE; + } + + g_is_thermal_running = CVI_FALSE; + if (thermal_thread) { + char buf[8]; + + write(therm_sockets[0], buf, 8); + pthread_join(thermal_thread, NULL); + thermal_thread = 0; + } + close(therm_sockets[0]); + close(therm_sockets[1]); + CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StopThermalThread\n"); + return CVI_SUCCESS; +} diff --git a/middleware/v2/modules/sys/src/cvi_tracer.c b/middleware/v2/modules/sys/src/cvi_tracer.c new file mode 100644 index 000000000..692dace2b --- /dev/null +++ b/middleware/v2/modules/sys/src/cvi_tracer.c @@ -0,0 +1,84 @@ +#include "cvi_misc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef ENABLE_TRACE +static int sTraceFD = -1; +pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +static inline void init(void) +{ + +#ifdef ENABLE_TRACE + const char *traceFileName = "/sys/kernel/debug/tracing/trace_marker"; + + sTraceFD = open(traceFileName, O_WRONLY); + if (sTraceFD == -1) { + printf("error opening trace file, errno(%d), %s\n", errno, strerror(errno)); + // sEnabledTags remains zero indicating that no tracing can occur + } +#endif +} + +void CVI_SYS_TraceBegin(const char *name) +{ + +#ifdef ENABLE_TRACE + pthread_mutex_lock(&lock); + if (sTraceFD == -1) { + init(); + } + pthread_mutex_unlock(&lock); + + char buf[1024] = {}; + size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + write(sTraceFD, buf, len); +#pragma GCC diagnostic pop +#endif + +} + +void CVI_SYS_TraceCounter(const char *name, signed int value) +{ + +#ifdef ENABLE_TRACE + char buf[1024] = {}; + + snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + write(sTraceFD, buf, strlen(buf)); +#pragma GCC diagnostic pop +#endif +} + +void CVI_SYS_TraceEnd(void) +{ + +#ifdef ENABLE_TRACE + char buf = 'E'; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + write(sTraceFD, &buf, 1); +#pragma GCC diagnostic pop +#endif + +} + +#ifndef ENABLE_TRACE +#pragma GCC diagnostic pop +#endif diff --git a/middleware/v2/modules/sys/src/cvi_vb.c b/middleware/v2/modules/sys/src/cvi_vb.c new file mode 100644 index 000000000..7ae2e5bcc --- /dev/null +++ b/middleware/v2/modules/sys/src/cvi_vb.c @@ -0,0 +1,552 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hashmap.h" +#include "devmem.h" +#include "cvi_base.h" +#include "cvi_vb.h" +#include "cvi_sys.h" +#include "vb_ioctl.h" +#include "linux/vb_uapi.h" + +#ifndef UNUSED +#define UNUSED(x) ((x) = (x)) +#endif + +typedef struct _pool { + CVI_U64 memBase; + void *vmemBase; + CVI_U32 u32BlkSize; + CVI_U32 u32BlkCnt; + VB_REMAP_MODE_E enRemapMode; +} VB_POOL_S; + +static Hashmap *vbMmapHash; +pthread_mutex_t hash_lock; + +static atomic_bool vb_inited = ATOMIC_VAR_INIT(false); + + +static int _vb_hash_key(void *key) +{ + return (((uintptr_t)key) >> 10); +} + +static bool _vb_hash_equals(void *keyA, void *keyB) +{ + return (keyA == keyB); +} + +VB_BLK CVI_VB_GetBlockwithID(VB_POOL Pool, CVI_U32 u32BlkSize, MOD_ID_E modId) +{ + CVI_TRACE_VB(CVI_DBG_ERR, "Pls use CVI_VB_GetBlock\n"); + UNUSED(Pool); + UNUSED(u32BlkSize); + UNUSED(modId); + return 0; +} + +/************************************************************************** + * Public APIs. + **************************************************************************/ +/* CVI_VB_GetBlock: acquice a vb_blk with specific size from pool. + * + * @param pool: the pool to acquice blk. if VB_INVALID_POOLID, go through common-pool to search. + * @param u32BlkSize: the size of vb_blk to acquire. + * @return: the vb_blk if available. otherwise, VB_INVALID_HANDLE. + */ +VB_BLK CVI_VB_GetBlock(VB_POOL Pool, CVI_U32 u32BlkSize) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_blk_cfg cfg; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return VB_INVALID_HANDLE; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.pool_id = Pool; + cfg.blk_size = u32BlkSize; + s32Ret = vb_ioctl_get_block(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_block fail, ret(%d)\n", s32Ret); + return VB_INVALID_HANDLE; + } + return (VB_BLK)cfg.blk; +} + +/* CVI_VB_ReleaseBlock: release a vb_blk. + * + * @param Block: the vb_blk going to be released. + * @return: CVI_SUCCESS if success; others if fail. + */ +CVI_S32 CVI_VB_ReleaseBlock(VB_BLK Block) +{ + CVI_S32 s32Ret, fd; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + s32Ret = vb_ioctl_release_block(fd, Block); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_release_block fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + return CVI_SUCCESS; +} + +VB_BLK CVI_VB_PhysAddr2Handle(CVI_U64 u64PhyAddr) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_blk_info blk_info; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return VB_INVALID_HANDLE; + } + + memset(&blk_info, 0, sizeof(blk_info)); + blk_info.phy_addr = u64PhyAddr; + s32Ret = vb_ioctl_phys_to_handle(fd, &blk_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_phys_to_handle fail, ret(%d)\n", s32Ret); + return VB_INVALID_HANDLE; + } + return (VB_BLK)blk_info.blk; +} + +CVI_U64 CVI_VB_Handle2PhysAddr(VB_BLK Block) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_blk_info blk_info; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return 0; + } + + memset(&blk_info, 0, sizeof(blk_info)); + blk_info.blk = Block; + s32Ret = vb_ioctl_get_blk_info(fd, &blk_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret); + return 0; + } + return (CVI_U64)blk_info.phy_addr; +} + +VB_POOL CVI_VB_Handle2PoolId(VB_BLK Block) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_blk_info blk_info; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return VB_INVALID_POOLID; + } + + memset(&blk_info, 0, sizeof(blk_info)); + blk_info.blk = Block; + s32Ret = vb_ioctl_get_blk_info(fd, &blk_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret); + return VB_INVALID_POOLID; + } + return (VB_POOL)blk_info.pool_id; +} + +CVI_S32 CVI_VB_InquireUserCnt(VB_BLK Block, CVI_U32 *pCnt) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_blk_info blk_info; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, pCnt); + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + memset(&blk_info, 0, sizeof(blk_info)); + blk_info.blk = Block; + s32Ret = vb_ioctl_get_blk_info(fd, &blk_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + *pCnt = blk_info.usr_cnt; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VB_Init(void) +{ + CVI_S32 s32Ret, fd; + bool expect = false; + + // Only init once until exit. + if (!atomic_compare_exchange_strong(&vb_inited, &expect, true)) + return CVI_SUCCESS; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + s32Ret = vb_ioctl_init(fd); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_init fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VB_Exit(void) +{ + CVI_S32 s32Ret, fd; + bool expect = true; + + // Only exit once. + if (!atomic_compare_exchange_strong(&vb_inited, &expect, false)) + return CVI_SUCCESS; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + s32Ret = vb_ioctl_exit(fd); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_exit fail, ret(%d)\n", s32Ret); + base_dev_close(); + return CVI_FAILURE; + } + + base_dev_close(); + return CVI_SUCCESS; +} + +VB_POOL CVI_VB_CreatePool(VB_POOL_CONFIG_S *pstVbPoolCfg) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_pool_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbPoolCfg); + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.blk_size = pstVbPoolCfg->u32BlkSize; + cfg.blk_cnt = pstVbPoolCfg->u32BlkCnt; + cfg.remap_mode = pstVbPoolCfg->enRemapMode; + strncpy(cfg.pool_name, pstVbPoolCfg->acName, VB_POOL_NAME_LEN - 1); + + s32Ret = vb_ioctl_create_pool(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_create_pool fail, ret(%d)\n", s32Ret); + return VB_INVALID_POOLID; + } + + return (VB_POOL)cfg.pool_id; +} + +VB_POOL CVI_VB_CreateExPool(VB_POOL_CONFIG_EX_S *pstVbPoolExCfg) +{ + CVI_S32 s32Ret, fd, i; + struct cvi_vb_pool_ex_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbPoolExCfg); + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.blk_cnt = pstVbPoolExCfg->u32BlkCnt; + for (i = 0; i < VB_POOL_MAX_BLK; i++) { + cfg.au64PhyAddr[i][0] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[0]; + cfg.au64PhyAddr[i][1] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[1]; + cfg.au64PhyAddr[i][2] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[2]; + } + + s32Ret = vb_ioctl_create_ex_pool(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_create_ex_pool fail, ret(%d)\n", s32Ret); + return VB_INVALID_POOLID; + } + + return (VB_POOL)cfg.pool_id; +} + +CVI_S32 CVI_VB_DestroyPool(VB_POOL Pool) +{ + CVI_S32 s32Ret, fd; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + s32Ret = vb_ioctl_destroy_pool(fd, Pool); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_destroy_pool fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + if (vbMmapHash && hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool)) + CVI_VB_MunmapPool(Pool); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VB_SetConfig(const VB_CONFIG_S *pstVbConfig) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_cfg cfg; + CVI_U32 i; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbConfig); + if (pstVbConfig->u32MaxPoolCnt > VB_COMM_POOL_MAX_CNT + || pstVbConfig->u32MaxPoolCnt == 0) { + CVI_TRACE_VB(CVI_DBG_ERR, "Invalid vb u32MaxPoolCnt(%d)\n", + pstVbConfig->u32MaxPoolCnt); + return CVI_ERR_VB_ILLEGAL_PARAM; + } + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.comm_pool_cnt = pstVbConfig->u32MaxPoolCnt; + for (i = 0; i < cfg.comm_pool_cnt; ++i) { + cfg.comm_pool[i].blk_size = pstVbConfig->astCommPool[i].u32BlkSize; + cfg.comm_pool[i].blk_cnt = pstVbConfig->astCommPool[i].u32BlkCnt; + cfg.comm_pool[i].remap_mode = pstVbConfig->astCommPool[i].enRemapMode; + strncpy(cfg.comm_pool[i].pool_name, + pstVbConfig->astCommPool[i].acName, VB_POOL_NAME_LEN - 1); + } + s32Ret = vb_ioctl_set_config(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_set_config fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_VB_GetConfig(VB_CONFIG_S *pstVbConfig) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_cfg cfg; + CVI_U32 i; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbConfig); + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return CVI_ERR_VB_NOTREADY; + } + + s32Ret = vb_ioctl_get_config(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_config fail, ret(%d)\n", s32Ret); + return CVI_FAILURE; + } + + memset(pstVbConfig, 0, sizeof(*pstVbConfig)); + pstVbConfig->u32MaxPoolCnt = cfg.comm_pool_cnt; + for (i = 0; i < cfg.comm_pool_cnt; ++i) { + pstVbConfig->astCommPool[i].u32BlkSize = cfg.comm_pool[i].blk_size; + pstVbConfig->astCommPool[i].u32BlkCnt = cfg.comm_pool[i].blk_cnt; + pstVbConfig->astCommPool[i].enRemapMode = cfg.comm_pool[i].remap_mode; + strncpy(pstVbConfig->astCommPool[i].acName, cfg.comm_pool[i].pool_name, + MAX_VB_POOL_NAME_LEN - 1); + } + return CVI_SUCCESS; +} + +/* CVI_VB_MmapPool - mmap the whole pool to get virtual-address + * + * @param Pool: pool id + * @return CVI_SUCCESS if success; others if fail + */ +CVI_S32 CVI_VB_MmapPool(VB_POOL Pool) +{ + CVI_S32 s32Ret, fd; + struct cvi_vb_pool_cfg cfg; + VB_POOL_S *pstVbPool = NULL; + void *vaddr; + + if (!vbMmapHash) { + vbMmapHash = hashmapCreate(20, _vb_hash_key, _vb_hash_equals); + pthread_mutex_init(&hash_lock, NULL); + } + + pthread_mutex_lock(&hash_lock); + pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool); + if (pstVbPool) { + pthread_mutex_unlock(&hash_lock); + return CVI_SUCCESS; + } + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_NOTREADY; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.pool_id = Pool; + + s32Ret = vb_ioctl_get_pool_cfg(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_pool_cfg fail, ret(%d)\n", s32Ret); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_ILLEGAL_PARAM; + } + + pstVbPool = (VB_POOL_S *)malloc(sizeof(*pstVbPool)); + if (pstVbPool == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "malloc failed.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_NOMEM; + } + + if (cfg.remap_mode == VB_REMAP_MODE_CACHED) + vaddr = CVI_SYS_MmapCache(cfg.mem_base, cfg.blk_cnt * cfg.blk_size); + else + vaddr = CVI_SYS_Mmap(cfg.mem_base, cfg.blk_cnt * cfg.blk_size); + if (vaddr == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "mmap failed.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_NOMEM; + } + + pstVbPool->vmemBase = vaddr; + pstVbPool->memBase = cfg.mem_base; + pstVbPool->u32BlkSize = cfg.blk_size; + pstVbPool->u32BlkCnt = cfg.blk_cnt; + pstVbPool->enRemapMode = cfg.remap_mode; + + hashmapPut(vbMmapHash, (void *)(uintptr_t)Pool, (void *)pstVbPool); + pthread_mutex_unlock(&hash_lock); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VB_MunmapPool(VB_POOL Pool) +{ + VB_POOL_S *pstVbPool = NULL; + + if (vbMmapHash == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n"); + return CVI_ERR_VB_NOTREADY; + } + + pthread_mutex_lock(&hash_lock); + pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool); + if (pstVbPool == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_NOTREADY; + } + + if (CVI_SYS_Munmap(pstVbPool->vmemBase, pstVbPool->u32BlkCnt * pstVbPool->u32BlkSize) != CVI_SUCCESS) { + CVI_TRACE_VB(CVI_DBG_ERR, "unmap failed.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_ILLEGAL_PARAM; + } + + hashmapRemove(vbMmapHash, (void *)(uintptr_t)Pool); + free(pstVbPool); + pthread_mutex_unlock(&hash_lock); + + if (hashmapSize(vbMmapHash) == 0) { + hashmapFree(vbMmapHash); + vbMmapHash = NULL; + pthread_mutex_destroy(&hash_lock); + } + return CVI_SUCCESS; +} + +/* CVI_VB_GetBlockVirAddr - to get virtual-address of the Block + * + * @param Pool: pool id + * @param Block: block id + * @param ppVirAddr: virtual-address of the Block, cached if pool create with VB_REMAP_MODE_CACHED + * @return CVI_SUCCESS if success; others if fail + */ +CVI_S32 CVI_VB_GetBlockVirAddr(VB_POOL Pool, VB_BLK Block, void **ppVirAddr) +{ + VB_POOL poolId; + CVI_U64 phyAddr; + VB_POOL_S *pstVbPool = NULL; + + MOD_CHECK_NULL_PTR(CVI_ID_VB, ppVirAddr); + + if (vbMmapHash == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n"); + return CVI_ERR_VB_NOTREADY; + } + + pthread_mutex_lock(&hash_lock); + pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool); + if (pstVbPool == NULL) { + CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n"); + pthread_mutex_unlock(&hash_lock); + return CVI_ERR_VB_NOTREADY; + } + pthread_mutex_unlock(&hash_lock); + + poolId = CVI_VB_Handle2PoolId(Block); + if (poolId != Pool) { + CVI_TRACE_VB(CVI_DBG_ERR, "Blk's Pool(%d) isn't given one(%d).\n", poolId, Pool); + return CVI_ERR_VB_ILLEGAL_PARAM; + } + + phyAddr = CVI_VB_Handle2PhysAddr(Block); + if (!phyAddr) { + CVI_TRACE_VB(CVI_DBG_ERR, "phyAddr = 0.\n"); + return CVI_ERR_VB_ILLEGAL_PARAM; + } + + *ppVirAddr = pstVbPool->vmemBase + (phyAddr - pstVbPool->memBase); + return CVI_SUCCESS; +} + +CVI_VOID CVI_VB_PrintPool(VB_POOL Pool) +{ + CVI_S32 s32Ret, fd; + + fd = get_base_fd(); + if (fd == -1) { + CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n"); + return; + } + s32Ret = vb_ioctl_print_pool(fd, Pool); + if (s32Ret != CVI_SUCCESS) + CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_print_pool fail, ret(%d)\n", s32Ret); +} + diff --git a/middleware/v2/modules/sys/src/devmem.c b/middleware/v2/modules/sys/src/devmem.c new file mode 100644 index 000000000..4112da711 --- /dev/null +++ b/middleware/v2/modules/sys/src/devmem.c @@ -0,0 +1,90 @@ +/* + ** read/write phy addr in userspace + ** open /dev/mem + ** taiqiang.cao@bitmain.com + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devmem.h" + +int devm_open(void) +{ + int fd; + + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + printf("cannot open '/dev/mem'\n"); + goto open_err; + } + + return fd; +open_err: + return -1; +} + +int devm_open_cached(void) +{ + int fd; + + fd = open("/dev/mem", O_RDWR); + if (fd == -1) { + printf("cannot open '/dev/mem'\n"); + goto open_err; + } + + return fd; +open_err: + return -1; +} + +void devm_close(int fd) +{ + if (fd) + close(fd); +} + +void *devm_map(int fd, uint64_t phy_addr, size_t len) +{ + off_t offset; + void *map_base; + uint32_t padding; + + offset = phy_addr & ~(sysconf(_SC_PAGE_SIZE) - 1); + padding = phy_addr - offset; + + map_base = mmap(NULL, len + padding, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, offset); + + if (map_base == MAP_FAILED) { + perror("mmap failed\n"); + printf("phy_addr = %#"PRIx64", length = %zu\t, mapped memory length = %zu\t, pa_offset = %#"PRIx64"\n" + , phy_addr, len, len + padding, (intmax_t)offset); + goto mmap_err; + } + + return map_base + padding; + +mmap_err: + return NULL; +} + +void devm_unmap(void *virt_addr, size_t len) +{ + uint64_t addr; + + /* page align */ + addr = (((uint64_t)(uintptr_t)virt_addr) & ~(sysconf(_SC_PAGE_SIZE) - 1)); + + munmap((void *)(uintptr_t)addr, len + (unsigned long) virt_addr - addr); +} diff --git a/middleware/v2/modules/sys/src/hashmap.c b/middleware/v2/modules/sys/src/hashmap.c new file mode 100644 index 000000000..3ab196760 --- /dev/null +++ b/middleware/v2/modules/sys/src/hashmap.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hashmap.h" +#include +#include +#include +#include +#include +#include +#include + +Hashmap *hashmapCreate(size_t initialCapacity, int (*hash)(void *key), bool (*equals)(void *keyA, void *keyB)) +{ + assert(hash != NULL); + assert(equals != NULL); + + Hashmap *map = malloc(sizeof(Hashmap)); + // 0.75 load factor. + size_t minimumBucketCount = initialCapacity * 4 / 3; + + if (map == NULL) { + return NULL; + } + + map->bucketCount = 1; + while (map->bucketCount <= minimumBucketCount) { + // Bucket count must be power of 2. + map->bucketCount <<= 1; + } + map->buckets = calloc(map->bucketCount, sizeof(Entry *)); + if (map->buckets == NULL) { + free(map); + return NULL; + } + + map->size = 0; + map->hash = hash; + map->equals = equals; + + pthread_mutex_init(&map->lock, NULL); + + return map; +} + +/** + * Hashes the given key. + */ +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +static inline int hashKey(Hashmap *map, void *key) +{ + int h = map->hash(key); + + // We apply this secondary hashing discovered by Doug Lea to defend + // against bad hashes. + h += ~(h << 9); + h ^= (((unsigned int)h) >> 14); + h += (h << 4); + h ^= (((unsigned int)h) >> 10); + + return h; +} + +size_t hashmapSize(Hashmap *map) +{ + return map->size; +} + +static inline size_t calculateIndex(size_t bucketCount, int hash) +{ + return ((size_t)hash) & (bucketCount - 1); +} + +static void expandIfNecessary(Hashmap *map) +{ + // If the load factor exceeds 0.75... + if (map->size > (map->bucketCount * 3 / 4)) { + // Start off with a 0.33 load factor. + size_t newBucketCount = map->bucketCount << 1; + Entry **newBuckets = calloc(newBucketCount, sizeof(Entry *)); + + if (newBuckets == NULL) { + // Abort expansion. + return; + } + + // Move over existing entries. + size_t i; + + for (i = 0; i < map->bucketCount; i++) { + Entry *entry = map->buckets[i]; + + while (entry != NULL) { + Entry *next = entry->next; + size_t index = calculateIndex(newBucketCount, entry->hash); + + entry->next = newBuckets[index]; + newBuckets[index] = entry; + entry = next; + } + } + // Copy over internals. + free(map->buckets); + map->buckets = newBuckets; + map->bucketCount = newBucketCount; + } +} + +void hashmapLock(Hashmap *map) +{ + pthread_mutex_lock(&map->lock); +} + +void hashmapUnlock(Hashmap *map) +{ + pthread_mutex_unlock(&map->lock); +} + +void hashmapFree(Hashmap *map) +{ + size_t i; + + for (i = 0; i < map->bucketCount; i++) { + Entry *entry = map->buckets[i]; + + while (entry != NULL) { + Entry *next = entry->next; + + free(entry); + entry = next; + } + } + free(map->buckets); + pthread_mutex_destroy(&map->lock); + free(map); +} + +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +/* FIXME: relies on signed integer overflow, which is undefined behavior */ +int hashmapHash(void *key, size_t keySize) +{ + int h = keySize; + char *data = (char *)key; + size_t i; + + for (i = 0; i < keySize; i++) { + h = h * 31 + *data; + data++; + } + return h; +} + +static Entry *createEntry(void *key, int hash, void *value) +{ + Entry *entry = malloc(sizeof(Entry)); + + if (entry == NULL) { + return NULL; + } + entry->key = key; + entry->hash = hash; + entry->value = value; + entry->next = NULL; + return entry; +} + +static inline bool equalKeys(void *keyA, int hashA, void *keyB, int hashB, bool (*equals)(void *, void *)) +{ + if (keyA == keyB) + return true; + if (hashA != hashB) + return false; + return equals(keyA, keyB); +} + +void *hashmapPut(Hashmap *map, void *key, void *value) +{ + int hash = hashKey(map, key); + size_t index = calculateIndex(map->bucketCount, hash); + Entry **p = &(map->buckets[index]); + + while (true) { + Entry *current = *p; + + // Add a new entry. + if (current == NULL) { + *p = createEntry(key, hash, value); + if (*p == NULL) { + errno = ENOMEM; + return NULL; + } + map->size++; + expandIfNecessary(map); + return NULL; + } + // Replace existing entry. + if (equalKeys(current->key, current->hash, key, hash, map->equals)) { + void *oldValue = current->value; + + current->value = value; + return oldValue; + } + // Move to next entry. + p = ¤t->next; + } +} + +void *hashmapGet(Hashmap *map, void *key) +{ + int hash = hashKey(map, key); + size_t index = calculateIndex(map->bucketCount, hash); + Entry *entry = map->buckets[index]; + + while (entry != NULL) { + if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) { + return entry->value; + } + entry = entry->next; + } + + return NULL; +} + +bool hashmapContainsKey(Hashmap *map, void *key) +{ + int hash = hashKey(map, key); + size_t index = calculateIndex(map->bucketCount, hash); + Entry *entry = map->buckets[index]; + + while (entry != NULL) { + if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) { + return true; + } + entry = entry->next; + } + return false; +} + +void *hashmapMemoize(Hashmap *map, void *key, void *(*initialValue)(void *key, void *context), void *context) +{ + int hash = hashKey(map, key); + size_t index = calculateIndex(map->bucketCount, hash); + Entry **p = &(map->buckets[index]); + + while (true) { + Entry *current = *p; + // Add a new entry. + if (current == NULL) { + *p = createEntry(key, hash, NULL); + if (*p == NULL) { + errno = ENOMEM; + return NULL; + } + void *value = initialValue(key, context); + (*p)->value = value; + map->size++; + expandIfNecessary(map); + return value; + } + // Return existing value. + if (equalKeys(current->key, current->hash, key, hash, map->equals)) { + return current->value; + } + // Move to next entry. + p = ¤t->next; + } +} + +void *hashmapRemove(Hashmap *map, void *key) +{ + int hash = hashKey(map, key); + size_t index = calculateIndex(map->bucketCount, hash); + // Pointer to the current entry. + Entry **p = &(map->buckets[index]); + Entry *current; + + while ((current = *p) != NULL) { + if (equalKeys(current->key, current->hash, key, hash, map->equals)) { + void *value = current->value; + *p = current->next; + free(current); + map->size--; + return value; + } + p = ¤t->next; + } + return NULL; +} + +void hashmapForEach(Hashmap *map, bool (*callback)(void *key, void *value, void *context), void *context) +{ + size_t i; + + for (i = 0; i < map->bucketCount; i++) { + Entry *entry = map->buckets[i]; + + while (entry != NULL) { + Entry *next = entry->next; + + if (!callback(entry->key, entry->value, context)) { + return; + } + entry = next; + } + } +} + +size_t hashmapCurrentCapacity(Hashmap *map) +{ + size_t bucketCount = map->bucketCount; + + return bucketCount * 3 / 4; +} + +size_t hashmapCountCollisions(Hashmap *map) +{ + size_t collisions = 0; + size_t i; + + for (i = 0; i < map->bucketCount; i++) { + Entry *entry = map->buckets[i]; + + while (entry != NULL) { + if (entry->next != NULL) { + collisions++; + } + entry = entry->next; + } + } + return collisions; +} + +int hashmapIntHash(void *key) +{ + // Return the key value itself. + return *((int *)key); +} + +bool hashmapIntEquals(void *keyA, void *keyB) +{ + int a = *((int *)keyA); + int b = *((int *)keyB); + + return a == b; +} diff --git a/middleware/v2/modules/sys/src/peri.c b/middleware/v2/modules/sys/src/peri.c new file mode 100644 index 000000000..efe6d5a3a --- /dev/null +++ b/middleware/v2/modules/sys/src/peri.c @@ -0,0 +1,205 @@ +/*************************************************************************** + * Copyright (C) CVITEK, Inc - All Rights Reserved + * Unauthorized copying of this file, via any medium is strictly prohibited + * Proprietary and confidential + * Written by Jammy Huang , Nov. 2019 + **************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +int i2c_file = -1; +int i2c_slave_addr; + +int i2cInit(uint8_t i2c_bus, uint8_t slave_addr) +{ +#define FILENAME_SIZE 12 + char filename[FILENAME_SIZE]; + char writeSize = 0; + + writeSize = snprintf(filename, FILENAME_SIZE, "/dev/i2c-%d", i2c_bus); + if (writeSize > FILENAME_SIZE) { + perror("Please enlarge the space of filename"); + } + + i2c_file = open(filename, O_RDWR); + if (i2c_file < 0) { + /* ERROR HANDLING: you can check errno to see what went wrong */ + perror("Failed to open the i2c bus"); + return -1; + } + + i2c_slave_addr = slave_addr; + return 0; +} + +void i2cExit(void) +{ + close(i2c_file); +} + +int i2cRead(uint16_t addr, unsigned int addr_nbytes, uint8_t *buffer, + unsigned int data_nbytes) +{ + if (addr_nbytes > 2) { + printf("i2c addr length at most 2.\n"); + return -1; + } + + uint8_t tx[2]; + + if (addr_nbytes == 2) { + tx[0] = addr >> 8; + tx[1] = addr & 0xff; + } else { + tx[0] = addr & 0xff; + } + + struct i2c_msg messages[] = { + { + .addr = i2c_slave_addr, + .flags = 0, + .buf = tx, + .len = addr_nbytes, + }, + { + .addr = i2c_slave_addr, + .flags = I2C_M_RD | I2C_M_NOSTART, + .buf = buffer, + .len = data_nbytes, + }, + }; + + struct i2c_rdwr_ioctl_data payload = { + .msgs = messages, + .nmsgs = ARRAY_SIZE(messages), + }; + + if (ioctl(i2c_file, I2C_RDWR, &payload) < 0) { + /* ERROR HANDLING: i2c transaction failed */ + printf("Failed to read from the i2c bus.\n"); + return -1; + } + return 0; +} + +int i2cWrite(uint16_t addr, unsigned int addr_nbytes, uint8_t *buffer, + unsigned int data_nbytes) +{ + if (addr_nbytes > 2) { + printf("i2c addr length at most 2.\n"); + return -1; + } + + uint16_t len = addr_nbytes + data_nbytes; + uint8_t *tx = malloc(len); + + if (addr_nbytes == 2) { + tx[0] = addr >> 8; + tx[1] = addr & 0xff; + memcpy(&tx[2], buffer, data_nbytes); + } else { + tx[0] = addr & 0xff; + memcpy(&tx[1], buffer, data_nbytes); + } + + struct i2c_msg messages[] = { + { + .addr = i2c_slave_addr, + .flags = 0, + .buf = tx, + .len = len, + }, + }; + + struct i2c_rdwr_ioctl_data payload = { + .msgs = messages, + .nmsgs = ARRAY_SIZE(messages), + }; + + if (ioctl(i2c_file, I2C_RDWR, &payload) < 0) { + /* ERROR HANDLING: i2c transaction failed */ + printf("Failed to write to the i2c bus.\n"); + free(tx); + return -1; + } + + free(tx); + return 0; +} + +// TODO: refine +#define ISP_BASE_ADDR 0x0A000000 +#define ISP_REG_RANGE 0x80000 + +static void *reg_base; +static int devm_fd = -1; + +int regInit(void) +{ + if (devm_fd != -1) + return -EMFILE; + + devm_fd = devm_open(); + if (devm_fd < 0) + return -1; + reg_base = devm_map(devm_fd, ISP_BASE_ADDR, ISP_REG_RANGE); + return 0; +} + +int regExit(void) +{ + if (reg_base != 0) + devm_unmap(reg_base, ISP_REG_RANGE); + if (devm_fd) + devm_close(devm_fd); + devm_fd = -1; + return 0; +} + +uint32_t regRead(uint32_t addr) +{ + return *(uint32_t *)(reg_base + addr - ISP_BASE_ADDR); +} + +void regWrite(uint32_t addr, uint32_t data) +{ + *(uint32_t *)(reg_base + addr - ISP_BASE_ADDR) = data; +} + +void regReadBurst(uint32_t addr, uint32_t *buffer, unsigned int ndws) +{ + for (unsigned int i = 0; i < ndws; ++i) + buffer[i] = regRead(addr + (i << 2)); +} + +void regWriteBurst(uint32_t addr, uint32_t *buffer, unsigned int ndws) +{ + for (unsigned int i = 0; i < ndws; ++i) + regWrite(addr + (i << 2), buffer[i]); +} + +void regWriteMask(uint32_t addr, uint32_t data, uint32_t mask) +{ + uint32_t value; + + value = regRead(addr) & ~mask; + value |= (data & mask); + regWrite(addr, value); +} diff --git a/middleware/v2/modules/sys/src/sys_ioctl.c b/middleware/v2/modules/sys/src/sys_ioctl.c new file mode 100644 index 000000000..076afb386 --- /dev/null +++ b/middleware/v2/modules/sys/src/sys_ioctl.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include +#include "sys_ioctl.h" + +#define SYS_S_CTRL_VALUE(_fd, _cfg, _ioctl)\ + do {\ + struct sys_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = _cfg;\ + if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define SYS_S_CTRL_VALUE64(_fd, _cfg, _ioctl)\ + do {\ + struct sys_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value64 = _cfg;\ + if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\ + perror("SYS_IOC_S_CTRL\n");\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define SYS_S_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct sys_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\ + perror("SYS_IOC_S_CTRL\n");\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define SYS_G_CTRL_VALUE(_fd, _out, _ioctl)\ + do {\ + struct sys_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = 0;\ + if (ioctl(_fd, SYS_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "SYS_IOC_G_CTRL - %s NG\n", __func__);\ + perror("SYS_IOC_G_CTRL\n");\ + return -1;\ + } \ + *_out = ec1.value;\ + return 0;\ + } while (0) + +#define SYS_G_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct sys_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, SYS_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "SYS_IOC_G_CTRL - %s NG\n", __func__);\ + perror("SYS_IOC_G_CTRL\n");\ + return -1;\ + } \ + return 0;\ + } while (0) + +int sys_set_vivpssmode(int fd, const VI_VPSS_MODE_S *cfg) +{ + SYS_S_CTRL_PTR(fd, cfg, SYS_IOCTL_SET_VIVPSSMODE); +} + +int sys_set_vpssmode(int fd, VPSS_MODE_E val) +{ + SYS_S_CTRL_VALUE(fd, val, SYS_IOCTL_SET_VPSSMODE); +} + +int sys_set_vpssmodeex(int fd, const VPSS_MODE_S *cfg) +{ + SYS_S_CTRL_PTR(fd, cfg, SYS_IOCTL_SET_VPSSMODE_EX); +} + +int sys_set_sys_init(int fd) +{ + SYS_S_CTRL_VALUE(fd, 0, SYS_IOCTL_SET_SYS_INIT); +} + +int sys_get_vivpssmode(int fd, const VI_VPSS_MODE_S *cfg) +{ + SYS_G_CTRL_PTR(fd, cfg, SYS_IOCTL_GET_VIVPSSMODE); +} + +int sys_get_vpssmode(int fd, VPSS_MODE_E *val) +{ + SYS_G_CTRL_VALUE(fd, val, SYS_IOCTL_GET_VPSSMODE); +} + +int sys_get_vpssmodeex(int fd, const VPSS_MODE_S *cfg) +{ + SYS_G_CTRL_PTR(fd, cfg, SYS_IOCTL_GET_VPSSMODE_EX); +} + +int sys_get_sys_init(int fd, CVI_U32 *val) +{ + SYS_G_CTRL_VALUE(fd, val, SYS_IOCTL_GET_SYS_INIT); +} diff --git a/middleware/v2/modules/sys/src/vb_ioctl.c b/middleware/v2/modules/sys/src/vb_ioctl.c new file mode 100644 index 000000000..4af30675a --- /dev/null +++ b/middleware/v2/modules/sys/src/vb_ioctl.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include "vb_ioctl.h" + +#define VB_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct vb_ext_control ec1;\ + int ret;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\ + if (ret < 0)\ + fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\ + return ret;\ + } while (0) + +#define VB_CTRL_S_VALUE(_fd, _cfg, _ioctl)\ + do {\ + struct vb_ext_control ec1;\ + int ret;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = _cfg;\ + ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\ + if (ret < 0)\ + fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\ + return ret;\ + } while (0) + +#define VB_CTRL_S_VALUE64(_fd, _cfg, _ioctl)\ + do {\ + struct vb_ext_control ec1;\ + int ret;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value64 = _cfg;\ + ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\ + if (ret < 0)\ + fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\ + return ret;\ + } while (0) + +#define VB_CTRL_G_VALUE(_fd, _out, _ioctl)\ + do {\ + struct vb_ext_control ec1;\ + int ret;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = 0;\ + ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\ + if (ret < 0)\ + fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\ + *_out = ec1.value;\ + return ret;\ + } while (0) + +int vb_ioctl_set_config(int fd, struct cvi_vb_cfg *cfg) +{ + VB_CTRL_PTR(fd, cfg, VB_IOCTL_SET_CONFIG); +} + +int vb_ioctl_get_config(int fd, struct cvi_vb_cfg *cfg) +{ + VB_CTRL_PTR(fd, cfg, VB_IOCTL_GET_CONFIG); +} + +int vb_ioctl_init(int fd) +{ + VB_CTRL_PTR(fd, NULL, VB_IOCTL_INIT); +} + +int vb_ioctl_exit(int fd) +{ + VB_CTRL_PTR(fd, NULL, VB_IOCTL_EXIT); +} + +int vb_ioctl_create_pool(int fd, struct cvi_vb_pool_cfg *cfg) +{ + VB_CTRL_PTR(fd, cfg, VB_IOCTL_CREATE_POOL); +} + +int vb_ioctl_create_ex_pool(int fd, struct cvi_vb_pool_ex_cfg *cfg) +{ + VB_CTRL_PTR(fd, cfg, VB_IOCTL_CREATE_EX_POOL); +} + +int vb_ioctl_destroy_pool(int fd, VB_POOL poolId) +{ + VB_CTRL_S_VALUE(fd, poolId, VB_IOCTL_DESTROY_POOL); +} + +int vb_ioctl_phys_to_handle(int fd, struct cvi_vb_blk_info *blk_info) +{ + VB_CTRL_PTR(fd, blk_info, VB_IOCTL_PHYS_TO_HANDLE); +} + +int vb_ioctl_get_blk_info(int fd, struct cvi_vb_blk_info *blk_info) +{ + VB_CTRL_PTR(fd, blk_info, VB_IOCTL_GET_BLK_INFO); +} + +int vb_ioctl_get_pool_cfg(int fd, struct cvi_vb_pool_cfg *pool_cfg) +{ + VB_CTRL_PTR(fd, pool_cfg, VB_IOCTL_GET_POOL_CFG); +} + +int vb_ioctl_get_block(int fd, struct cvi_vb_blk_cfg *blk_cfg) +{ + VB_CTRL_PTR(fd, blk_cfg, VB_IOCTL_GET_BLOCK); +} + +int vb_ioctl_release_block(int fd, VB_BLK blk) +{ + VB_CTRL_S_VALUE64(fd, blk, VB_IOCTL_RELEASE_BLOCK); +} + +int vb_ioctl_get_pool_max_cnt(int fd, CVI_U32 *vb_max_pools) +{ + VB_CTRL_G_VALUE(fd, vb_max_pools, VB_IOCTL_GET_POOL_MAX_CNT); +} + +int vb_ioctl_print_pool(int fd, VB_POOL poolId) +{ + VB_CTRL_S_VALUE(fd, poolId, VB_IOCTL_PRINT_POOL); +} + +int vb_ioctl_unit_test(int fd, CVI_U32 op) +{ + VB_CTRL_S_VALUE(fd, op, VB_IOCTL_UNIT_TEST); +} diff --git a/middleware/v2/modules/vdec/Makefile b/middleware/v2/modules/vdec/Makefile new file mode 100644 index 000000000..354a96df3 --- /dev/null +++ b/middleware/v2/modules/vdec/Makefile @@ -0,0 +1,44 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(PWD)/include +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libvdec.a +TARGET_SO = $(MW_LIB)/libvdec.so + +EXTRA_CFLAGS = $(INCS) + +ifeq ($(DEBUG), 1) +EXTRA_CFLAGS += -g -O0 +endif + +.PHONY : clean all +all : prepare $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $@ $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $@) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) $(LEXTRA_LDFLAGS) -o $@ --start-group $(OBJS) $(LIBS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $@) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +prepare: + @echo "SDK_VER = ${SDK_VER}" + @head=`git rev-parse --verify --short HEAD` + @date=`git show -s --format=%cd --date=short ${head}` + +-include $(DEPS) diff --git a/middleware/v2/modules/vdec/src/cvi_vdec.c b/middleware/v2/modules/vdec/src/cvi_vdec.c new file mode 100644 index 000000000..a0099d476 --- /dev/null +++ b/middleware/v2/modules/vdec/src/cvi_vdec.c @@ -0,0 +1,272 @@ + +#include +#include +#include + +#include "devmem.h" +#include "cvi_vdec.h" + +#include + +#define UNUSED(x) ((void)(x)) + +vdec_dbg vdecDbg; +static CVI_S32 s32DevmemFd = -1; +static CVI_U32 u32ChannelCreatedCnt; + +typedef struct _VIDEO_FRAME_INFO_EX_S { + const VIDEO_FRAME_INFO_S *pstFrame; + CVI_S32 s32MilliSec; +} VIDEO_FRAME_INFO_EX_S; + +typedef struct _VDEC_STREAM_EX_S { + const VDEC_STREAM_S *pstStream; + CVI_S32 s32MilliSec; +} VDEC_STREAM_EX_S; + +CVI_S32 s32VdecFd[VDEC_MAX_CHN_NUM] = {0}; + +CVI_S32 CVI_VDEC_CreateChn(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pstAttr) +{ + CVI_S32 s32Ret = CVI_FAILURE; + CVI_CHAR devName[255]; + + if (s32DevmemFd == -1) { + s32DevmemFd = devm_open_cached(); + if (s32DevmemFd < 0) + return CVI_FAILURE; + } + + if (s32VdecFd[VdChn] == 0) { + sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn); + s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC); + CVI_VDEC_TRACE("open device (%s) fd: %d\n", devName, s32VdecFd[VdChn]); + } + + if (s32VdecFd[VdChn] > 0) { + s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_CREATE_CHN, pstAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_VDEC_ERR("ioctl CVI_VC_VDEC_CREATE_CHN fail with %d\n", s32Ret); + return s32Ret; + } + u32ChannelCreatedCnt += 1; + } else { + CVI_VDEC_ERR("fail to open device %s\n", devName); + s32Ret = CVI_FAILURE; + } + + return s32Ret; +} + +CVI_S32 CVI_VDEC_DestroyChn(VDEC_CHN VdChn) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (s32VdecFd[VdChn] > 0) { + s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_DESTROY_CHN, NULL); + if (s32Ret != CVI_SUCCESS) { + CVI_VDEC_ERR("ioctl CVI_VC_VDEC_DESTROY_CHN fail with %d\n", s32Ret); + return s32Ret; + } + close(s32VdecFd[VdChn]); + s32VdecFd[VdChn] = 0; + } + + u32ChannelCreatedCnt -= 1; + if (u32ChannelCreatedCnt == 0) { + devm_close(s32DevmemFd); + s32DevmemFd = -1; + } + + return s32Ret; +} + +CVI_S32 CVI_VDEC_GetChnAttr(VDEC_CHN VdChn, VDEC_CHN_ATTR_S *pstAttr) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_CHN_ATTR, pstAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_SetChnAttr(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pstAttr) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SET_CHN_ATTR, pstAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_StartRecvStream(VDEC_CHN VdChn) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_START_RECV_STREAM, NULL); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_StopRecvStream(VDEC_CHN VdChn) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_STOP_RECV_STREAM, NULL); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_QueryStatus(VDEC_CHN VdChn, VDEC_CHN_STATUS_S *pstStatus) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_QUERY_STATUS, pstStatus); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_GetFd(VDEC_CHN VdChn) +{ + if (s32VdecFd[VdChn] <= 0) { + CVI_CHAR devName[255]; + + sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn); + s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC); + CVI_VDEC_TRACE("open device (%s) fd: %d\n", devName, s32VdecFd[VdChn]); + } + return s32VdecFd[VdChn]; +} + +CVI_S32 CVI_VDEC_CloseFd(VDEC_CHN VdChn) +{ + // close fd in destroy channel + UNUSED(VdChn); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VDEC_ResetChn(VDEC_CHN VdChn) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_RESET_CHN); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_SetChnParam(VDEC_CHN VdChn, const VDEC_CHN_PARAM_S *pstParam) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SET_CHN_PARAM, pstParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_GetChnParam(VDEC_CHN VdChn, VDEC_CHN_PARAM_S *pstParam) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_CHN_PARAM, pstParam); + } + return CVI_FAILURE; +} + +/* s32MilliSec: -1 is block,0 is no block,other positive number is timeout */ +CVI_S32 CVI_VDEC_SendStream(VDEC_CHN VdChn, const VDEC_STREAM_S *pstStream, CVI_S32 s32MilliSec) +{ + if (s32VdecFd[VdChn] > 0) { + VDEC_STREAM_EX_S stStreamEx, *pstStreamEx = &stStreamEx; + + pstStreamEx->pstStream = pstStream; + pstStreamEx->s32MilliSec = s32MilliSec; + + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SEND_STREAM, pstStreamEx); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_GetFrame(VDEC_CHN VdChn, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + if (s32VdecFd[VdChn] > 0) { + CVI_S32 s32Ret = CVI_SUCCESS; + VIDEO_FRAME_INFO_EX_S stFrameInfoEx, *pstFrameInfoEx = &stFrameInfoEx; + + pstFrameInfoEx->pstFrame = pstFrameInfo; + pstFrameInfoEx->s32MilliSec = s32MilliSec; + + s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_FRAME, pstFrameInfoEx); + if (s32Ret == CVI_SUCCESS) { + int i = 0; + + for (i = 0; i < 3; i++) { + if (pstFrameInfo->stVFrame.u64PhyAddr[i] && + pstFrameInfo->stVFrame.u32Length[i]) { + pstFrameInfo->stVFrame.pu8VirAddr[i] = + devm_map(s32DevmemFd, + pstFrameInfo->stVFrame.u64PhyAddr[i], + pstFrameInfo->stVFrame.u32Length[i]); + } + } + } + return s32Ret; + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_ReleaseFrame(VDEC_CHN VdChn, const VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + if (s32VdecFd[VdChn] > 0) { + int i = 0; + + for (i = 0; i < 3; i++) { + if (pstFrameInfo->stVFrame.pu8VirAddr[i] && pstFrameInfo->stVFrame.u32Length[i]) { + devm_unmap(pstFrameInfo->stVFrame.pu8VirAddr[i], pstFrameInfo->stVFrame.u32Length[i]); + } + } + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_RELEASE_FRAME, pstFrameInfo); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_AttachVbPool(VDEC_CHN VdChn, const VDEC_CHN_POOL_S *pstPool) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_ATTACH_VBPOOL, pstPool); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_DetachVbPool(VDEC_CHN VdChn) +{ + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_DETACH_VBPOOL, NULL); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_SetModParam(const VDEC_MOD_PARAM_S *pstModParam) +{ + VDEC_CHN VdChn = 0; // default hard-code + + if (s32VdecFd[VdChn] == 0) { + CVI_CHAR devName[255]; + + sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn); + s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC); + + if (s32DevmemFd == -1) { + s32DevmemFd = devm_open_cached(); + if (s32DevmemFd < 0) + return CVI_FAILURE; + } + } + + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[0], CVI_VC_VDEC_SET_MOD_PARAM, pstModParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VDEC_GetModParam(VDEC_MOD_PARAM_S *pstModParam) +{ + VDEC_CHN VdChn = 0; // default hard-code + + if (s32VdecFd[VdChn] > 0) { + return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_MOD_PARAM, pstModParam); + } + return CVI_FAILURE; +} + diff --git a/middleware/v2/modules/venc/Makefile b/middleware/v2/modules/venc/Makefile new file mode 100644 index 000000000..a8d8c408a --- /dev/null +++ b/middleware/v2/modules/venc/Makefile @@ -0,0 +1,59 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = src +SRCS = $(wildcard $(SDIR)/*.c) +INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -Iinclude +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libvenc.a +TARGET_SO = $(MW_LIB)/libvenc.so +ifeq ($(MULTI_PROCESS_SUPPORT), 1) +DEFS += -DRPC_MULTI_PROCESS +endif + +EXTRA_CFLAGS = $(INCS) $(DEFS) + +ifeq ($(DEBUG), 1) +EXTRA_CFLAGS += -g -O0 +endif + +ldflags-y = -lsys + + +ifeq ($(CLI_DEBUG_SUPPORT), 1) +DEFS += -DCLI_DEBUG_SUPPORT +ldflags-y += -lcli +LIB_A_FLAGS += $(MW_3RD_LIB)/libcli.a +LIB_SO_FLAGS += $(MW_3RD_LIB)/libcli.so +endif + +TMP_INC = $(MW_INC)/cvi_jpg* $(MW_INC)/cvi_h265* + +.PHONY : clean all +all : prepare $(TARGET_A) $(TARGET_SO) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) $(LIB_A_FLAGS) + @$(AR) $(ARFLAGS) $@ $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $@) + +$(TARGET_SO): $(OBJS) $(LIB_SO_FLAGS) + @$(LD) $(LDFLAGS) $(ldflags-y) -o $@ --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $@) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +prepare: + @echo "SDK_VER = ${SDK_VER}" + @head=`git rev-parse --verify --short HEAD` + @date=`git show -s --format=%cd --date=short ${head}` + +-include $(DEPS) diff --git a/middleware/v2/modules/venc/src/cvi_venc.c b/middleware/v2/modules/venc/src/cvi_venc.c new file mode 100644 index 000000000..c47ff52b7 --- /dev/null +++ b/middleware/v2/modules/venc/src/cvi_venc.c @@ -0,0 +1,695 @@ + +#include +#include +#include +#include + +#include "devmem.h" +#include "cvi_venc.h" + +#include + +#define UNUSED(x) ((void)(x)) + +typedef struct _VENC_STREAM_EX_S { + VENC_STREAM_S *pstStream; + CVI_S32 s32MilliSec; +} VENC_STREAM_EX_S; + +typedef struct _VENC_USER_DATA_S { + CVI_U8 *pu8Data; + CVI_U32 u32Len; +} VENC_USER_DATA_S; + +typedef struct _VIDEO_FRAME_INFO_EX_S { + const VIDEO_FRAME_INFO_S *pstFrame; + CVI_S32 s32MilliSec; +} VIDEO_FRAME_INFO_EX_S; + +typedef struct _USER_FRAME_INFO_EX_S { + const USER_FRAME_INFO_S *pstUserFrame; + CVI_S32 s32MilliSec; +} USER_FRAME_INFO_EX_S; + +#define CVI_VENC_NO_INPUT -10 +#define CVI_VENC_INPUT_ERR -11 +#define DUMP_YUV "dump_src.yuv" +#define DUMP_BS "dump_bs.bin" + +venc_dbg vencDbg; +static CVI_S32 s32DevmemFd = -1; +static CVI_U32 u32ChannelCreatedCnt; + +CVI_S32 s32VencFd[VENC_MAX_CHN_NUM] = {0}; +CVI_U8 *pStreamPackArray[VENC_MAX_CHN_NUM][8] = {NULL}; + +static CVI_S32 cviGetEnv(CVI_CHAR *env, CVI_CHAR *fmt, CVI_VOID *param) +{ + CVI_CHAR *debugEnv; + CVI_S32 val = CVI_VENC_NO_INPUT; + + debugEnv = getenv(env); + if (debugEnv) { + if (strcmp(fmt, "%s") == 0) { + strcpy(param, debugEnv); + } else { + if (sscanf(debugEnv, fmt, &val) != 1) + return CVI_VENC_INPUT_ERR; + CVI_VENC_TRACE("%s = 0x%X\n", env, val); + } + } + + return val; +} + +static CVI_VOID cviChangeMask(CVI_S32 frameIdx) +{ + venc_dbg *pDbg = &vencDbg; + + pDbg->currMask = pDbg->dbgMask; + if (pDbg->startFn >= 0) { + if (frameIdx >= pDbg->startFn && + frameIdx <= pDbg->endFn) + pDbg->currMask = pDbg->dbgMask; + else + pDbg->currMask = CVI_VENC_MASK_ERR; + } + + CVI_VENC_TRACE("currMask = 0x%X\n", pDbg->currMask); +} + +CVI_VOID cviGetMask(void) +{ + venc_dbg *pDbg = &vencDbg; + + CVI_VENC_TRACE("\n"); + + memset(pDbg, 0, sizeof(venc_dbg)); + + pDbg->dbgMask = cviGetEnv("venc_mask", "0x%x", NULL); + if (pDbg->dbgMask == CVI_VENC_NO_INPUT || + pDbg->dbgMask == CVI_VENC_INPUT_ERR) + pDbg->dbgMask = CVI_VENC_MASK_ERR; + else + pDbg->dbgMask |= CVI_VENC_MASK_ERR; + + pDbg->currMask = pDbg->dbgMask; + pDbg->startFn = cviGetEnv("venc_sfn", "%d", NULL); + pDbg->endFn = cviGetEnv("venc_efn", "%d", NULL); + cviGetEnv("venc_dir", "%s", pDbg->dbgDir); + + cviChangeMask(0); +} + +static CVI_S32 openDevice(VENC_CHN VeChn) +{ + if (s32VencFd[VeChn] <= 0) { + CVI_CHAR devName[255]; + + sprintf(devName, "/dev/%s%d", CVI_VC_DRV_ENCODER_DEV_NAME, VeChn); + s32VencFd[VeChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC); + + if (s32VencFd[VeChn] <= 0) { + CVI_VENC_ERR("open device (%s) fail\n", devName); + return CVI_FAILURE; + } + CVI_VENC_TRACE("open device (%s) fd: %d\n", devName, s32VencFd[VeChn]); + } + + if (s32DevmemFd == -1) { + s32DevmemFd = devm_open_cached(); + if (s32DevmemFd < 0) { + CVI_VENC_ERR("devm_open fail\n"); + return CVI_FAILURE; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VENC_CreateChn(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pstAttr) +{ + CVI_S32 s32Ret = CVI_FAILURE; + CVI_CHAR devName[255]; + + if (openDevice(VeChn) != CVI_SUCCESS) { + CVI_VENC_ERR("openDevice fail\n"); + return s32Ret; + } + + if (s32VencFd[VeChn] > 0) { + s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_CREATE_CHN, pstAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_VENC_ERR("ioctl CVI_VC_VENC_CREATE_CHN fail with %d\n", s32Ret); + return s32Ret; + } + u32ChannelCreatedCnt += 1; + } else { + CVI_VENC_ERR("fail to open device %s\n", devName); + s32Ret = CVI_FAILURE; + } + return s32Ret; +} + +CVI_S32 CVI_VENC_DestroyChn(VENC_CHN VeChn) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (s32VencFd[VeChn] > 0) { + s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_DESTROY_CHN); + if (s32Ret != CVI_SUCCESS) { + CVI_VENC_ERR("ioctl CVI_VC_VENC_DESTROY_CHN fail with %d\n", s32Ret); + return s32Ret; + } + close(s32VencFd[VeChn]); + s32VencFd[VeChn] = 0; + } + + u32ChannelCreatedCnt -= 1; + if (u32ChannelCreatedCnt == 0) { + devm_close(s32DevmemFd); + s32DevmemFd = -1; + } + + return s32Ret; +} + +CVI_S32 CVI_VENC_ResetChn(VENC_CHN VeChn) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_RESET_CHN); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_StartRecvFrame(VENC_CHN VeChn, const VENC_RECV_PIC_PARAM_S *pstRecvParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_START_RECV_FRAME, pstRecvParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_StopRecvFrame(VENC_CHN VeChn) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_STOP_RECV_FRAME); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_QueryStatus(VENC_CHN VeChn, VENC_CHN_STATUS_S *pstStatus) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_QUERY_STATUS, pstStatus); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetChnAttr(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pstChnAttr) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CHN_ATTR, pstChnAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetChnAttr(VENC_CHN VeChn, VENC_CHN_ATTR_S *pstChnAttr) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CHN_ATTR, pstChnAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetStream(VENC_CHN VeChn, VENC_STREAM_S *pstStream, CVI_S32 S32MilliSec) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + + if (s32VencFd[VeChn] > 0) { + VENC_STREAM_EX_S stStreamEx, *pstStreamEx = &stStreamEx; + + pstStreamEx->pstStream = pstStream; + pstStreamEx->s32MilliSec = S32MilliSec; + s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_STREAM, pstStreamEx); + + if (s32Ret == CVI_SUCCESS) { + CVI_U32 i = 0; + VENC_PACK_S *ppack; + + for (i = 0; i < pstStreamEx->pstStream->u32PackCount; i++) { + ppack = &pstStreamEx->pstStream->pstPack[i]; + if (ppack->u64PhyAddr && ppack->u32Len) { + pStreamPackArray[VeChn][i] = ppack->pu8Addr; + ppack->pu8Addr = devm_map(s32DevmemFd, ppack->u64PhyAddr, ppack->u32Len); + } + } + } + return s32Ret; + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_ReleaseStream(VENC_CHN VeChn, VENC_STREAM_S *pstStream) +{ + if (s32VencFd[VeChn] > 0) { + CVI_U32 i = 0; + VENC_PACK_S *ppack; + + for (i = 0; i < pstStream->u32PackCount; i++) { + ppack = &pstStream->pstPack[i]; + if (ppack->u64PhyAddr && ppack->u32Len) { + devm_unmap(ppack->pu8Addr, ppack->u32Len); + ppack->pu8Addr = pStreamPackArray[VeChn][i]; + } + } + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_RELEASE_STREAM, pstStream); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_InsertUserData(VENC_CHN VeChn, CVI_U8 *pu8Data, CVI_U32 u32Len) +{ + if (s32VencFd[VeChn] > 0) { + VENC_USER_DATA_S stUserData, *pstUserData = &stUserData; + + pstUserData->pu8Data = pu8Data; + pstUserData->u32Len = u32Len; + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_INSERT_USERDATA, pstUserData); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SendFrame(VENC_CHN VeChn, const VIDEO_FRAME_INFO_S *pstFrame, CVI_S32 s32MilliSec) +{ + if (s32VencFd[VeChn] > 0) { + VIDEO_FRAME_INFO_EX_S stFrameEx, *pstFrameEx = &stFrameEx; + + pstFrameEx->pstFrame = pstFrame; + pstFrameEx->s32MilliSec = s32MilliSec; + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SEND_FRAME, pstFrameEx); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SendFrameEx(VENC_CHN VeChn, const USER_FRAME_INFO_S *pstFrame, CVI_S32 s32MilliSec) +{ + if (s32VencFd[VeChn] > 0) { + USER_FRAME_INFO_EX_S stUserFrameEx, *pstUserFrameEx = &stUserFrameEx; + + pstUserFrameEx->pstUserFrame = pstFrame; + pstUserFrameEx->s32MilliSec = s32MilliSec; + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SEND_FRAMEEX, pstUserFrameEx); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_RequestIDR(VENC_CHN VeChn, CVI_BOOL bInstant) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_REQUEST_IDR, &bInstant); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetFd(VENC_CHN VeChn) +{ + if (openDevice(VeChn) != CVI_SUCCESS) { + CVI_VENC_ERR("openDevice fail\n"); + return CVI_FAILURE; + } + return s32VencFd[VeChn]; +} + +CVI_S32 CVI_VENC_CloseFd(VENC_CHN VeChn) +{ + // close fd in destroy channel + UNUSED(VeChn); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VENC_SetRoiAttr(VENC_CHN VeChn, const VENC_ROI_ATTR_S *pstRoiAttr) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_ROI_ATTR, pstRoiAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetRoiAttr(VENC_CHN VeChn, CVI_U32 u32Index, VENC_ROI_ATTR_S *pstRoiAttr) +{ + if (s32VencFd[VeChn] > 0) { + pstRoiAttr->u32Index = u32Index; + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_ROI_ATTR, pstRoiAttr); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264Trans(VENC_CHN VeChn, const VENC_H264_TRANS_S *pstH264Trans) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_TRANS, pstH264Trans); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264Trans(VENC_CHN VeChn, VENC_H264_TRANS_S *pstH264Trans) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_TRANS, pstH264Trans); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264Entropy(VENC_CHN VeChn, const VENC_H264_ENTROPY_S *pstH264EntropyEnc) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_ENTROPY, pstH264EntropyEnc); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264Entropy(VENC_CHN VeChn, VENC_H264_ENTROPY_S *pstH264EntropyEnc) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_ENTROPY, pstH264EntropyEnc); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264Vui(VENC_CHN VeChn, const VENC_H264_VUI_S *pstH264Vui) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_VUI, pstH264Vui); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264Vui(VENC_CHN VeChn, VENC_H264_VUI_S *pstH264Vui) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_VUI, pstH264Vui); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH265Vui(VENC_CHN VeChn, const VENC_H265_VUI_S *pstH265Vui) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_VUI, pstH265Vui); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH265Vui(VENC_CHN VeChn, VENC_H265_VUI_S *pstH265Vui) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_VUI, pstH265Vui); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetJpegParam(VENC_CHN VeChn, const VENC_JPEG_PARAM_S *pstJpegParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_JPEG_PARAM, pstJpegParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetJpegParam(VENC_CHN VeChn, VENC_JPEG_PARAM_S *pstJpegParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_JPEG_PARAM, pstJpegParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetRcParam(VENC_CHN VeChn, VENC_RC_PARAM_S *pstRcParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_RC_PARAM, pstRcParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetRcParam(VENC_CHN VeChn, const VENC_RC_PARAM_S *pstRcParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_RC_PARAM, pstRcParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetRefParam(VENC_CHN VeChn, const VENC_REF_PARAM_S *pstRefParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_REF_PARAM, pstRefParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetRefParam(VENC_CHN VeChn, VENC_REF_PARAM_S *pstRefParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_REF_PARAM, pstRefParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH265Trans(VENC_CHN VeChn, const VENC_H265_TRANS_S *pstH265Trans) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_TRANS, pstH265Trans); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH265Trans(VENC_CHN VeChn, VENC_H265_TRANS_S *pstH265Trans) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_TRANS, pstH265Trans); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetFrameLostStrategy(VENC_CHN VeChn, const VENC_FRAMELOST_S *pstFrmLostParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_FRAMELOST_STRATEGY, pstFrmLostParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetFrameLostStrategy(VENC_CHN VeChn, VENC_FRAMELOST_S *pstFrmLostParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_FRAMELOST_STRATEGY, pstFrmLostParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetSuperFrameStrategy(VENC_CHN VeChn, const VENC_SUPERFRAME_CFG_S *pstSuperFrmParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_SUPERFRAME_STRATEGY, pstSuperFrmParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetSuperFrameStrategy(VENC_CHN VeChn, VENC_SUPERFRAME_CFG_S *pstSuperFrmParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_SUPERFRAME_STRATEGY, pstSuperFrmParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetChnParam(VENC_CHN VeChn, const VENC_CHN_PARAM_S *pstChnParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CHN_PARAM, pstChnParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetChnParam(VENC_CHN VeChn, VENC_CHN_PARAM_S *pstChnParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CHN_PARAM, pstChnParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetModParam(const VENC_PARAM_MOD_S *pstModParam) +{ + VENC_CHN VeChn = 0; // default hard-code + + if (s32DevmemFd == -1) { + s32DevmemFd = devm_open_cached(); + if (s32DevmemFd < 0) + return CVI_FAILURE; + } + + if (openDevice(VeChn) != CVI_SUCCESS) { + CVI_VENC_ERR("openDevice fail\n"); + return CVI_FAILURE; + } + + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_MOD_PARAM, pstModParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetModParam(VENC_PARAM_MOD_S *pstModParam) +{ + VENC_CHN VeChn = 0; // default hard-code + + if (openDevice(VeChn) != CVI_SUCCESS) { + CVI_VENC_ERR("openDevice fail\n"); + return CVI_FAILURE; + } + + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_MOD_PARAM, pstModParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_AttachVbPool(VENC_CHN VeChn, const VENC_CHN_POOL_S *pstPool) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_ATTACH_VBPOOL, pstPool); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_DetachVbPool(VENC_CHN VeChn) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_DETACH_VBPOOL); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetCuPrediction(VENC_CHN VeChn, + const VENC_CU_PREDICTION_S *pstCuPrediction) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CUPREDICTION, pstCuPrediction); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetCuPrediction(VENC_CHN VeChn, VENC_CU_PREDICTION_S *pstCuPrediction) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CUPREDICTION, pstCuPrediction); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_CalcFrameParam(VENC_CHN VeChn, VENC_FRAME_PARAM_S *pstFrameParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_CALC_FRAME_PARAM, pstFrameParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetFrameParam(VENC_CHN VeChn, const VENC_FRAME_PARAM_S *pstFrameParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_FRAME_PARAM, pstFrameParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetFrameParam(VENC_CHN VeChn, VENC_FRAME_PARAM_S *pstFrameParam) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_FRAME_PARAM, pstFrameParam); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264SliceSplit(VENC_CHN VeChn, const VENC_H264_SLICE_SPLIT_S *pstSliceSplit) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_SLICE_SPLIT, pstSliceSplit); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264SliceSplit(VENC_CHN VeChn, VENC_H264_SLICE_SPLIT_S *pstSliceSplit) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_SLICE_SPLIT, pstSliceSplit); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH265SliceSplit(VENC_CHN VeChn, const VENC_H265_SLICE_SPLIT_S *pstSliceSplit) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_SLICE_SPLIT, pstSliceSplit); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH265SliceSplit(VENC_CHN VeChn, VENC_H265_SLICE_SPLIT_S *pstSliceSplit) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_SLICE_SPLIT, pstSliceSplit); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264Dblk(VENC_CHN VeChn, const VENC_H264_DBLK_S *pstH264Dblk) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_Dblk, pstH264Dblk); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264Dblk(VENC_CHN VeChn, VENC_H264_DBLK_S *pstH264Dblk) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_Dblk, pstH264Dblk); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH265Dblk(VENC_CHN VeChn, const VENC_H265_DBLK_S *pstH265Dblk) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_Dblk, pstH265Dblk); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH265Dblk(VENC_CHN VeChn, VENC_H265_DBLK_S *pstH265Dblk) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_Dblk, pstH265Dblk); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_SetH264IntraPred(VENC_CHN VeChn, const VENC_H264_INTRA_PRED_S *pstH264IntraPred) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_INTRA_PRED, pstH264IntraPred); + } + return CVI_FAILURE; +} + +CVI_S32 CVI_VENC_GetH264IntraPred(VENC_CHN VeChn, VENC_H264_INTRA_PRED_S *pstH264IntraPred) +{ + if (s32VencFd[VeChn] > 0) { + return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_INTRA_PRED, pstH264IntraPred); + } + return CVI_FAILURE; +} diff --git a/middleware/v2/modules/vpu/Makefile b/middleware/v2/modules/vpu/Makefile new file mode 100644 index 000000000..b319a926c --- /dev/null +++ b/middleware/v2/modules/vpu/Makefile @@ -0,0 +1,44 @@ +SHELL = /bin/bash +ifeq ($(PARAM_FILE), ) + PARAM_FILE:=../../Makefile.param + include $(PARAM_FILE) +endif + +SDIR = $(PWD)/src +SRCS = $(wildcard $(SDIR)/*.c) +SRCS := $(filter-out $(SDIR)/cvi_gdc.c, $(SRCS)) +SRCS := $(filter-out $(SDIR)/gdc_mesh.c, $(SRCS)) + +INCS = -I$(MW_INC) -I$(ISP_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(BIN_INC) -I./include + +OBJS = $(SRCS:.c=.o) +DEPS = $(SRCS:.c=.d) +TARGET_A = $(MW_LIB)/libvpu.a +TARGET_SO = $(MW_LIB)/libvpu.so + +EXTRA_CFLAGS = $(INCS) + + +.PHONY : clean all +all : $(TARGET_A) $(TARGET_SO) + +$(SDIR)/gdc_mesh_1822.o: $(SDIR)/gdc_mesh_1822.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -O3 -c $< -o $@ + @echo [$(notdir $(CC))] $(notdir $@) + +$(SDIR)/%.o: $(SDIR)/%.c + @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@ + @echo [$(notdir $(CC))] $(notdir $@) + +$(TARGET_A): $(OBJS) + @$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) + @echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A)) + +$(TARGET_SO): $(OBJS) + @$(LD) $(LDFLAGS) -o $(TARGET_SO) --start-group $(OBJS) --end-group + @echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO)) + +clean: + @rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO) + +-include $(DEPS) diff --git a/middleware/v2/modules/vpu/src/cvi_gdc.c b/middleware/v2/modules/vpu/src/cvi_gdc.c new file mode 100644 index 000000000..9c5738fd3 --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_gdc.c @@ -0,0 +1,640 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_buffer.h" +#include "cvi_base.h" +#include "cvi_sys.h" +#include "cvi_vb.h" + +#include "cvi_gdc.h" +#include "ioctl_vio.h" + +#include "gdc_mesh.h" + +#define DWA_YUV_BLACK 0x808000 +#define DWA_RGB_BLACK 0x0 + +#define CHECK_GDC_FORMAT(imgIn, imgOut) \ + do { \ + if (imgIn.stVFrame.enPixelFormat != imgOut.stVFrame.enPixelFormat) { \ + CVI_TRACE_GDC(CVI_DBG_ERR, "in/out pixelformat(%d-%d) mismatch\n", \ + imgIn.stVFrame.enPixelFormat, imgOut.stVFrame.enPixelFormat); \ + return CVI_ERR_GDC_ILLEGAL_PARAM; \ + } \ + if (!GDC_SUPPORT_FMT(imgIn.stVFrame.enPixelFormat)) { \ + CVI_TRACE_GDC(CVI_DBG_ERR, "pixelformat(%d) unsupported\n", imgIn.stVFrame.enPixelFormat); \ + return CVI_ERR_GDC_ILLEGAL_PARAM; \ + } \ + } while (0) + +static CVI_S32 gdc_rotation_check_size(ROTATION_E enRotation, const GDC_TASK_ATTR_S *pstTask) +{ + if (enRotation > ROTATION_270) { + CVI_TRACE_GDC(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + if (enRotation == ROTATION_90 || enRotation == ROTATION_270) { + if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Height) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input height(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Width, + pstTask->stImgIn.stVFrame.u32Height); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Width) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input width(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Height, + pstTask->stImgIn.stVFrame.u32Width); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } else { + if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Width) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input width(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Width, + pstTask->stImgIn.stVFrame.u32Width); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Height) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input height(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Height, + pstTask->stImgIn.stVFrame.u32Height); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_Suspend(void) +{ + CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_Resume(void) +{ + CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} + +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_GDC_BeginJob(GDC_HANDLE *phHandle) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, phHandle); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_EndJob(GDC_HANDLE hHandle) +{ + UNUSED(hHandle); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_CancelJob(GDC_HANDLE hHandle) +{ + if (hHandle == CVI_NULL) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Null pointer.\n"); + return CVI_ERR_GDC_NULL_PTR; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_AddCorrectionTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, + const FISHEYE_ATTR_S *pstFishEyeAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstFishEyeAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + + if (pstFishEyeAttr->bEnable) { + if (pstFishEyeAttr->u32RegionNum == 0) { + CVI_TRACE_GDC(CVI_DBG_ERR, "RegionNum(%d) can't be 0 if enable fisheye.\n", + pstFishEyeAttr->u32RegionNum); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (((CVI_U32)pstFishEyeAttr->s32HorOffset > pstTask->stImgIn.stVFrame.u32Width) || + ((CVI_U32)pstFishEyeAttr->s32VerOffset > pstTask->stImgIn.stVFrame.u32Height)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "center pos(%d %d) out of frame size(%d %d).\n", + pstFishEyeAttr->s32HorOffset, pstFishEyeAttr->s32VerOffset, + pstTask->stImgIn.stVFrame.u32Width, pstTask->stImgIn.stVFrame.u32Height); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + for (CVI_U32 i = 0; i < pstFishEyeAttr->u32RegionNum; ++i) { + if ((pstFishEyeAttr->enMountMode == FISHEYE_WALL_MOUNT) && + (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_360_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): WALL_MOUNT not support Panorama_360.\n", i); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstFishEyeAttr->enMountMode == FISHEYE_CEILING_MOUNT) && + (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): CEILING_MOUNT not support Panorama_180.\n", i); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstFishEyeAttr->enMountMode == FISHEYE_DESKTOP_MOUNT) && + (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): DESKTOP_MOUNT not support Panorama_180.\n", i); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + } + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_FISHEYE; + param->stFishEyeAttr = *pstFishEyeAttr; + + if (param->stTask.reserved != CVI_GDC_MAGIC) { + CVI_U64 paddr; + CVI_VOID *vaddr; + + if (CVI_SYS_IonAlloc(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_FISHEYE) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++; + return CVI_ERR_GDC_NOBUF; + } + param->stTask.au64privateData[0] = paddr; + param->stTask.au64privateData[1] = (uintptr_t)vaddr; + +#if 0 + FILE *fp; + int f_size; + CVI_U64 mesh_tbl_addr; + CVI_U16 *mesh_id; + + fp = fopen("mesh_id.bin", "r"); + if (fp == NULL) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file not found.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_END); + f_size = ftell(fp); + if (f_size == -1) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file can't tell.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_SET); + fread(vaddr, 1, f_size, fp); + fclose(fp); + + mesh_id = vaddr; + paddr += ALIGN(f_size + 0x1000, 32); + vaddr += ALIGN(f_size + 0x1000, 32); + + fp = fopen("mesh_tbl.bin", "r"); + if (fp == NULL) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file not found.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_END); + f_size = ftell(fp); + if (f_size == -1) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file can't tell.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_SET); + fread(vaddr, 1, f_size, fp); + fclose(fp); + + mesh_tbl_addr = paddr; + + /**!! offset changes by mesh file !!**/ + CVI_U32 offset[3] = {0x300, 0x300, 0x2800}; + CVI_U8 index = 0; + + while (*mesh_id != 0xffff) { + if (*mesh_id == 0xfffb) { + if (index > 3) { + CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n"); + continue; + } + *(++mesh_id) = mesh_tbl_addr & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f; + mesh_tbl_addr += offset[index++]; + } + ++mesh_id; + } +#else + SIZE_S in_size, out_size; + + in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width; + in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height; + out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width; + out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height; + mesh_gen_fisheye(in_size, out_size, pstFishEyeAttr, paddr, vaddr, ROTATION_0); + CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_FISHEYE); +#endif + } + //gdc_proc_ctx->stFishEyeStatus.u32AddTaskSuc++; + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_AddRotationTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, ROTATION_E enRotation) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_ROT; + param->enRotation = enRotation; + + if (param->stTask.reserved != CVI_GDC_MAGIC) { + SIZE_S in_size, out_size; + CVI_U64 paddr; + CVI_VOID *vaddr; + + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_ROT) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + return CVI_ERR_GDC_NOBUF; + } + + in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width; + in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height; + out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width; + out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height; + mesh_gen_rotation(in_size, out_size, enRotation, paddr, vaddr); + CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_ROT); + param->stTask.au64privateData[0] = paddr; + param->stTask.au64privateData[1] = (uintptr_t)vaddr; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_AddAffineTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const AFFINE_ATTR_S *pstAffineAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstAffineAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + if (pstAffineAttr->u32RegionNum == 0) { + CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) can't be zero.\n", pstAffineAttr->u32RegionNum); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + if (pstAffineAttr->stDestSize.u32Width > pstTask->stImgOut.stVFrame.u32Width) { + CVI_TRACE_GDC(CVI_DBG_ERR, "dest's width(%d) can't be larger than frame's width(%d)\n", + pstAffineAttr->stDestSize.u32Width, pstTask->stImgOut.stVFrame.u32Width); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + for (CVI_U32 i = 0; i < pstAffineAttr->u32RegionNum; ++i) { + CVI_TRACE_GDC(CVI_DBG_INFO, "u32RegionNum(%d) (%f, %f) (%f, %f) (%f, %f) (%f, %f)\n", i, + pstAffineAttr->astRegionAttr[i][0].x, pstAffineAttr->astRegionAttr[i][0].y, + pstAffineAttr->astRegionAttr[i][1].x, pstAffineAttr->astRegionAttr[i][1].y, + pstAffineAttr->astRegionAttr[i][2].x, pstAffineAttr->astRegionAttr[i][2].y, + pstAffineAttr->astRegionAttr[i][3].x, pstAffineAttr->astRegionAttr[i][3].y); + if ((pstAffineAttr->astRegionAttr[i][0].x < 0) || (pstAffineAttr->astRegionAttr[i][0].y < 0) || + (pstAffineAttr->astRegionAttr[i][1].x < 0) || (pstAffineAttr->astRegionAttr[i][1].y < 0) || + (pstAffineAttr->astRegionAttr[i][2].x < 0) || (pstAffineAttr->astRegionAttr[i][2].y < 0) || + (pstAffineAttr->astRegionAttr[i][3].x < 0) || (pstAffineAttr->astRegionAttr[i][3].y < 0)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) affine point can't be negative\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstAffineAttr->astRegionAttr[i][1].x < pstAffineAttr->astRegionAttr[i][0].x) || + (pstAffineAttr->astRegionAttr[i][3].x < pstAffineAttr->astRegionAttr[i][2].x)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) point1/3's x should be bigger thant 0/2's\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstAffineAttr->astRegionAttr[i][2].y < pstAffineAttr->astRegionAttr[i][0].y) || + (pstAffineAttr->astRegionAttr[i][3].y < pstAffineAttr->astRegionAttr[i][1].y)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) point2/3's y should be bigger thant 0/1's\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_AFFINE; + param->stAffineAttr = *pstAffineAttr; + + SIZE_S in_size, out_size; + CVI_U64 paddr; + CVI_VOID *vaddr; + + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_AFFINE) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + return CVI_ERR_GDC_NOBUF; + } + + in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width; + in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height; + out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width; + out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height; + mesh_gen_affine(in_size, out_size, pstAffineAttr, paddr, vaddr); + CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_AFFINE); + param->stTask.au64privateData[0] = paddr; + param->stTask.au64privateData[1] = (uintptr_t)vaddr; + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_AddLDCTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask + , const LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstLDCAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + if (enRotation != ROTATION_0) { + if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_LDC; + param->stLDCAttr = *pstLDCAttr; + param->stTask.au64privateData[3] = enRotation; + + return CVI_SUCCESS; +} + +// cnv +#define CVI_GDC_MESH_SIZE_CNV (100000) +//offset[0:2]=tbl_param[0:2], len_tbl = tbl_param[3], len_idl = tbl_param[4] +CVI_S32 CVI_GDC_AddCorrectionTaskCNV(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask + , const FISHEYE_ATTR_S *pstFishEyeAttr, uint8_t *p_tbl, uint8_t *p_idl, uint32_t *tbl_param) +{ + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + int32_t len_tbl = tbl_param[4]; + int32_t len_idl = tbl_param[3]; + + + if (pstFishEyeAttr->bEnable) { + if (pstFishEyeAttr->u32RegionNum == 0) { + CVI_TRACE_GDC(CVI_DBG_ERR, "RegionNum(%d) can't be 0 if enable fisheye.\n" + , pstFishEyeAttr->u32RegionNum); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (((CVI_U32)pstFishEyeAttr->s32HorOffset > pstTask->stImgIn.stVFrame.u32Width) + || ((CVI_U32)pstFishEyeAttr->s32VerOffset > pstTask->stImgIn.stVFrame.u32Height)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "center pos(%d %d) out of frame size(%d %d).\n" + , pstFishEyeAttr->s32HorOffset, pstFishEyeAttr->s32VerOffset + , pstTask->stImgIn.stVFrame.u32Width, pstTask->stImgIn.stVFrame.u32Height); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + for (CVI_U32 i = 0; i < pstFishEyeAttr->u32RegionNum; ++i) { + if ((pstFishEyeAttr->enMountMode == FISHEYE_WALL_MOUNT) + && (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_360_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): WALL_MOUNT not support Panorama_360.\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstFishEyeAttr->enMountMode == FISHEYE_CEILING_MOUNT) + && (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): CEILING_MOUNT not support Panorama_180.\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if ((pstFishEyeAttr->enMountMode == FISHEYE_DESKTOP_MOUNT) + && (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): DESKTOP_MOUNT not support Panorama_180.\n", i); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + } + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_FISHEYE; + param->stFishEyeAttr = *pstFishEyeAttr; + + if (param->stTask.reserved != CVI_GDC_MAGIC) { + CVI_U64 paddr; + CVI_VOID *vaddr; + + if (CVI_SYS_IonAlloc(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_CNV) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + return CVI_ERR_GDC_NOBUF; + } + param->stTask.au64privateData[0] = paddr; + param->stTask.au64privateData[1] = (uintptr_t)vaddr; + + #if 1 + int f_size; + CVI_U64 mesh_tbl_addr; + CVI_U16 *mesh_id; + + f_size = len_idl; + memcpy(vaddr, p_idl, f_size); + mesh_id = vaddr; + paddr += ALIGN(f_size + 0x1000, 32); + vaddr += ALIGN(f_size + 0x1000, 32); + + f_size = len_tbl; + memcpy(vaddr, p_tbl, f_size); + mesh_tbl_addr = paddr; + + /**!! offset changes by mesh file !!**/ + CVI_U32 offset[3] = {0x1440, 0x1200, 0x1200}; + CVI_U8 index = 0; + + offset[0] = tbl_param[0]; + offset[1] = tbl_param[1]; + offset[2] = tbl_param[2]; + while (*mesh_id != 0xffff) { + if (*mesh_id == 0xfffb) { + if (index > 3) { + CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n"); + continue; + } + *(++mesh_id) = mesh_tbl_addr & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f; + mesh_tbl_addr += offset[index++]; + } + ++mesh_id; + } + #else + SIZE_S in_size, out_size; + + in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width; + in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height; + out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width; + out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height; + mesh_gen_fisheye(in_size, out_size, pstFishEyeAttr, paddr, vaddr); + CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_FISHEYE); + #endif + } + return CVI_SUCCESS; +} + +//#define CVI_GDC_MESH_SIZE_CNV (100000) +unsigned char ptbl[200000]; +unsigned char ptbid[100000]; +// static int flag_mem = 1; +int f_size; + +#define USE_BIN_TXT 0 // 0: use mesh txt data, 1: use mesh tbl bin data + +CVI_S32 CVI_GDC_AddCnvWarpTask(const float *pfmesh_data, GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, + const FISHEYE_ATTR_S *pstAffineAttr, bool *bReNew) +{ + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + + struct gdc_task_param *param = calloc(1, sizeof(*param)); + + param->stTask = *pstTask; + param->type = GDC_TASK_TYPE_FISHEYE; // GDC_TASK_TYPE_AFFINE; + param->stFishEyeAttr = *pstAffineAttr; + *bReNew = true; + + if (*bReNew == false) { + return CVI_SUCCESS; + } + if (param->stTask.reserved != CVI_GDC_MAGIC) { + CVI_U64 paddr; + CVI_VOID *vaddr; + + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_CNV) != CVI_SUCCESS) { + *bReNew = true; + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + return CVI_ERR_GDC_NOBUF; + } + +#if USE_BIN_TXT + FILE *fp; + // int f_size; + // flag_mem = 1; + + CVI_U64 mesh_tbl_addr; + CVI_U16 *mesh_id; + + if (flag_mem) { + memset(ptbid, 0, sizeof(ptbid)); + fp = fopen("cnv_mesh_id.bin", "r"); + if (fp == NULL) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file not found.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_END); + f_size = ftell(fp); + if (f_size == -1) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file can't tell.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_SET); + fread(ptbid, 1, f_size, fp); + fclose(fp); + printf("mesh id size: %d\n", f_size); + } + mesh_id = vaddr; + memcpy(mesh_id, ptbid, f_size); + paddr += ALIGN(f_size + 0x1000, 32); + vaddr += ALIGN(f_size + 0x1000, 32); + + if (flag_mem) { + flag_mem = 0; + memset(ptbl, 0, sizeof(ptbl)); + + fp = fopen("cnv_mesh_tbl.bin", "r"); + if (fp == NULL) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file not found.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_END); + f_size = ftell(fp); + if (f_size == -1) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file can't tell.\n"); + return CVI_ERR_VO_NOT_PERMIT; + } + fseek(fp, 0, SEEK_SET); + fread(ptbl, 1, f_size, fp); + fclose(fp); + } + + memcpy(vaddr, ptbl, f_size); + + printf("mesh tbl size: %d\n", f_size); + mesh_tbl_addr = paddr; + + /**!! offset changes by mesh file !!**/ + CVI_U32 offset[3] = { 0x1440, 0x1200, 0x1200 }; + CVI_U8 index = 0; + + while (*mesh_id != 0xffff) { + if (*mesh_id == 0xfffb) { + if (index > 3) { + CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n"); + continue; + } + *(++mesh_id) = mesh_tbl_addr & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff; + *(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f; + mesh_tbl_addr += offset[index++]; + } + ++mesh_id; + } +#else + SIZE_S in_size, out_size; + + in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width; + in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height; + out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width; + out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height; + + struct timeval t0, t1; + + gettimeofday(&t0, NULL); + // got cnv mesh table from file + // get_cnv_warp_mesh_tbl(in_size, out_size, pstAffineAttr, paddr, vaddr); + // FISHEYE_ATTR_S pstFisheyeAttr; + mesh_gen_cnv(pfmesh_data, in_size, out_size, pstAffineAttr, paddr, vaddr); + + gettimeofday(&t1, NULL); + unsigned long elapsed_dwa = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec; + + printf("mesh_gen_cnv speed: %lu\n", elapsed_dwa); + +#endif + printf("out[0]\n"); + CVI_SYS_IonFlushCache(paddr, vaddr, + CVI_GDC_MESH_SIZE_CNV); // 0x100000); + printf("out[1]\n"); + param->stTask.au64privateData[0] = paddr; + param->stTask.au64privateData[1] = (uintptr_t)vaddr; + printf("finished\n"); + + *bReNew = false; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_SetMeshSize(int nMeshHor, int nMeshVer) +{ + return set_mesh_size(nMeshHor, nMeshVer); +} diff --git a/middleware/v2/modules/vpu/src/cvi_gdc_1822.c b/middleware/v2/modules/vpu/src/cvi_gdc_1822.c new file mode 100644 index 000000000..7cdc08238 --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_gdc_1822.c @@ -0,0 +1,684 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_buffer.h" +#include "cvi_base.h" +#include "cvi_sys.h" +#include "cvi_vb.h" + +#include "cvi_gdc.h" +#include "gdc_mesh.h" +#include "dwa_ioctl.h" +#include "vi_ioctl.h" +#include "vpss_ioctl.h" +#include "gdc_ctx.h" + + +#define DWA_YUV_BLACK 0x808000 +#define DWA_RGB_BLACK 0x0 + +#define CHECK_GDC_FORMAT(imgIn, imgOut) \ + do { \ + if (imgIn.stVFrame.enPixelFormat != imgOut.stVFrame.enPixelFormat) { \ + CVI_TRACE_GDC(CVI_DBG_ERR, "in/out pixelformat(%d-%d) mismatch\n", \ + imgIn.stVFrame.enPixelFormat, imgOut.stVFrame.enPixelFormat); \ + return CVI_ERR_GDC_ILLEGAL_PARAM; \ + } \ + if (!GDC_SUPPORT_FMT(imgIn.stVFrame.enPixelFormat)) { \ + CVI_TRACE_GDC(CVI_DBG_ERR, "pixelformat(%d) unsupported\n", imgIn.stVFrame.enPixelFormat); \ + return CVI_ERR_GDC_ILLEGAL_PARAM; \ + } \ + } while (0) + +static CVI_S32 gdc_rotation_check_size(ROTATION_E enRotation, const GDC_TASK_ATTR_S *pstTask) +{ + if (enRotation >= ROTATION_MAX) { + CVI_TRACE_GDC(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + if (enRotation == ROTATION_90 || enRotation == ROTATION_270 || enRotation == ROTATION_XY_FLIP) { + if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Height) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input height(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Width, + pstTask->stImgIn.stVFrame.u32Height); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Width) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input width(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Height, + pstTask->stImgIn.stVFrame.u32Width); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } else { + if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Width) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input width(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Width, + pstTask->stImgIn.stVFrame.u32Width); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Height) { + CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input height(%d)'\n", + enRotation, pstTask->stImgOut.stVFrame.u32Height, + pstTask->stImgIn.stVFrame.u32Height); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + + return CVI_SUCCESS; +} + +void gdcq_init(void) +{ +} + +CVI_S32 CVI_GDC_Suspend(void) +{ + CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_Resume(void) +{ + CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n"); + + return CVI_SUCCESS; +} + +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_GDC_BeginJob(GDC_HANDLE *phHandle) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, phHandle); + + struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + struct gdc_handle_data cfg; + + memset(&cfg, 0, sizeof(cfg)); + if (gdc_begin_job(d->fd, &cfg)) + return CVI_FAILURE; + + *phHandle = cfg.handle; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_EndJob(GDC_HANDLE hHandle) +{ + struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + struct gdc_handle_data cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.handle = hHandle; + return gdc_end_job(d->fd, &cfg); +} + +CVI_S32 CVI_GDC_CancelJob(GDC_HANDLE hHandle) +{ + struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + struct gdc_handle_data cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.handle = hHandle; + return gdc_cancel_job(d->fd, &cfg); +} + +CVI_S32 CVI_GDC_AddCorrectionTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, + const FISHEYE_ATTR_S *pstFishEyeAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstFishEyeAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(hHandle); + + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; +} + +CVI_S32 CVI_GDC_AddRotationTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, ROTATION_E enRotation) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(hHandle); + + if (enRotation == ROTATION_180) { + CVI_TRACE_GDC(CVI_DBG_ERR, "do not support rotation 180\n"); + return CVI_ERR_GDC_NOT_SUPPORT; + } + + if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + struct gdc_task_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.handle = hHandle; + memcpy(&attr.stImgIn, &pstTask->stImgIn, sizeof(attr.stImgIn)); + memcpy(&attr.stImgOut, &pstTask->stImgOut, sizeof(attr.stImgOut)); + //memcpy(attr.au64privateData, pstTask->au64privateData, sizeof(attr.au64privateData)); + //attr.reserved = pstTask->reserved; + attr.enRotation = enRotation; + return gdc_add_rotation_task(d->fd, &attr); +} + +CVI_S32 CVI_GDC_AddAffineTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const AFFINE_ATTR_S *pstAffineAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstAffineAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(hHandle); + + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; +} + +CVI_S32 CVI_GDC_AddLDCTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask + , const LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstLDCAttr); + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(hHandle); + + if (enRotation == ROTATION_180) { + CVI_TRACE_GDC(CVI_DBG_ERR, "do not support rotation 180\n"); + return CVI_ERR_GDC_NOT_SUPPORT; + } + + if (enRotation != ROTATION_0) { + if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0); + + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + struct gdc_task_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.handle = hHandle; + memcpy(&attr.stImgIn, &pstTask->stImgIn, sizeof(attr.stImgIn)); + memcpy(&attr.stImgOut, &pstTask->stImgOut, sizeof(attr.stImgOut)); + memcpy(attr.au64privateData, pstTask->au64privateData, sizeof(attr.au64privateData)); + attr.reserved = pstTask->reserved; + attr.enRotation = enRotation; + return gdc_add_ldc_task(d->fd, &attr); +} + +CVI_S32 CVI_GDC_AddCorrectionTaskCNV(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask + , const FISHEYE_ATTR_S *pstFishEyeAttr, uint8_t *p_tbl, uint8_t *p_idl, uint32_t *tbl_param) +{ + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(hHandle); + UNUSED(pstFishEyeAttr); + UNUSED(p_tbl); + UNUSED(p_idl); + UNUSED(tbl_param); + + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; +} + +CVI_S32 CVI_GDC_AddCnvWarpTask(const float *pfmesh_data, GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, + const FISHEYE_ATTR_S *pstAffineAttr, bool *bReNew) +{ + CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut); + UNUSED(pfmesh_data); + UNUSED(hHandle); + UNUSED(pstAffineAttr); + UNUSED(bReNew); + + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; +} + +CVI_S32 CVI_GDC_GenLDCMesh(CVI_U32 u32Width, CVI_U32 u32Height, const LDC_ATTR_S *pstLDCAttr, + const char *name, CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr) +{ + CVI_U64 paddr; + CVI_VOID *vaddr; + SIZE_S in_size, out_size; + CVI_U32 mesh_1st_size = 0, mesh_2nd_size = 0, mesh_size = 0; + ROTATION_E enRotation = ROTATION_0; + + if (pstLDCAttr->bAspect) { + if (pstLDCAttr->s32XYRatio < 0 || pstLDCAttr->s32XYRatio > 100) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32XYRatio(%d).\n" + , pstLDCAttr->s32XYRatio); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } else { + if (pstLDCAttr->s32XRatio < 0 || pstLDCAttr->s32XRatio > 100) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32XRatio(%d).\n" + , pstLDCAttr->s32XRatio); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstLDCAttr->s32YRatio < 0 || pstLDCAttr->s32YRatio > 100) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32YRatio(%d).\n" + , pstLDCAttr->s32YRatio); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + if (pstLDCAttr->s32CenterXOffset < -511 || pstLDCAttr->s32CenterXOffset > 511) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32CenterXOffset(%d).\n" + , pstLDCAttr->s32CenterXOffset); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstLDCAttr->s32CenterYOffset < -511 || pstLDCAttr->s32CenterYOffset > 511) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32CenterYOffset(%d).\n" + , pstLDCAttr->s32CenterYOffset); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (pstLDCAttr->s32DistortionRatio < -300 || pstLDCAttr->s32DistortionRatio > 500) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32DistortionRatio(%d).\n" + , pstLDCAttr->s32DistortionRatio); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + if (!name) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign name for LDC mesh\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + out_size.u32Width = in_size.u32Width; + out_size.u32Height = in_size.u32Height; + + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + mesh_size = mesh_1st_size + mesh_2nd_size; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "W=%d, H=%d, mesh_size=%d\n", + in_size.u32Width, in_size.u32Height, + mesh_size); + + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, name, mesh_size) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, " Can't acquire memory for LDC mesh.\n"); + return CVI_ERR_GDC_NOMEM; + } + + if (mesh_gen_ldc(in_size, out_size, pstLDCAttr, paddr, vaddr, enRotation) != CVI_SUCCESS) { + CVI_SYS_IonFree(paddr, vaddr); + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't generate ldc mesh.\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + CVI_SYS_IonFlushCache(paddr, vaddr, mesh_size); + + *pu64PhyAddr = paddr; + *ppVirAddr = vaddr; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_LoadLDCMesh(CVI_U32 u32Width, CVI_U32 u32Height, const char *fileNname + , const char *tskName, CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr) +{ + CVI_U64 paddr; + CVI_VOID *vaddr; + SIZE_S in_size, out_size; + CVI_U32 mesh_1st_size = 0, mesh_2nd_size = 0, mesh_size = 0; + + if (!fileNname) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign name for LDC mesh\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + if (!tskName) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign task name for LDC\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + out_size.u32Width = in_size.u32Width; + out_size.u32Height = in_size.u32Height; + + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + mesh_size = mesh_1st_size + mesh_2nd_size; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "W=%d, H=%d, mesh_size=%d\n" + , in_size.u32Width, in_size.u32Height, mesh_size); + + // acquire memory space for mesh. + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, tskName, mesh_size) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n"); + return CVI_ERR_GDC_NOMEM; + } + + FILE *fp = fopen(fileNname, "rb"); + if (!fp) { + CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", fileNname); + CVI_SYS_IonFree(paddr, vaddr); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + fseek(fp, 0, SEEK_END); + int fileSize = ftell(fp); + + if (mesh_size != (CVI_U32)fileSize) { + CVI_TRACE_GDC(CVI_DBG_ERR, "loadmesh file:(%s) size is not match.\n", fileNname); + CVI_SYS_IonFree(paddr, vaddr); + fclose(fp); + return CVI_FAILURE; + } + rewind(fp); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "load mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n", + mesh_size, paddr, vaddr); + + fread(vaddr, mesh_size, 1, fp); + fclose(fp); + CVI_SYS_IonFlushCache(paddr, vaddr, mesh_size); + + *pu64PhyAddr = paddr; + *ppVirAddr = vaddr; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_SetBufWrapAttr(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const DWA_BUF_WRAP_S *pstBufWrap) +{ + struct dwa_buf_wrap_cfg *cfg; + struct vdev *d; + CVI_S32 s32Ret; + + d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + cfg = malloc(sizeof(*cfg)); + if (!cfg) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc malloc fails.\n"); + return CVI_FAILURE; + } + + memset(cfg, 0, sizeof(*cfg)); + cfg->handle = hHandle; + memcpy(&cfg->stTask.stImgIn, &pstTask->stImgIn, sizeof(cfg->stTask.stImgIn)); + memcpy(&cfg->stTask.stImgOut, &pstTask->stImgOut, sizeof(cfg->stTask.stImgOut)); + memcpy(&cfg->stBufWrap, pstBufWrap, sizeof(cfg->stBufWrap)); + + s32Ret = gdc_set_chn_buf_wrap(d->fd, cfg); + + free(cfg); + + return s32Ret; +} + +CVI_S32 CVI_GDC_GetBufWrapAttr(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, DWA_BUF_WRAP_S *pstBufWrap) +{ + struct dwa_buf_wrap_cfg *cfg; + struct vdev *d; + CVI_S32 s32Ret; + + d = get_dev_info(VDEV_TYPE_DWA, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state); + return CVI_ERR_GDC_SYS_NOTREADY; + } + + cfg = malloc(sizeof(*cfg)); + if (!cfg) { + CVI_TRACE_GDC(CVI_DBG_ERR, "gdc malloc fails.\n"); + return CVI_FAILURE; + } + + memset(cfg, 0, sizeof(*cfg)); + cfg->handle = hHandle; + memcpy(&cfg->stTask, pstTask, sizeof(cfg->stTask)); + + s32Ret = gdc_get_chn_buf_wrap(d->fd, cfg); + + free(cfg); + + if (s32Ret == CVI_SUCCESS) + memcpy(pstBufWrap, &cfg->stBufWrap, sizeof(*pstBufWrap)); + + return s32Ret; +} + +CVI_S32 CVI_GDC_DumpMesh(MESH_DUMP_ATTR_S *pMeshDumpAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pMeshDumpAttr); + + CVI_U64 phyMesh; + CVI_VOID *virMesh; + CVI_U32 u32Width, u32Height, vpssGrp, vpssChn, viChn; + SIZE_S in_size, out_size; + CVI_U32 mesh_1st_size, mesh_2nd_size, meshSize; + CVI_S32 s32Ret; + CVI_S32 fd; + struct vpss_chn_attr attr; + + FILE *fp; + MOD_ID_E mod = pMeshDumpAttr->enModId; + CVI_CHAR *filePath = pMeshDumpAttr->binFileName; + + switch (mod) { + case CVI_ID_VI: + viChn = pMeshDumpAttr->viMeshAttr.chn; + phyMesh = g_vi_mesh[viChn].paddr; + virMesh = g_vi_mesh[viChn].vaddr; + u32Width = gViCtx->chnAttr[viChn].stSize.u32Width; + u32Height = gViCtx->chnAttr[viChn].stSize.u32Height; + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + out_size.u32Width = in_size.u32Width; + out_size.u32Height = in_size.u32Height; + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + meshSize = mesh_1st_size + mesh_2nd_size; + break; + case CVI_ID_VPSS: + fd = get_vpss_fd(); + attr.VpssGrp = vpssGrp = pMeshDumpAttr->vpssMeshAttr.grp; + attr.VpssChn = vpssChn = pMeshDumpAttr->vpssMeshAttr.chn; + phyMesh = mesh[vpssGrp][vpssChn].paddr; + virMesh = mesh[vpssGrp][vpssChn].vaddr; + + s32Ret = vpss_get_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", vpssGrp, vpssChn); + return s32Ret; + } + u32Width = attr.stChnAttr.u32Width; + u32Height = attr.stChnAttr.u32Height; + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + out_size.u32Width = in_size.u32Width; + out_size.u32Height = in_size.u32Height; + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + meshSize = mesh_1st_size + mesh_2nd_size; + break; + default: + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "dump mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n", + meshSize, phyMesh, virMesh); + + fp = fopen(filePath, "wb"); + if (!fp) { + CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", filePath); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + fwrite(virMesh, meshSize, 1, fp); + fflush(fp); + fclose(fp); + return CVI_SUCCESS; +} + +CVI_S32 CVI_GDC_LoadMesh(MESH_DUMP_ATTR_S *pMeshDumpAttr) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, pMeshDumpAttr); + + CVI_U64 phyMesh; + CVI_VOID *virMesh; + CVI_U32 vpssGrp = 0, vpssChn = 0, viChn = 0; + SIZE_S in_size, out_size; + CVI_U32 mesh_1st_size, mesh_2nd_size, mesh_size; + CVI_U32 u32Width, u32Height; + struct cvi_gdc_mesh *pmesh; + FILE *fp; + CVI_S32 fd; + MOD_ID_E mod = pMeshDumpAttr->enModId; + CVI_CHAR *filePath = pMeshDumpAttr->binFileName; + CVI_S32 s32Ret; + struct vpss_chn_attr attr; + + switch (mod) { + case CVI_ID_VI: + viChn = pMeshDumpAttr->viMeshAttr.chn; + pmesh = &g_vi_mesh[viChn]; + u32Width = gViCtx->chnAttr[viChn].stSize.u32Width; + u32Height = gViCtx->chnAttr[viChn].stSize.u32Height; + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + break; + case CVI_ID_VPSS: + fd = get_vpss_fd(); + attr.VpssGrp = vpssGrp = pMeshDumpAttr->vpssMeshAttr.grp; + attr.VpssChn = vpssChn = pMeshDumpAttr->vpssMeshAttr.chn; + pmesh = &mesh[vpssGrp][vpssChn]; + + s32Ret = vpss_get_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", vpssGrp, vpssChn); + return s32Ret; + } + u32Width = attr.stChnAttr.u32Width; + u32Height = attr.stChnAttr.u32Height; + in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN); + in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN); + break; + default: + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + return CVI_ERR_GDC_NOT_SUPPORT; + } + + out_size.u32Width = in_size.u32Width; + out_size.u32Height = in_size.u32Height; + + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + mesh_size = mesh_1st_size + mesh_2nd_size; + + fp = fopen(filePath, "rb"); + if (!fp) { + CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", filePath); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + fseek(fp, 0, SEEK_END); + int fileSize = ftell(fp); + + if (mesh_size != (CVI_U32)fileSize) { + CVI_TRACE_GDC(CVI_DBG_ERR, "loadmesh file:(%s) size is not match.\n", filePath); + fclose(fp); + return CVI_FAILURE; + } + rewind(fp); + + // acquire memory space for mesh. + if (CVI_SYS_IonAlloc_Cached(&phyMesh, &virMesh, "gdc_mesh", mesh_size) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for gdc mesh.\n"); + fclose(fp); + return CVI_ERR_VPSS_NOMEM; + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "load mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n", + mesh_size, phyMesh, virMesh); + pmesh->paddr = phyMesh; + pmesh->vaddr = virMesh; + + fread(virMesh, mesh_size, 1, fp); + CVI_SYS_IonFlushCache(phyMesh, virMesh, mesh_size); + + switch (mod) { + case CVI_ID_VI: + g_vi_mesh[viChn].meshSize = mesh_size; + //vi_ctx.stLDCAttr[viChn].bEnable = CVI_TRUE; + + fd = get_vi_fd(); + struct vi_chn_ldc_cfg vi_cfg; + + vi_cfg.ViChn = viChn; + vi_cfg.enRotation = ROTATION_0; + //vi_cfg.stLDCAttr = *pstLDCAttr; + vi_cfg.stLDCAttr.bEnable = CVI_TRUE; + vi_cfg.meshHandle = pmesh->paddr; + if (vi_sdk_set_chn_ldc(fd, &vi_cfg) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "VI Set Chn(%d) LDC fail\n", viChn); + fclose(fp); + return CVI_FAILURE; + } + break; + case CVI_ID_VPSS: + mesh[vpssGrp][vpssChn].meshSize = mesh_size; + //vpssCtx[vpssGrp].stChnCfgs[vpssChn].stLDCAttr.bEnable = CVI_TRUE; + fd = get_vpss_fd(); + struct vpss_chn_ldc_cfg vpss_cfg; + + vpss_cfg.VpssGrp = vpssGrp; + vpss_cfg.VpssChn = vpssChn; + vpss_cfg.enRotation = ROTATION_0; + //vpss_cfg.stLDCAttr = *pstLDCAttr; + vpss_cfg.stLDCAttr.bEnable = CVI_TRUE; + vpss_cfg.meshHandle = pmesh->paddr; + if (vpss_set_chn_ldc(fd, &vpss_cfg) != CVI_SUCCESS) { + CVI_TRACE_GDC(CVI_DBG_ERR, "VPSS Set Chn(%d) LDC fail\n", vpssChn); + fclose(fp); + return CVI_FAILURE; + } + break; + default: + CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n"); + fclose(fp); + return CVI_ERR_GDC_NOT_SUPPORT; + } + fclose(fp); + return CVI_SUCCESS; +} diff --git a/middleware/v2/modules/vpu/src/cvi_region.c b/middleware/v2/modules/vpu/src/cvi_region.c new file mode 100644 index 000000000..da7a6490c --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_region.c @@ -0,0 +1,319 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include + +#include "cvi_base.h" +#include +#include "cvi_sys.h" +#include "cvi_vpss.h" +#include "cvi_vo.h" +#include "cvi_region.h" +#include "hashmap.h" +#include "rgn_ioctl.h" + +struct rgn_canvas { + STAILQ_ENTRY(rgn_canvas) stailq; + RGN_HANDLE Handle; + CVI_U64 u64PhyAddr; + CVI_U8 *pu8VirtAddr; + CVI_U32 u32Size; +}; + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_mutex_t canvas_q_lock = PTHREAD_MUTEX_INITIALIZER; +STAILQ_HEAD(rgn_canvas_q, rgn_canvas) canvas_q; + +static void rgn_init(void) +{ + STAILQ_INIT(&canvas_q); +} + +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_RGN_Create(RGN_HANDLE Handle, const RGN_ATTR_S *pstRegion) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion); + + // Driver control + fd = get_rgn_fd(); + if (rgn_create(fd, Handle, pstRegion) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Create RGN fail.\n"); + return CVI_FAILURE; + } + + pthread_mutex_lock(&canvas_q_lock); + pthread_once(&once, rgn_init); + pthread_mutex_unlock(&canvas_q_lock); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_Destroy(RGN_HANDLE Handle) +{ + CVI_S32 fd = -1; + + // Driver control + fd = get_rgn_fd(); + if (rgn_destroy(fd, Handle) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Destroy RGN fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_GetAttr(RGN_HANDLE Handle, RGN_ATTR_S *pstRegion) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion); + + // Driver control + fd = get_rgn_fd(); + if (rgn_get_attr(fd, Handle, pstRegion) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Get RGN attributes fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_SetAttr(RGN_HANDLE Handle, const RGN_ATTR_S *pstRegion) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion); + // Driver control + fd = get_rgn_fd(); + if (rgn_set_attr(fd, Handle, pstRegion) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Set RGN attributes fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_SetBitMap(RGN_HANDLE Handle, const BITMAP_S *pstBitmap) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstBitmap); + // Driver control + fd = get_rgn_fd(); + + s32Ret = rgn_set_bit_map(fd, Handle, pstBitmap); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Set RGN Bitmap fail, s32Ret=%x.\n", s32Ret); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_AttachToChn(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn); + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr); + +#ifdef __SOC_PHOBOS__ + if (pstChn->enModId == CVI_ID_VO) { + CVI_TRACE_RGN(CVI_DBG_ERR, "No vo device, cannot attach to vo!\n"); + return CVI_ERR_RGN_ILLEGAL_PARAM; + } +#endif + + // Driver control + fd = get_rgn_fd(); + if (rgn_attach_to_chn(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Attach RGN to channel fail.\n"); + return CVI_FAILURE; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_DetachFromChn(RGN_HANDLE Handle, const MMF_CHN_S *pstChn) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn); + +#ifdef __SOC_PHOBOS__ + if (pstChn->enModId == CVI_ID_VO) { + CVI_TRACE_RGN(CVI_DBG_ERR, "No vo device, cannot detach from vo!\n"); + return CVI_ERR_RGN_ILLEGAL_PARAM; + } +#endif + + // Driver control + fd = get_rgn_fd(); + if (rgn_detach_from_chn(fd, Handle, pstChn) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Detach RGN from channel fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_SetDisplayAttr(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn); + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr); + + // Driver control + fd = get_rgn_fd(); + if (rgn_set_display_attr(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Set display RGN attributes fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_GetDisplayAttr(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, RGN_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn); + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr); + + // Driver control + fd = get_rgn_fd(); + if (rgn_get_display_attr(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Get display RGN attributes fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_GetCanvasInfo(RGN_HANDLE Handle, RGN_CANVAS_INFO_S *pstCanvasInfo) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret; + struct rgn_canvas *canvas; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstCanvasInfo); + + // Driver control + fd = get_rgn_fd(); + + s32Ret = rgn_get_canvas_info(fd, Handle, pstCanvasInfo); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Get RGN canvas information fail, s32Ret=%x.\n", s32Ret); + return s32Ret; + } + + canvas = calloc(1, sizeof(struct rgn_canvas)); + if (!canvas) { + CVI_TRACE_RGN(CVI_DBG_ERR, "malloc failed.\n"); + return CVI_ERR_RGN_NOMEM; + } + pthread_mutex_lock(&canvas_q_lock); + canvas->u64PhyAddr = pstCanvasInfo->u64PhyAddr; + canvas->u32Size = pstCanvasInfo->u32Stride * pstCanvasInfo->stSize.u32Height; + pstCanvasInfo->pu8VirtAddr = canvas->pu8VirtAddr = + CVI_SYS_Mmap(pstCanvasInfo->u64PhyAddr, canvas->u32Size); + if (pstCanvasInfo->pu8VirtAddr == NULL) { + free(canvas); + CVI_TRACE_RGN(CVI_DBG_INFO, "CVI_SYS_Mmap NG.\n"); + return CVI_FAILURE; + } + canvas->Handle = Handle; + pstCanvasInfo->pstCanvasCmprAttr = (RGN_CANVAS_CMPR_ATTR_S *)pstCanvasInfo->pu8VirtAddr; + pstCanvasInfo->pstObjAttr = (RGN_CMPR_OBJ_ATTR_S *)(pstCanvasInfo->pu8VirtAddr + + sizeof(RGN_CANVAS_CMPR_ATTR_S)); + STAILQ_INSERT_TAIL(&canvas_q, canvas, stailq); + pthread_mutex_unlock(&canvas_q_lock); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_UpdateCanvas(RGN_HANDLE Handle) +{ + CVI_S32 fd = -1; + struct rgn_canvas *canvas; + + // Driver control + fd = get_rgn_fd(); + if (rgn_update_canvas(fd, Handle) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Update RGN canvas fail.\n"); + return CVI_FAILURE; + } + + pthread_mutex_lock(&canvas_q_lock); + if (!STAILQ_EMPTY(&canvas_q)) { + STAILQ_FOREACH(canvas, &canvas_q, stailq) { + if (canvas->Handle == Handle) { + STAILQ_REMOVE(&canvas_q, canvas, rgn_canvas, stailq); + CVI_SYS_Munmap(canvas->pu8VirtAddr, canvas->u32Size); + free(canvas); + break; + } + } + } + pthread_mutex_unlock(&canvas_q_lock); + + return CVI_SUCCESS; +} + +/* CVI_RGN_Invert_Color - invert color per luma statistics of video content + * Chns' pixel-format should be YUV. + * RGN's pixel-format should be ARGB1555. + * + * @param Handle: RGN Handle + * @param pstChn: the chn which rgn attached + * @param pu32Color: rgn's content + */ +CVI_S32 CVI_RGN_Invert_Color(RGN_HANDLE Handle, MMF_CHN_S *pstChn, CVI_U32 *pu32Color) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn); + MOD_CHECK_NULL_PTR(CVI_ID_RGN, pu32Color); + + // Driver control + fd = get_rgn_fd(); + if (rgn_invert_color(fd, Handle, pstChn, (void *)pu32Color) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Invert RGN color fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_RGN_SetChnPalette(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, RGN_PALETTE_S *pstPalette) +{ + struct vdev *d; + + // Driver control + d = get_dev_info(VDEV_TYPE_RGN, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_RGN(CVI_DBG_ERR, "rgn state(%d) incorrect.", d->state); + return CVI_ERR_RGN_SYS_NOTREADY; + } + + if (rgn_set_chn_palette(d->fd, Handle, pstChn, pstPalette) != CVI_SUCCESS) { + CVI_TRACE_RGN(CVI_DBG_INFO, "Invert RGN color fail.\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} diff --git a/middleware/v2/modules/vpu/src/cvi_vi.c b/middleware/v2/modules/vpu/src/cvi_vi.c new file mode 100644 index 000000000..6dc5a7bd7 --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_vi.c @@ -0,0 +1,2170 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_buffer.h" +#include "cvi_base.h" +#include "cvi_vi.h" +#include "cvi_vb.h" +#include "cvi_sys.h" +#include "cvi_gdc.h" +#include "vi_ioctl.h" +#include "gdc_mesh.h" +#include "cvi_sns_ctrl.h" +#include "dump_register.h" +#include + + +#define CHECK_VI_PIPEID_VALID(x) \ + do { \ + if ((x) > (VI_MAX_PIPE_NUM - 1)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " invalid pipe-id(%d)\n", x); \ + return CVI_ERR_VI_INVALID_PIPEID; \ + } \ + } while (0) + +#define CHECK_VI_DEVID_VALID(x) \ + do { \ + if ((x) > (VI_MAX_DEV_NUM - 1)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " invalid dev-id(%d)\n", x); \ + return CVI_ERR_VI_INVALID_DEVID; \ + } \ + } while (0) + +#define CHECK_VI_CHNID_VALID(x) \ + do { \ + if ((x) > (VI_MAX_CHN_NUM - 1)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " invalid chn-id(%d)\n", x); \ + return CVI_ERR_VI_INVALID_CHNID; \ + } \ + } while (0) + +#define CHECK_VI_NULL_PTR(ptr) \ + do { \ + if (ptr == NULL) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " Invalid null pointer\n"); \ + return CVI_ERR_VI_INVALID_NULL_PTR; \ + } \ + } while (0) + +#define CHECK_VI_PIPE_CREATED(pipe) \ + do { \ + if (gViCtx->isPipeCreated[pipe] == CVI_FALSE) { \ + CVI_TRACE_VI(CVI_DBG_WARN, "Pipe(%d) is stop\n", pipe); \ + return CVI_SUCCESS; \ + } \ + } while (0) + +#define VDEV_CLOSED_CHK(_dev_type, _dev_id) \ + struct vdev *d; \ + d = get_dev_info(_dev_type, 0); \ + if (IS_VDEV_CLOSED(d->state)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, "vi dev(0) state(%d) incorrect.", d->state);\ + return CVI_ERR_VI_SYS_NOTREADY; \ + } + +#define VIPIPE_TO_DEV(_pipe_id, _dev_id) \ + do { \ + if (_pipe_id == 0 || _pipe_id == 1) \ + _dev_id = 0; \ + else if (_pipe_id == 2 || _pipe_id == 3) \ + _dev_id = 1; \ + } while (0) + +#define CHECK_VI_EXTCHNID_VALID(x) \ + do { \ + if (((x) < VI_EXT_CHN_START) || ((x) >= (VI_EXT_CHN_START + VI_MAX_EXT_CHN_NUM))) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " invalid extchn-id(%d)\n", x); \ + return CVI_ERR_VI_INVALID_CHNID; \ + } \ + } while (0) + +#define CHECK_VI_GDC_FMT(x) \ + do { \ + if (!GDC_SUPPORT_FMT(x)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, "invalid PixFormat(%d) for gdc.\n", (x)); \ + return CVI_ERR_VI_INVALID_PARA; \ + } \ + } while (0) + +static inline CVI_S32 CHECK_VI_CTX_NULL_PTR(void *ptr) +{ + CVI_S32 ret = CVI_SUCCESS; + + if (ptr == NULL) { + CVI_TRACE_VI(CVI_DBG_ERR, "Call SetDevAttr first\n"); + ret = CVI_ERR_VI_FAILED_NOTCONFIG; + } + + return ret; +} + +typedef CVI_VOID (*pfnChnMirrorFlip) (VI_PIPE ViPipe, ISP_SNS_MIRRORFLIP_TYPE_E eChnMirrorFlip); +static pfnChnMirrorFlip s_pfnDevMirrorFlip[VI_MAX_DEV_NUM]; + +struct vi_pm_s { + VI_PM_OPS_S stOps; + CVI_VOID *pvData; +}; +static struct vi_pm_s apstViPm[VI_MAX_DEV_NUM] = { 0 }; + +static struct cvi_vi_ctx vi_ctx_bak; +//VI dma buffer addr +static CVI_U64 dmaBufpAddr; +struct cvi_gdc_mesh g_vi_mesh[VI_MAX_CHN_NUM]; + +struct cvi_vi_ctx *gViCtx; + +struct vi_dbg_th_info_s { + CVI_U8 th_enable; + pthread_t vi_dbg_thread; +}; +struct vi_dbg_th_info_s gViDbgTH; + +/************************************************************************** + * Internal APIs for vi only + **************************************************************************/ + +static CVI_VOID *vi_dbg_handler(CVI_VOID *data) +{ + CVI_S32 fd = -1; + fd_set rfds; + //struct timeval tv; + CVI_S32 ret = CVI_SUCCESS; + UNUSED(data); + + prctl(PR_SET_NAME, "vi_dbg_handler"); + + fd = get_vi_fd(); + + gViDbgTH.th_enable = CVI_TRUE; + + while (gViDbgTH.th_enable) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + //tv.tv_sec = 10; + //tv.tv_usec = 0; + + ret = select(fd + 1, &rfds, NULL, NULL, NULL); + if (ret == -1) { + if (errno == EINTR) + continue; + CVI_TRACE_VI(CVI_DBG_ERR, "vi_dbg_thread select error\n"); + break; + } + + //Cat vi_dbg/mipi_rx if error + if (FD_ISSET(fd, &rfds) && gViDbgTH.th_enable) { + system("cat /proc/mipi-rx"); + system("cat /proc/cvitek/vi_dbg"); + } + } + CVI_TRACE_VI(CVI_DBG_INFO, "-\n"); + + pthread_exit(NULL); +} + +static CVI_S32 _vi_proc_mmap(void) +{ + struct vdev *d; + + d = get_dev_info(VDEV_TYPE_ISP, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi state(%d) incorrect.", d->state); + return CVI_ERR_VI_SYS_NOTREADY; + } + + if (gViCtx != NULL) { + CVI_TRACE_VI(CVI_DBG_DEBUG, "vi proc has already done mmap\n"); + return CVI_SUCCESS; + } + + gViCtx = (struct cvi_vi_ctx *)mmap(NULL, VI_SHARE_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, d->fd, 0); + if (gViCtx == MAP_FAILED) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi proc mmap fail!\n"); + return CVI_FAILURE; + } + + memset(gViCtx, 0, sizeof(*gViCtx)); + + return CVI_SUCCESS; +} + +static CVI_S32 _vi_proc_unmap(void) +{ + if (gViCtx == NULL) { + CVI_TRACE_VI(CVI_DBG_DEBUG, "VI proc no need to unmap\n"); + return CVI_SUCCESS; + } + + munmap((void *)gViCtx, VI_SHARE_MEM_SIZE); + + gViCtx = NULL; + + return CVI_SUCCESS; +} + +static CVI_S32 _vi_chn_enable_mirror_flip(VI_CHN ViChn) +{ + ISP_SNS_MIRRORFLIP_TYPE_E eChnMirrorFlip; + VI_DEV ViDev = 0; + + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (gViCtx->chnAttr[ViChn].bMirror && gViCtx->chnAttr[ViChn].bFlip) + eChnMirrorFlip = ISP_SNS_MIRROR_FLIP; + else if (gViCtx->chnAttr[ViChn].bMirror) + eChnMirrorFlip = ISP_SNS_MIRROR; + else if (gViCtx->chnAttr[ViChn].bFlip) + eChnMirrorFlip = ISP_SNS_FLIP; + else + eChnMirrorFlip = ISP_SNS_NORMAL; + + if (eChnMirrorFlip != ISP_SNS_NORMAL && !s_pfnDevMirrorFlip[ViChn]) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI chn mirror/flip do not support this sensor."); + return CVI_ERR_VI_NOT_SUPPORT; + } + + if ((CVI_U32)ViChn < gViCtx->devAttr[0].chn_num) + ViDev = 0; + else + ViDev = 1; + + if (s_pfnDevMirrorFlip[ViDev]) + s_pfnDevMirrorFlip[ViDev](ViDev, eChnMirrorFlip); + + return CVI_SUCCESS; +} + +CVI_S32 _vi_update_rotation_mesh(VI_CHN ViChn, ROTATION_E enRotation) +{ + struct vi_chn_rot_cfg cfg; + CVI_S32 fd = get_vi_fd(); + + cfg.ViChn = ViChn; + cfg.enRotation = enRotation; + if (vi_sdk_set_chn_rotation(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI Set Chn(%d) Rotation(%d) fail\n", ViChn, enRotation); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +static CVI_S32 _vi_update_ldc_mesh(VI_PIPE ViPipe, VI_CHN ViChn, + const VI_LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation) +{ + CVI_U64 paddr, paddr_old; + CVI_VOID *vaddr, *vaddr_old; + struct cvi_gdc_mesh *pmesh = &g_vi_mesh[ViChn]; + CVI_S32 s32Ret; + + if (!pstLDCAttr->bEnable) { + pthread_mutex_lock(&pmesh->lock); + gViCtx->stLDCAttr[ViChn] = *pstLDCAttr; + pthread_mutex_unlock(&pmesh->lock); + + if (gViCtx->enRotation[ViChn] != ROTATION_0) + return _vi_update_rotation_mesh(ViChn, gViCtx->enRotation[ViChn]); + else + return CVI_SUCCESS; + } + + s32Ret = CVI_GDC_GenLDCMesh(gViCtx->chnAttr[ViChn].stSize.u32Width + , gViCtx->chnAttr[ViChn].stSize.u32Height + , &pstLDCAttr->stAttr, "vi_mesh", &paddr, &vaddr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "Chn(%d) gen mesh fail\n", ViChn); + return s32Ret; + } + + pthread_mutex_lock(&pmesh->lock); + if (pmesh->paddr) { + paddr_old = pmesh->paddr; + vaddr_old = pmesh->vaddr; + } else { + paddr_old = 0; + vaddr_old = NULL; + } + pmesh->paddr = paddr; + pmesh->vaddr = vaddr; + //gViCtx->stLDCAttr[ViChn] = *pstLDCAttr; + //gViCtx->enRotation[ViChn] = enRotation; + pthread_mutex_unlock(&pmesh->lock); + + if (paddr_old && paddr_old != DEFAULT_MESH_PADDR) + CVI_SYS_IonFree(paddr_old, vaddr_old); + + CVI_TRACE_VI(CVI_DBG_DEBUG, "ViPipe(%d) ViChn(%d) mesh base(%#"PRIx64") vaddr(%p)\n" + , ViPipe, ViChn, paddr, vaddr); + + CVI_S32 fd = get_vi_fd(); + struct vi_chn_ldc_cfg cfg; + + cfg.ViChn = ViChn; + cfg.enRotation = enRotation; + cfg.stLDCAttr = *pstLDCAttr; + cfg.meshHandle = paddr; + if (vi_sdk_set_chn_ldc(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI Set Chn(%d) LDC fail\n", ViChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 _cvi_vi_freeIonBuf(void) +{ + CVI_S32 ret = CVI_SUCCESS; + + if (dmaBufpAddr) { + ret = CVI_SYS_IonFree(dmaBufpAddr, NULL); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "Free Ion dmaBufAddr failed\n"); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } + } + + CVI_TRACE_VI(CVI_DBG_DEBUG, "VI FreeIonBuf success\n"); + + dmaBufpAddr = 0; + return ret; +} + +CVI_S32 _cvi_vi_getIonBuf(void) +{ + CVI_U64 pAddr = 0; + CVI_S32 ret = CVI_SUCCESS; + CVI_U32 size = 0; + struct vdev *d; + struct cvi_vi_dma_buf_info info = {.paddr = 0, .size = 0}; + + d = get_dev_info(VDEV_TYPE_ISP, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi state(%d) incorrect.", d->state); + return CVI_ERR_VI_SYS_NOTREADY; + } + + //ioctl to isp driver to get size + ret = vi_get_dma_size(d->fd, &size); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_dma_size ioctl failed\n"); + return CVI_ERR_VI_NOMEM; + } + + if (size == 0) { + for (int i = 0; i < gViCtx->total_dev_num; i++) { + if (gViCtx->devAttr[i].enInputDataType == VI_DATA_TYPE_RGB) { + CVI_TRACE_VI(CVI_DBG_ERR, "get dma size(%d) error\n", size); + return CVI_ERR_VI_NOMEM; + } + } + + dmaBufpAddr = 0; + CVI_TRACE_VI(CVI_DBG_DEBUG, "yuv sensor not need dma size\n"); + return CVI_SUCCESS; + } + + ret = CVI_SYS_IonAlloc_Cached(&pAddr, NULL, "VI_DMA_BUF", size); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI ion alloc size(%d) failed.\n", size); + return CVI_ERR_VI_NOMEM; + } + + //set paddr and size to isp driver + info.paddr = pAddr; + info.size = size; + ret = vi_set_dma_buf_info(d->fd, &info); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_set_dma_buf_info ioctl failed\n"); + CVI_SYS_IonFree(pAddr, NULL); + return CVI_ERR_VI_NOT_SUPPORT; + } + + dmaBufpAddr = pAddr; + + CVI_TRACE_VI(CVI_DBG_INFO, "VI ion alloc size(%d) success\n", info.size); + + return ret; +} + +/************************************************************************** + * Internal APIs for other modules + **************************************************************************/ + +CVI_S32 CVI_VI_Suspend(void) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_U8 i = 0; + + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + gViCtx->vi_stt = VI_SUSPEND; + + memcpy(&vi_ctx_bak, gViCtx, sizeof(struct cvi_vi_ctx)); + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + s32Ret = CVI_VI_DisableChn(0, i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_DisableChn failed with %#x!\n", s32Ret); + return s32Ret; + } + /* suspend sensor. */ + if (apstViPm[i].stOps.pfnSnsSuspend) { + s32Ret = apstViPm[i].stOps.pfnSnsSuspend(apstViPm[i].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "sensor[%d] suspend failed with %#x!\n", i, s32Ret); + return s32Ret; + } + } + /* suspend mipi. */ + if (apstViPm[i].stOps.pfnMipiSuspend) { + s32Ret = apstViPm[i].stOps.pfnMipiSuspend(apstViPm[i].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "mipi[%d] suspend failed with %#x!\n", i, s32Ret); + return s32Ret; + } + } + } + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + s32Ret = CVI_VI_DestroyPipe(i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_DestroyPipe failed with %#x!\n", s32Ret); + return s32Ret; + } + } + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + s32Ret = CVI_VI_DisableDev(i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_DisableDev failed with %#x!\n", s32Ret); + return s32Ret; + } + } + + //CVI_SYS_VI_Close(); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_Resume(void) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_U8 i = 0; + VI_DEV_ATTR_S stViDevAttr; + VI_PIPE_ATTR_S stPipeAttr; + VI_CHN_ATTR_S stChnAttr; + struct vdev *d; + + //CVI_SYS_VI_Open(); + + d = get_dev_info(VDEV_TYPE_ISP, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi dev(%d) state(%d) incorrect.", 0, d->state); + return CVI_ERR_VI_SYS_NOTREADY; + } + + s32Ret = vi_set_clk(d->fd, 1); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "Set isp clk ioctl\n"); + return CVI_FAILURE; + } + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + /* resume mipi. */ + if (apstViPm[i].stOps.pfnMipiResume) { + s32Ret = apstViPm[i].stOps.pfnMipiResume(apstViPm[i].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "mipi[%d] resume failed with %#x!\n", i, s32Ret); + return s32Ret; + } + } + /* resume sensor. */ + if (apstViPm[i].stOps.pfnSnsResume) { + s32Ret = apstViPm[i].stOps.pfnSnsResume(apstViPm[i].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "sensor[%d] resume failed with %#x!\n", i, s32Ret); + return s32Ret; + } + } + + memcpy(&stViDevAttr, &vi_ctx_bak.devAttr[i], sizeof(VI_DEV_ATTR_S)); + + s32Ret = CVI_VI_SetDevAttr(i, &stViDevAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_SetDevAttr failed with %#x!\n", s32Ret); + return s32Ret; + } + + s32Ret = CVI_VI_EnableDev(i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_EnableDev failed with %#x!\n", s32Ret); + return s32Ret; + } + } + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + memcpy(&stPipeAttr, &vi_ctx_bak.pipeAttr[i], sizeof(VI_PIPE_ATTR_S)); + + s32Ret = CVI_VI_CreatePipe(i, &stPipeAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_CreatePipe failed with %#x!\n", s32Ret); + return s32Ret; + } + + s32Ret = CVI_VI_StartPipe(i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_StartPipe failed with %#x!\n", s32Ret); + return s32Ret; + } + } + + for (i = 0; i < vi_ctx_bak.total_dev_num; i++) { + memcpy(&stChnAttr, &vi_ctx_bak.chnAttr[i], sizeof(VI_CHN_ATTR_S)); + + s32Ret = CVI_VI_SetChnAttr(0, i, &stChnAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_SetChnAttr failed with %#x!\n", s32Ret); + return CVI_FAILURE; + } + + s32Ret = CVI_VI_EnableChn(0, i); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "CVI_VI_EnableChn failed with %#x!\n", s32Ret); + return CVI_FAILURE; + } + } + + //gViCtx->vi_stt = vi_prc_ctx->vi_stt = VI_RUNNING; + + return CVI_SUCCESS; +} + +CVI_VOID CVI_VI_SetMotionLV(struct mlv_info mlevel_i) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + struct vdev *d; + struct mlv_info_s mlv_i_tmp; + + d = get_dev_info(VDEV_TYPE_ISP, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi state(%d) incorrect.", d->state); + s32Ret = CVI_FAILURE; + } + + if (s32Ret == CVI_SUCCESS) { + mlv_i_tmp.sensor_num = mlevel_i.sensor_num; + mlv_i_tmp.frm_num = mlevel_i.frm_num; + mlv_i_tmp.mlv = mlevel_i.mlv; + memcpy(mlv_i_tmp.mtable, mlevel_i.mtable, MO_TBL_SIZE); + + s32Ret = vi_sdk_set_motion_lv(d->fd, &mlv_i_tmp); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_motion_lv ioctl failed\n"); + } + } +} + +CVI_VOID CVI_VI_SET_DIS_INFO(struct dis_info dis_i) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + struct vdev *d; + struct dis_info_s dis_i_tmp; + + d = get_dev_info(VDEV_TYPE_ISP, 0); + if (!IS_VDEV_OPEN(d->state)) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi state(%d) incorrect.", d->state); + s32Ret = CVI_FAILURE; + } + + if (s32Ret == CVI_SUCCESS) { + dis_i_tmp.sensor_num = dis_i.sensor_num; + dis_i_tmp.frm_num = dis_i.frm_num; + dis_i_tmp.dis_i.start_x = dis_i.dis_i.start_x; + dis_i_tmp.dis_i.start_y = dis_i.dis_i.start_y; + dis_i_tmp.dis_i.end_x = dis_i.dis_i.end_x; + dis_i_tmp.dis_i.end_y = dis_i.dis_i.end_y; + + s32Ret = vi_sdk_set_dis_info(d->fd, &dis_i_tmp); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_dis_info ioctl failed\n"); + } + } +} + +CVI_S32 CVI_VI_SetBypassFrm(CVI_U32 snr_num, CVI_U8 bypass_num) +{ + CHECK_VI_CHNID_VALID(snr_num); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + gViCtx->bypass_frm[snr_num] = bypass_num; + + return CVI_SUCCESS; +} + +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_VI_SetDevNum(CVI_U32 devNum) +{ + UNUSED(devNum); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetDevNum(CVI_U32 *devNum) +{ + CHECK_VI_NULL_PTR(devNum); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *devNum = gViCtx->total_dev_num; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetDevAttr(VI_DEV ViDev, const VI_DEV_ATTR_S *pstDevAttr) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + VI_DEV_ATTR_S devAttr; + + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevAttr); + + fd = get_vi_fd(); + + if (ViDev == 0 && (gViCtx == NULL)) { + if (_vi_proc_mmap() != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "_vi_proc_mmap failed.\n"); + return CVI_ERR_VI_BUF_EMPTY; + } + + for (int i = 0; i < VI_MAX_CHN_NUM; ++i) { + gViCtx->enRotation[i] = ROTATION_0; + gViCtx->stLDCAttr[i].bEnable = CVI_FALSE; + } + + for (int i = 0; i < VI_MAX_CHN_NUM; ++i) + for (int j = 0; j < VI_MAX_EXTCHN_BIND_PER_CHN; ++j) + gViCtx->chn_bind[i][j] = VI_INVALID_CHN; + } + + devAttr = *pstDevAttr; + + s32Ret = vi_sdk_set_dev_attr(fd, ViDev, &devAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "setDevAttr ioctl failed\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetDevAttr(VI_DEV ViDev, VI_DEV_ATTR_S *pstDevAttr) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevAttr); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + s32Ret = vi_sdk_get_dev_attr(fd, ViDev, pstDevAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_dev_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_EnableDev(VI_DEV ViDev) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_DEVID_VALID(ViDev); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + fd = get_vi_fd(); + + if (gViCtx->devAttr[ViDev].stSize.u32Width == 0 && + gViCtx->devAttr[ViDev].stSize.u32Height == 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "Call SetDevAttr first\n"); + return CVI_ERR_VI_FAILED_NOTCONFIG; + } + + s32Ret = vi_sdk_enable_dev(fd, ViDev); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "enable_dev ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_DisableDev(VI_DEV ViDev) +{ + CVI_S32 ret = CVI_SUCCESS; + CVI_U8 i = 0; + CVI_U8 all_dev_disabled = true; + + CHECK_VI_DEVID_VALID(ViDev); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (gViCtx->isDevEnable[ViDev] == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_INFO, "vi dev(%d) is already disabled.", ViDev); + return CVI_SUCCESS; + } + + gViCtx->isDevEnable[ViDev] = false; + + for (i = 0; i < VI_MAX_DEV_NUM; i++) { + if (gViCtx->isDevEnable[i]) { + all_dev_disabled = false; + break; + } + } + + if (all_dev_disabled && gViCtx->vi_stt != VI_SUSPEND) { + ret = _vi_proc_unmap(); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "_vi_proc_unmap failed.\n"); + return CVI_ERR_VI_FAILED_NOT_DISABLED; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetDevTimingAttr(VI_DEV ViDev, const VI_DEV_TIMING_ATTR_S *pstTimingAttr) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + VI_DEV_TIMING_ATTR_S stTimingAttr; + + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstTimingAttr); + + fd = get_vi_fd(); + + stTimingAttr = *pstTimingAttr; + s32Ret = vi_sdk_set_dev_timing_attr(fd, ViDev, &stTimingAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_dev_timing_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetDevTimingAttr(VI_DEV ViDev, VI_DEV_TIMING_ATTR_S *pstTimingAttr) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstTimingAttr); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (gViCtx->isDevEnable[ViDev] == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_ERR, "EnableDev first\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + if (gViCtx->stTimingAttr[ViDev].bEnable == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_ERR, "SetDevTimingAttr first\n"); + return CVI_ERR_VI_FAILED_NOTCONFIG; + } + + *pstTimingAttr = gViCtx->stTimingAttr[ViDev]; + return CVI_SUCCESS; +} + +/* 2 for vi pipe */ +CVI_S32 CVI_VI_CreatePipe(VI_PIPE ViPipe, const VI_PIPE_ATTR_S *pstPipeAttr) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + VI_PIPE_ATTR_S stPipeAttr; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstPipeAttr); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + fd = get_vi_fd(); + + if (gViCtx->isPipeCreated[ViPipe] == CVI_TRUE) { + CVI_TRACE_VI(CVI_DBG_ERR, "Pipe(%d) has been created\n", ViPipe); + return CVI_ERR_VI_PIPE_EXIST; + } + + stPipeAttr = *pstPipeAttr; + + s32Ret = vi_sdk_create_pipe(fd, ViPipe, &stPipeAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_create_pipe ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_DestroyPipe(VI_PIPE ViPipe) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + CHECK_VI_PIPE_CREATED(ViPipe); + + gViCtx->isPipeCreated[ViPipe] = false; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_StartPipe(VI_PIPE ViPipe) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + CHECK_VI_PIPE_CREATED(ViPipe); + + fd = get_vi_fd(); + + s32Ret = vi_sdk_start_pipe(fd, ViPipe); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_start_pipe ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return s32Ret; +} + +CVI_S32 CVI_VI_StopPipe(VI_PIPE ViPipe) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + CHECK_VI_PIPE_CREATED(ViPipe); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetPipeAttr(VI_PIPE ViPipe, const VI_PIPE_ATTR_S *pstPipeAttr) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + VI_PIPE_ATTR_S pipeAttr; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstPipeAttr); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + pipeAttr = *pstPipeAttr; + + s32Ret = vi_sdk_set_pipe_attr(fd, ViPipe, &pipeAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_pipe_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetPipeAttr(VI_PIPE ViPipe, VI_PIPE_ATTR_S *pstPipeAttr) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstPipeAttr); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + s32Ret = vi_sdk_get_pipe_attr(fd, ViPipe, pstPipeAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_pipe_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetPipeDumpAttr(VI_PIPE ViPipe, const VI_DUMP_ATTR_S *pstDumpAttr) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + VI_DUMP_ATTR_S dumpAttr; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstDumpAttr); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + dumpAttr = *pstDumpAttr; + s32Ret = vi_sdk_set_pipe_dump_attr(fd, ViPipe, &dumpAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_pipe_dump_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetPipeDumpAttr(VI_PIPE ViPipe, VI_DUMP_ATTR_S *pstDumpAttr) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstDumpAttr); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + s32Ret = vi_sdk_get_pipe_dump_attr(fd, ViPipe, pstDumpAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_pipe_dump_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +// get bayer from preraw +CVI_S32 CVI_VI_GetPipeFrame(VI_PIPE ViPipe, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstFrameInfo); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + s32Ret = vi_sdk_get_pipe_frame(fd, ViPipe, pstFrameInfo, s32MilliSec); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_pipe_frame ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_ReleasePipeFrame(VI_PIPE ViPipe, const VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + VIDEO_FRAME_INFO_S stVideoFrame; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstFrameInfo); + + fd = get_vi_fd(); + if (fd < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "get_vi_fd open failed\n"); + return CVI_ERR_VI_BUSY; + } + + stVideoFrame = *pstFrameInfo; + s32Ret = vi_sdk_release_pipe_frame(fd, ViPipe, &stVideoFrame); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_release_pipe_frame ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_StartSmoothRawDump(const VI_SMOOTH_RAW_DUMP_INFO_S *pstDumpInfo) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_NULL_PTR(pstDumpInfo); + CHECK_VI_NULL_PTR(pstDumpInfo->phy_addr_list); + CHECK_VI_PIPEID_VALID(pstDumpInfo->ViPipe); + CHECK_VI_PIPE_CREATED(pstDumpInfo->ViPipe); + + VI_PIPE ViPipe = pstDumpInfo->ViPipe; + CVI_U8 frm_num = 0; + CVI_U64 phy_addr = 0; + struct cvi_vip_isp_smooth_raw_param param; + struct cvi_vip_isp_raw_blk *raw_blk = CVI_NULL; + + fd = get_vi_fd(); + + if (pstDumpInfo->u8BlkCnt < 2) { + CVI_TRACE_VI(CVI_DBG_ERR, "Need two ring buffer at least, now is %d\n", pstDumpInfo->u8BlkCnt); + return CVI_ERR_VI_INVALID_PARA; + } + + if ((gViCtx->devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) || + (gViCtx->devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_FRAME) || + (gViCtx->devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_FRAME_FULL_RATE)) { + frm_num = 2; + } else { + frm_num = 1; + } + + frm_num = (pstDumpInfo->u8BlkCnt) * frm_num; + + raw_blk = calloc(frm_num, sizeof(struct cvi_vip_isp_raw_blk)); + if (raw_blk == CVI_NULL) { + CVI_TRACE_VI(CVI_DBG_ERR, "malloc raw_blk failed\n"); + return CVI_ERR_VI_NOMEM; + } + + for (CVI_U8 i = 0; i < frm_num; i++) { + phy_addr = *(pstDumpInfo->phy_addr_list + i); + if (phy_addr == 0) { + if (raw_blk != CVI_NULL) { + free(raw_blk); + raw_blk = CVI_NULL; + } + CVI_TRACE_VI(CVI_DBG_ERR, "phy_addr is invalid\n"); + return CVI_ERR_VI_INVALID_PARA; + } + + (raw_blk + i)->raw_dump.phy_addr = phy_addr; + // CVI_TRACE_VI(CVI_DBG_DEBUG, "i=%d, phy_paddr(%#"PRIx64")\n", i, (raw_blk+i)->raw_dump.phy_addr); + + // set rawdump crop info + (raw_blk + i)->crop_x = pstDumpInfo->stCropRect.s32X; + (raw_blk + i)->crop_y = pstDumpInfo->stCropRect.s32Y; + (raw_blk + i)->src_w = pstDumpInfo->stCropRect.u32Width; + (raw_blk + i)->src_h = pstDumpInfo->stCropRect.u32Height; + //CVI_TRACE_VI(CVI_DBG_DEBUG, "i (%d), crop_x(%d), crop_y(%d), src_w(%d), src_h(%d)\n", + // i, (raw_blk + i)->crop_x, (raw_blk + i)->crop_y, + // (raw_blk + i)->src_w, (raw_blk + i)->src_h); + } + + param.raw_num = ViPipe; + param.frm_num = frm_num; + param.raw_blk = raw_blk; + + s32Ret = vi_sdk_start_smooth_rawdump(fd, ViPipe, ¶m); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_start_smooth_rawdump ioctl failed\n"); + free(raw_blk); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + if (raw_blk != CVI_NULL) { + free(raw_blk); + raw_blk = CVI_NULL; + } + + return s32Ret; +} + +CVI_S32 CVI_VI_StopSmoothRawDump(const VI_SMOOTH_RAW_DUMP_INFO_S *pstDumpInfo) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_NULL_PTR(pstDumpInfo); + CHECK_VI_PIPEID_VALID(pstDumpInfo->ViPipe); + CHECK_VI_PIPE_CREATED(pstDumpInfo->ViPipe); + + VI_PIPE ViPipe = pstDumpInfo->ViPipe; + struct cvi_vip_isp_smooth_raw_param param; + + fd = get_vi_fd(); + + param.raw_num = ViPipe; + + s32Ret = vi_sdk_stop_smooth_rawdump(fd, ViPipe, ¶m); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_stop_smooth_rawdump ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetSmoothRawDump(VI_PIPE ViPipe, VIDEO_FRAME_INFO_S *pstVideoFrame, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_NULL_PTR(pstVideoFrame); + + fd = get_vi_fd(); + + s32Ret = vi_sdk_get_smooth_rawdump(fd, ViPipe, pstVideoFrame, s32MilliSec); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_smooth_rawdump ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_PutSmoothRawDump(VI_PIPE ViPipe, const VIDEO_FRAME_INFO_S *pstVideoFrame) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + VIDEO_FRAME_INFO_S stVideoFrame[2]; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstVideoFrame); + + fd = get_vi_fd(); + + stVideoFrame[0] = pstVideoFrame[0]; + stVideoFrame[1] = pstVideoFrame[1]; + s32Ret = vi_sdk_put_smooth_rawdump(fd, ViPipe, stVideoFrame); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_put_smooth_rawdump ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_QueryPipeStatus(VI_PIPE ViPipe, VI_PIPE_STATUS_S *pstStatus) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstStatus); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + CHECK_VI_PIPE_CREATED(ViPipe); + + pstStatus->bEnable = gViCtx->is_enable[0]; + pstStatus->stSize.u32Height = gViCtx->pipeAttr[ViPipe].u32MaxH; + pstStatus->stSize.u32Width = gViCtx->pipeAttr[ViPipe].u32MaxW; + pstStatus->u32FrameRate = gViCtx->pipeAttr[ViPipe].stFrameRate.s32SrcFrameRate; + pstStatus->u32IntCnt = 0;//todo + pstStatus->u32LostFrame = 0;//todo + pstStatus->u32VbFail = 0;//todo + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetPipeFrameSource(VI_PIPE ViPipe, const VI_PIPE_FRAME_SOURCE_E enSource) +{ + CVI_S32 fd = -1; + CVI_U32 s32Ret = CVI_SUCCESS; + VI_PIPE_FRAME_SOURCE_E src = enSource; + + CHECK_VI_PIPEID_VALID(ViPipe); + + if (enSource < 0 || enSource >= VI_PIPE_FRAME_SOURCE_BUTT) { + CVI_TRACE_VI(CVI_DBG_ERR, "enSource(%d)is invalid\n", enSource); + return CVI_ERR_VI_INVALID_PARA; + } + + fd = get_vi_fd(); + + s32Ret = vi_sdk_set_pipe_frm_src(fd, ViPipe, &src); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_pipe_frm_src ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetPipeFrameSource(VI_PIPE ViPipe, VI_PIPE_FRAME_SOURCE_E *penSource) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(penSource); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *penSource = gViCtx->enSource[ViPipe]; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SendPipeRaw(CVI_U32 u32PipeNum, VI_PIPE PipeId[], const VIDEO_FRAME_INFO_S *pstVideoFrame[], + CVI_S32 s32MilliSec) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_NULL_PTR(PipeId); + CHECK_VI_NULL_PTR(pstVideoFrame); + + UNUSED(s32MilliSec); + + fd = get_vi_fd(); + + for (CVI_U32 i = 0; i < u32PipeNum; ++i) { + VI_PIPE pipeid = PipeId[i]; + VIDEO_FRAME_INFO_S stVideoFrm = *pstVideoFrame[i]; + + s32Ret = vi_sdk_send_pipe_raw(fd, pipeid, &stVideoFrm); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_send_pipe_raw ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetPipeFd(VI_PIPE ViPipe) +{ + CVI_S32 fd = -1; + + CHECK_VI_PIPEID_VALID(ViPipe); + + fd = get_vi_fd(); + + if (fd <= 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "Get pipe fd fail\n"); + return CVI_FAILURE; + } + + return fd; +} + +CVI_S32 CVI_VI_CloseFd(void) +{ + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetPipeCrop(VI_PIPE ViPipe, const CROP_INFO_S *pstCropInfo) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + VI_CROP_INFO_S cropInfo; + + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstCropInfo); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + fd = get_vi_fd(); + + if (pstCropInfo->stRect.s32X % 2 || pstCropInfo->stRect.s32Y % 2 || + pstCropInfo->stRect.u32Width % 2 || pstCropInfo->stRect.u32Height % 2) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)_y(%d)_w(%d)_h(%d) must be multiple of 2.\n", + pstCropInfo->stRect.s32X, + pstCropInfo->stRect.s32Y, + pstCropInfo->stRect.u32Width, + pstCropInfo->stRect.u32Height); + return CVI_ERR_VI_INVALID_PARA; + } + + if (pstCropInfo->stRect.s32X < 0 || pstCropInfo->stRect.s32Y < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)_y(%d) is invalid.\n", + pstCropInfo->stRect.s32X, + pstCropInfo->stRect.s32Y); + return CVI_ERR_VI_INVALID_PARA; + } + + if ((pstCropInfo->stRect.s32X + pstCropInfo->stRect.u32Width) > + gViCtx->pipeAttr[ViPipe].u32MaxW || + (pstCropInfo->stRect.s32Y + pstCropInfo->stRect.u32Height) > + gViCtx->pipeAttr[ViPipe].u32MaxH) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)+w(%d) or y(%d)+h(%d) is bigger than chn_w(%d)_h(%d)\n", + pstCropInfo->stRect.s32X, + pstCropInfo->stRect.u32Width, + pstCropInfo->stRect.s32Y, + pstCropInfo->stRect.u32Height, + gViCtx->pipeAttr[ViPipe].u32MaxW, + gViCtx->pipeAttr[ViPipe].u32MaxH); + return CVI_ERR_VI_INVALID_PARA; + } + + gViCtx->pipeCrop[ViPipe] = *pstCropInfo; + if (gViCtx->pipeCrop[ViPipe].bEnable == CVI_TRUE) { + cropInfo.bEnable = pstCropInfo->bEnable; + cropInfo.stCropRect = pstCropInfo->stRect; + s32Ret = vi_sdk_set_chn_crop(fd, ViPipe, 0, &cropInfo); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_chn_crop ioctl failed\n"); + return CVI_FAILURE; + } + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetPipeCrop(VI_PIPE ViPipe, CROP_INFO_S *pstCropInfo) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstCropInfo); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstCropInfo = gViCtx->pipeCrop[ViPipe]; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_AttachVbPool(VI_PIPE ViPipe, VI_CHN ViChn, VB_POOL VbPool) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + + CVI_S32 fd = get_vi_fd(); + struct vi_vb_pool_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.ViPipe = ViPipe; + cfg.ViChn = ViChn; + cfg.VbPool = VbPool; + return vi_sdk_attach_vbpool(fd, &cfg); +} + +CVI_S32 CVI_VI_DetachVbPool(VI_PIPE ViPipe, VI_CHN ViChn) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + + CVI_S32 fd = get_vi_fd(); + struct vi_vb_pool_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.ViPipe = ViPipe; + cfg.ViChn = ViChn; + return vi_sdk_detach_vbpool(fd, &cfg); +} + +CVI_S32 CVI_VI_SetChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, VI_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstChnAttr); + + fd = get_vi_fd(); + + if (pstChnAttr->stFrameRate.s32SrcFrameRate != pstChnAttr->stFrameRate.s32DstFrameRate) + CVI_TRACE_VI(CVI_DBG_WARN, "FrameRate ctrl, src(%d) dst(%d), not support yet.\n" + , pstChnAttr->stFrameRate.s32SrcFrameRate, pstChnAttr->stFrameRate.s32DstFrameRate); + + s32Ret = vi_sdk_set_chn_attr(fd, ViPipe, ViChn, pstChnAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_chn_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, VI_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstChnAttr); + + fd = get_vi_fd(); + + s32Ret = vi_sdk_get_chn_attr(fd, ViPipe, ViChn, pstChnAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_chn_attr ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_EnableChn(VI_PIPE ViPipe, VI_CHN ViChn) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (ViChn >= (VI_MAX_CHN_NUM + VI_MAX_EXT_CHN_NUM)) { + CVI_TRACE_VI(CVI_DBG_ERR, " invalid chn-id(%d)\n", ViChn); + return CVI_ERR_VI_INVALID_CHNID; + } + + fd = get_vi_fd(); + + if (gViCtx->is_enable[ViChn] == CVI_TRUE) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi chn(%d) is already enabled.\n", ViChn); + return CVI_ERR_VI_FAILED_NOT_DISABLED; + } + + if (ViChn >= VI_EXT_CHN_START) { + VI_EXT_CHN_ATTR_S *pstExtChnAttr = &gViCtx->stExtChnAttr[ViChn - VI_EXT_CHN_START]; + + gViCtx->is_enable[ViChn] = CVI_TRUE; + gViCtx->chn_bind[pstExtChnAttr->s32BindChn][0] = ViChn; + } else { + if (ViChn < VI_MAX_CHN_NUM) + _vi_chn_enable_mirror_flip(ViChn); + + if (gViCtx->total_dev_num != ViChn + 1) + return CVI_SUCCESS; + + s32Ret = _cvi_vi_getIonBuf(); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI getIonBuf is failed\n"); + return CVI_ERR_SYS_NOMEM; + } + + s32Ret = vi_sdk_enable_chn(fd, ViPipe, ViChn); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_enable_chn ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + { + struct sched_param param; + pthread_attr_t attr; + + param.sched_priority = 85; + + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + + pthread_create(&gViDbgTH.vi_dbg_thread, &attr, (void *)vi_dbg_handler, NULL); + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_DisableChn(VI_PIPE ViPipe, VI_CHN ViChn) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_U8 i = 0; + + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (ViChn >= (VI_MAX_CHN_NUM + VI_MAX_EXT_CHN_NUM)) { + CVI_TRACE_VI(CVI_DBG_ERR, " invalid chn-id(%d)\n", ViChn); + return CVI_ERR_VI_INVALID_CHNID; + } + + fd = get_vi_fd(); + + if (gViCtx->is_enable[ViChn] == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_INFO, "vi chn(%d) is already disabled.", ViChn); + return CVI_SUCCESS; + } + + if (ViChn < VI_MAX_PHY_CHN_NUM) { + CVI_U8 all_chn_disabled = true; + + gViCtx->is_enable[ViChn] = CVI_FALSE; + + for (i = 0; i < gViCtx->total_chn_num; i++) { + if (gViCtx->is_enable[i]) { + all_chn_disabled = false; + break; + } + } + + if (all_chn_disabled) { + gViDbgTH.th_enable = CVI_FALSE; + + s32Ret = vi_sdk_disable_chn(fd, ViPipe, ViChn); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_disable_chn ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + pthread_join(gViDbgTH.vi_dbg_thread, NULL); + + s32Ret = _cvi_vi_freeIonBuf(); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI freeIonBuf is failed\n"); + return CVI_ERR_SYS_ILLEGAL_PARAM; + } + } + } else if (ViChn >= VI_EXT_CHN_START) { + VI_EXT_CHN_ATTR_S *pstExtChnAttr = &gViCtx->stExtChnAttr[ViChn - VI_EXT_CHN_START]; + + gViCtx->is_enable[ViChn] = CVI_FALSE; + gViCtx->chn_bind[pstExtChnAttr->s32BindChn][0] = VI_INVALID_CHN; + //vi_ctx.stFishEyeAttr[ViChn - VI_EXT_CHN_START].bEnable = CVI_FALSE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetChnCrop(VI_PIPE ViPipe, VI_CHN ViChn, const VI_CROP_INFO_S *pstCropInfo) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + VI_CROP_INFO_S cropInfo; + + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstCropInfo); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + fd = get_vi_fd(); + + if (pstCropInfo->stCropRect.s32X % 2 || pstCropInfo->stCropRect.s32Y % 2 || + pstCropInfo->stCropRect.u32Width % 2 || pstCropInfo->stCropRect.u32Height % 2) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)_y(%d)_w(%d)_h(%d) must be multiple of 2.\n", + pstCropInfo->stCropRect.s32X, + pstCropInfo->stCropRect.s32Y, + pstCropInfo->stCropRect.u32Width, + pstCropInfo->stCropRect.u32Height); + return CVI_ERR_VI_INVALID_PARA; + } + + if (pstCropInfo->stCropRect.s32X < 0 || pstCropInfo->stCropRect.s32Y < 0) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)_y(%d) is invalid.\n", + pstCropInfo->stCropRect.s32X, + pstCropInfo->stCropRect.s32Y); + return CVI_ERR_VI_INVALID_PARA; + } + + if ((pstCropInfo->stCropRect.s32X + pstCropInfo->stCropRect.u32Width) > + gViCtx->chnAttr[ViChn].stSize.u32Width || + (pstCropInfo->stCropRect.s32Y + pstCropInfo->stCropRect.u32Height) > + gViCtx->chnAttr[ViChn].stSize.u32Height) { + CVI_TRACE_VI(CVI_DBG_ERR, "crop_x(%d)+w(%d) or y(%d)+h(%d) is bigger than chn_w(%d)_h(%d)\n", + pstCropInfo->stCropRect.s32X, + pstCropInfo->stCropRect.u32Width, + pstCropInfo->stCropRect.s32Y, + pstCropInfo->stCropRect.u32Height, + gViCtx->chnAttr[ViChn].stSize.u32Width, + gViCtx->chnAttr[ViChn].stSize.u32Height); + return CVI_ERR_VI_INVALID_PARA; + } + + gViCtx->chnCrop[ViChn] = *pstCropInfo; + + if (gViCtx->chnCrop[ViChn].bEnable == CVI_TRUE) { + cropInfo = *pstCropInfo; + s32Ret = vi_sdk_set_chn_crop(fd, ViPipe, ViChn, &cropInfo); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_set_chn_crop ioctl failed\n"); + return CVI_FAILURE; + } + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetChnCrop(VI_PIPE ViPipe, VI_CHN ViChn, VI_CROP_INFO_S *pstCropInfo) +{ + CVI_U32 s32Ret = CVI_SUCCESS; + CVI_S32 fd = -1; + + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstCropInfo); + + fd = get_vi_fd(); + + s32Ret = vi_sdk_get_chn_crop(fd, ViPipe, ViChn, pstCropInfo); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_chn_crop ioctl failed\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_GetChnFrame(VI_PIPE ViPipe, VI_CHN ViChn, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + + if (ViChn >= (VI_MAX_CHN_NUM + VI_MAX_EXT_CHN_NUM)) { + CVI_TRACE_VI(CVI_DBG_ERR, " invalid chn-id(%d)\n", ViChn); + return CVI_ERR_VI_INVALID_CHNID; + } + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(pstFrameInfo); + + fd = get_vi_fd(); + + s32Ret = vi_sdk_get_chn_frame(fd, ViPipe, ViChn, pstFrameInfo, s32MilliSec); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_chn_frame ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_ReleaseChnFrame(VI_PIPE ViPipe, VI_CHN ViChn, const VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + CVI_S32 fd = -1; + CVI_S32 s32Ret = CVI_SUCCESS; + VIDEO_FRAME_INFO_S stFrameInfo; + + CHECK_VI_NULL_PTR(pstFrameInfo); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + + fd = get_vi_fd(); + + stFrameInfo = *pstFrameInfo; + s32Ret = vi_sdk_release_chn_frame(fd, ViPipe, ViChn, &stFrameInfo); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_release_chn_frame ioctl failed\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_QueryChnStatus(VI_PIPE ViPipe, VI_CHN ViChn, VI_CHN_STATUS_S *pstChnStatus) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_NULL_PTR(pstChnStatus); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstChnStatus = gViCtx->chnStatus[ViChn]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetChnRotation(VI_PIPE ViPipe, VI_CHN ViChn, const ROTATION_E enRotation) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_GDC_FMT(gViCtx->chnAttr[ViChn].enPixelFormat); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + struct cvi_gdc_mesh *pmesh = &g_vi_mesh[ViChn]; + + if (enRotation == ROTATION_180) { + CVI_TRACE_VI(CVI_DBG_ERR, "not support rotation(%d).\n", enRotation); + return CVI_ERR_VI_NOT_SUPPORT; + } else if (enRotation >= ROTATION_MAX) { + CVI_TRACE_VI(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation); + return CVI_ERR_VI_INVALID_PARA; + } else if (enRotation == gViCtx->enRotation[ViChn]) { + CVI_TRACE_VI(CVI_DBG_INFO, "rotation(%d) not changed.\n", enRotation); + return CVI_SUCCESS; + } else if (!gViCtx->stLDCAttr[ViChn].bEnable && enRotation == ROTATION_0) { + pthread_mutex_lock(&pmesh->lock); + gViCtx->enRotation[ViChn] = enRotation; + pthread_mutex_unlock(&pmesh->lock); + return CVI_SUCCESS; + } + + if (gViCtx->stLDCAttr[ViChn].bEnable) + return _vi_update_ldc_mesh(ViPipe, ViChn, &gViCtx->stLDCAttr[ViChn], enRotation); + else + return _vi_update_rotation_mesh(ViChn, enRotation); +} + +CVI_S32 CVI_VI_GetChnRotation(VI_PIPE ViPipe, VI_CHN ViChn, ROTATION_E *penRotation) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *penRotation = gViCtx->enRotation[ViChn]; + return CVI_SUCCESS; +} + +static CVI_S32 _vpss_is_online(void) +{ + return 0; +} + +CVI_S32 CVI_VI_SetChnLDCAttr(VI_PIPE ViPipe, VI_CHN ViChn, const VI_LDC_ATTR_S *pstLDCAttr) +{ + CHECK_VI_NULL_PTR(pstLDCAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + + CHECK_VI_GDC_FMT(gViCtx->chnAttr[ViChn].enPixelFormat); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + return _vi_update_ldc_mesh(ViPipe, ViChn, pstLDCAttr, gViCtx->enRotation[ViChn]); +} + +CVI_S32 CVI_VI_GetChnLDCAttr(VI_PIPE ViPipe, VI_CHN ViChn, VI_LDC_ATTR_S *pstLDCAttr) +{ + CHECK_VI_NULL_PTR(pstLDCAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstLDCAttr = gViCtx->stLDCAttr[ViChn]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_RegChnFlipMirrorCallBack(VI_PIPE ViPipe, VI_DEV ViDev, void *pvData) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pvData); + + s_pfnDevMirrorFlip[ViDev] = (pfnChnMirrorFlip)pvData; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_UnRegChnFlipMirrorCallBack(VI_PIPE ViPipe, VI_DEV ViDev) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_DEVID_VALID(ViDev); + + s_pfnDevMirrorFlip[ViDev] = CVI_NULL; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_SetChnFlipMirror(VI_PIPE ViPipe, VI_CHN ViChn, CVI_BOOL bFlip, CVI_BOOL bMirror) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (!gViCtx->is_enable[ViChn]) { + CVI_TRACE_VI(CVI_DBG_ERR, "ViChn(%d) is not enable.\n", ViChn); + return CVI_FAILURE; + } + + gViCtx->chnAttr[ViChn].bFlip = bFlip; + gViCtx->chnAttr[ViChn].bMirror = bMirror; + + return _vi_chn_enable_mirror_flip(ViChn); +} + +CVI_S32 CVI_VI_GetChnFlipMirror(VI_PIPE ViPipe, VI_CHN ViChn, CVI_BOOL *pbFlip, CVI_BOOL *pbMirror) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_CHNID_VALID(ViChn); + CHECK_VI_NULL_PTR(pbFlip); + CHECK_VI_NULL_PTR(pbMirror); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (!gViCtx->is_enable[ViChn]) { + CVI_TRACE_VI(CVI_DBG_ERR, "ViChn(%d) is not enable.\n", ViChn); + return CVI_FAILURE; + } + + *pbFlip = gViCtx->chnAttr[ViChn].bFlip; + *pbMirror = gViCtx->chnAttr[ViChn].bMirror; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_DumpHwRegisterToFile(VI_PIPE ViPipe, FILE *fp, VI_DUMP_REGISTER_TABLE_S *pstRegTbl) +{ + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_NULL_PTR(fp); + CHECK_VI_NULL_PTR(pstRegTbl); + + CVI_S32 s32Ret = CVI_SUCCESS; + CVI_U32 chip; + + CVI_SYS_GetChipId(&chip); + +#if defined(ARCH_CV182X) || defined(ARCH_CV183X) + if (IS_CHIP_CV182X(chip)) { + s32Ret = dump_register_182x(ViPipe, fp, pstRegTbl); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "dump_register_182x fail\n"); + return s32Ret; + } + } else if (IS_CHIP_CV183X(chip)) { + s32Ret = dump_register_183x(ViPipe, fp, pstRegTbl); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "dump_register_183x fail\n"); + return s32Ret; + } + } +#elif defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) + if (IS_CHIP_CV181X(chip) || IS_CHIP_CV180X(chip)) { + s32Ret = dump_hw_register(ViPipe, fp, pstRegTbl); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "dump_hw_register fail\n"); + return s32Ret; + } + } else { + CVI_TRACE_VI(CVI_DBG_ERR, "CHIP ID error [%d]\n", chip); + } +#endif + return CVI_SUCCESS; +} + +void _cfg_ctrl_test(struct vdev *d) +{ + CVI_U32 op; + CVI_U32 enable_pic = 0; + + printf("\n\n/*********CFG START***********/\n"); + printf("pre_be online(0/1)\n"); + scanf("%d", &op); + vi_set_be_online(d->fd, op); + + printf("postraw online(0/1)\n"); + scanf("%d", &op); + vi_set_online(d->fd, op); +#if 0 + printf("is_hdr_on(0/1)\n"); + scanf("%d", &op); + isp_set_hdr(d->fd, op); +#endif + printf("is_3dnr_on(0/1)\n"); + scanf("%d", &op); + vi_set_3dnr(d->fd, op); +// #ifdef ARCH_CV182X +// printf("is_rgbir_on(0/1)\n"); +// scanf("%d", &op); +// isp_set_rgbir(d->fd, op); +// #endif + printf("is_preraw_from_dram(0/1)\n"); + scanf("%d", &enable_pic); + if (enable_pic == 1) { + struct cvi_isp_usr_pic_cfg cfg; + + vi_enable_usr_pic(d->fd, CVI_ISP_SOURCE_FE); + vi_set_usr_pic_timing(d->fd, 3); + + cfg.fmt.width = 1920; + cfg.fmt.height = 1080; + cfg.fmt.code = BAYER_FORMAT_GR; + cfg.crop.left = 0; + cfg.crop.top = 0; + cfg.crop.width = 1920; + cfg.crop.height = 1080; + vi_set_usr_pic(d->fd, &cfg); + vi_put_usr_pic(d->fd, 0); + printf("Upload raw picture\n"); + scanf("%d", &op); +#if defined(__SOC_MARS__) + system("echo 0,0 > /sys/module/mars_vi/parameters/csi_patgen_en"); +#elif defined(__SOC_PHOBOS__) + system("echo 0,0 > /sys/module/phobos_vi/parameters/csi_patgen_en"); +#endif + } else { + vi_enable_usr_pic(d->fd, CVI_ISP_SOURCE_DEV); + printf("is_pattern_gen(0/1)\n"); + scanf("%d", &op); + +#if defined(__SOC_MARS__) + if (op == 1) + system("echo 1,0 > /sys/module/mars_vi/parameters/csi_patgen_en"); + else + system("echo 0,0 > /sys/module/mars_vi/parameters/csi_patgen_en"); +#elif defined(__SOC_PHOBOS__) + if (op == 1) + system("echo 1,0 > /sys/module/phobos_vi/parameters/csi_patgen_en"); + else + system("echo 0,0 > /sys/module/phobos_vi/parameters/csi_patgen_en"); +#endif + } + + printf("/*********CFG END*************/\n\n"); +} + +CVI_S32 _CVI_VI_CFG_CTRL_TEST(void) +{ + struct vdev *d; + + d = get_dev_info(VDEV_TYPE_ISP, 0); +#if 1 + _cfg_ctrl_test(d); +#else + isp_set_be_online(d->fd, 0); + isp_set_online(d->fd, 1); + isp_set_hdr(d->fd, 0); + isp_set_3dnr(d->fd, 0); + { + struct cvi_isp_usr_pic_cfg cfg; + + isp_enable_usr_pic(d->fd, CVI_ISP_SOURCE_FE); + isp_set_usr_pic_timing(d->fd, 3); + + cfg.fmt.width = 1920; + cfg.fmt.height = 1080; + cfg.fmt.code = BAYER_FORMAT_BG; + cfg.crop.left = 0; + cfg.crop.top = 0; + cfg.crop.width = 1920; + cfg.crop.height = 1080; + isp_set_usr_pic(d->fd, &cfg); + isp_put_usr_pic(d->fd, 0); + } + system("echo 1,0 > /sys/module/cv182x_vip/parameters/csi_patgen_en"); +#endif + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_RegPmCallBack(VI_DEV ViDev, VI_PM_OPS_S *pstPmOps, void *pvData) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstPmOps); + CHECK_VI_NULL_PTR(pvData); + + memcpy(&apstViPm[ViDev].stOps, pstPmOps, sizeof(VI_PM_OPS_S)); + apstViPm[ViDev].pvData = pvData; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VI_UnRegPmCallBack(VI_DEV ViDev) +{ + CHECK_VI_DEVID_VALID(ViDev); + + memset(&apstViPm[ViDev].stOps, 0, sizeof(VI_PM_OPS_S)); + apstViPm[ViDev].pvData = NULL; + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_Trig_AHD(VI_PIPE ViPipe, CVI_U8 u8AHDSignal) +{ + CVI_S32 fd = -1; + VI_CHN ViChn = ViPipe; + + CHECK_VI_PIPEID_VALID(ViPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + fd = get_vi_fd(); + + if (gViCtx->pipeAttr[ViPipe].bYuvBypassPath == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_ERR, "VI Pipe(%d) is not yuv bypass mode.", ViPipe); + return CVI_ERR_VI_NOT_SUPPORT; + } + + gViCtx->chnStatus[ViChn].bEnable = (u8AHDSignal == 0) ? CVI_FALSE : CVI_TRUE; + if (gViCtx->chnStatus[ViChn].bEnable == CVI_TRUE) { + vi_set_trig_preraw(fd, ViPipe); + } + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_SetExtChnFisheye(VI_PIPE ViPipe, VI_CHN ViChn, const FISHEYE_ATTR_S *pstFishEyeAttr) +{ + CHECK_VI_NULL_PTR(pstFishEyeAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_EXTCHNID_VALID(ViChn); + + //ToDo fisheye + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_GetExtChnFisheye(VI_PIPE ViPipe, VI_CHN ViChn, FISHEYE_ATTR_S *pstFishEyeAttr) +{ + CHECK_VI_NULL_PTR(pstFishEyeAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_EXTCHNID_VALID(ViChn); + + //ToDo fisheye + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_SetExtChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, const VI_EXT_CHN_ATTR_S *pstExtChnAttr) +{ + CHECK_VI_NULL_PTR(pstExtChnAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_EXTCHNID_VALID(ViChn); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (pstExtChnAttr->s32BindChn >= VI_MAX_CHN_NUM) { + CVI_TRACE_VI(CVI_DBG_ERR, " invalid bind chn-id(%d)\n", pstExtChnAttr->s32BindChn); + return CVI_ERR_VI_INVALID_PARA; + } + + VI_CHN_ATTR_S *pstChnAttr = &gViCtx->chnAttr[pstExtChnAttr->s32BindChn]; + + if (_vpss_is_online()) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "ViPipe(%d) Chn(%d) not supported if online.\n" + , ViPipe, ViChn); + return CVI_ERR_VI_INVALID_PARA; + } + + if (!gViCtx->is_enable[pstExtChnAttr->s32BindChn]) { + CVI_TRACE_VI(CVI_DBG_ERR, "bindchn(%d) not enabled yet.\n", pstExtChnAttr->s32BindChn); + return CVI_ERR_VI_INVALID_PARA; + } + + //ToDo ldc/fisheye + + if (pstChnAttr->enPixelFormat != pstExtChnAttr->enPixelFormat) { + CVI_TRACE_VI(CVI_DBG_ERR, "PixelFormat mismatch extchn(%d) - bindchn(%d)\n" + , pstExtChnAttr->enPixelFormat, pstChnAttr->enPixelFormat); + return CVI_ERR_VI_INVALID_PARA; + } + gViCtx->stExtChnAttr[ViChn - VI_EXT_CHN_START] = *pstExtChnAttr; + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_GetExtChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, VI_EXT_CHN_ATTR_S *pstExtChnAttr) +{ + CHECK_VI_NULL_PTR(pstExtChnAttr); + CHECK_VI_PIPEID_VALID(ViPipe); + CHECK_VI_EXTCHNID_VALID(ViChn); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstExtChnAttr = gViCtx->stExtChnAttr[ViChn - VI_EXT_CHN_START]; + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_SetMipiBindDev(VI_DEV ViDev, MIPI_DEV MipiDev) +{ + CHECK_VI_DEVID_VALID(ViDev); + + UNUSED(MipiDev); + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_GetMipiBindDev(VI_DEV ViDev, MIPI_DEV *pMipiDev) +{ + CHECK_VI_DEVID_VALID(ViDev); + if (pMipiDev == NULL) { + CVI_TRACE_VI(CVI_DBG_ERR, " invalid arg\n"); + return CVI_ERR_VI_INVALID_NULL_PTR; + } + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_SetDevBindPipe(VI_DEV ViDev, const VI_DEV_BIND_PIPE_S *pstDevBindPipe) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevBindPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + if (gViCtx->isDevEnable[ViDev] == CVI_FALSE) { + CVI_TRACE_VI(CVI_DBG_ERR, "Call EnableDev first\n"); + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + + if (pstDevBindPipe->u32Num > 2) { + CVI_TRACE_VI(CVI_DBG_ERR, "bindPipe number can't over 2\n"); + return CVI_ERR_VI_FAILED_BINDED; + } + + gViCtx->devBindPipeAttr[ViDev] = *pstDevBindPipe; + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_GetDevBindPipe(VI_DEV ViDev, VI_DEV_BIND_PIPE_S *pstDevBindPipe) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevBindPipe); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstDevBindPipe = gViCtx->devBindPipeAttr[ViDev]; + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_SetDevAttrEx(VI_DEV ViDev, const VI_DEV_ATTR_EX_S *pstDevAttrEx) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevAttrEx); + + memset(&gViCtx->devAttrEx[ViDev], 0, sizeof(gViCtx->devAttrEx[ViDev])); + gViCtx->devAttrEx[ViDev] = *pstDevAttrEx; + + return CVI_SUCCESS; +} + +/** + * @deprecated + */ +CVI_S32 CVI_VI_GetDevAttrEx(VI_DEV ViDev, VI_DEV_ATTR_EX_S *pstDevAttrEx) +{ + CHECK_VI_DEVID_VALID(ViDev); + CHECK_VI_NULL_PTR(pstDevAttrEx); + if (CHECK_VI_CTX_NULL_PTR(gViCtx) != CVI_SUCCESS) + return CVI_ERR_VI_FAILED_NOTCONFIG; + + *pstDevAttrEx = gViCtx->devAttrEx[ViDev]; + + return CVI_SUCCESS; +} diff --git a/middleware/v2/modules/vpu/src/cvi_vo.c b/middleware/v2/modules/vpu/src/cvi_vo.c new file mode 100644 index 000000000..471e90d2a --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_vo.c @@ -0,0 +1,1186 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_sys.h" +#include +#include "cvi_buffer.h" + +#include "cvi_base.h" +#include "cvi_vo.h" +#include "cvi_gdc.h" +#include "cvi_vb.h" +#include "gdc_mesh.h" +#include "vo_ioctl.h" +#include +#include + +#define CHECK_VO_DEV_VALID(VoDev) do { \ + if ((VoDev >= VO_MAX_DEV_NUM) || (VoDev < 0)) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) invalid.\n", VoDev); \ + return CVI_ERR_VO_INVALID_DEVID; \ + } \ + } while (0) + +#define CHECK_VO_LAYER_VALID(VoLayer) do { \ + if ((VoLayer >= VO_MAX_LAYER_NUM) || (VoLayer < 0)) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) invalid.\n", VoLayer); \ + return CVI_ERR_VO_INVALID_LAYERID; \ + } \ + } while (0) + +#define CHECK_VO_CHN_VALID(VoLayer, VoChn) do { \ + if ((VoLayer >= VO_MAX_LAYER_NUM) || (VoLayer < 0)) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) invalid.\n", VoLayer); \ + return CVI_ERR_VO_INVALID_LAYERID; \ + } \ + if ((VoChn >= VO_MAX_CHN_NUM) || (VoChn < 0)) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoChn(%d) invalid.\n", VoChn); \ + return CVI_ERR_VO_INVALID_CHNID; \ + } \ + } while (0) + +#define CHECK_VO_LAYER_ENABLE(VoLayer) do { \ + if (!gVoCtx->is_layer_enable[VoLayer]) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) isn't enabled yet.\n", VoLayer); \ + return CVI_ERR_VO_VIDEO_NOT_ENABLED; \ + } \ + } while (0) + +#define CHECK_VO_LAYER_DISABLE(VoLayer) do { \ + if (gVoCtx->is_layer_enable[VoLayer]) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) already enabled.\n", VoLayer); \ + return CVI_ERR_VO_VIDEO_NOT_DISABLED; \ + } \ + } while (0) + +#define CHECK_VO_CHN_ENABLE(VoLayer, VoChn) do { \ + if (!gVoCtx->is_chn_enable[VoLayer][VoChn]) { \ + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) VoChn(%d) isn't enabled yet.\n", VoLayer, VoChn);\ + return CVI_ERR_VO_CHN_NOT_ENABLED; \ + } \ + } while (0) + +VO_SYNC_INFO_S stSyncInfo[VO_OUTPUT_BUTT] = { + [VO_OUTPUT_800x600_60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 600, .u16Vbb = 24, .u16Vfb = 1 + , .u16Hact = 800, .u16Hbb = 88, .u16Hfb = 40 + , .u16Vpw = 4, .u16Hpw = 128, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_1080P24] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 24 + , .u16Vact = 1080, .u16Vbb = 36, .u16Vfb = 4 + , .u16Hact = 1920, .u16Hbb = 148, .u16Hfb = 638 + , .u16Vpw = 5, .u16Hpw = 44, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_1080P25] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 25 + , .u16Vact = 1080, .u16Vbb = 36, .u16Vfb = 4 + , .u16Hact = 1920, .u16Hbb = 148, .u16Hfb = 528 + , .u16Vpw = 5, .u16Hpw = 44, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_1080P30] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 30 + , .u16Vact = 1080, .u16Vbb = 36, .u16Vfb = 4 + , .u16Hact = 1920, .u16Hbb = 148, .u16Hfb = 88 + , .u16Vpw = 5, .u16Hpw = 44, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_720P50] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 50 + , .u16Vact = 720, .u16Vbb = 20, .u16Vfb = 5 + , .u16Hact = 1280, .u16Hbb = 220, .u16Hfb = 440 + , .u16Vpw = 5, .u16Hpw = 40, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_720P60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 720, .u16Vbb = 20, .u16Vfb = 5 + , .u16Hact = 1280, .u16Hbb = 220, .u16Hfb = 110 + , .u16Vpw = 5, .u16Hpw = 40, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_1080P50] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 50 + , .u16Vact = 1080, .u16Vbb = 36, .u16Vfb = 4 + , .u16Hact = 1920, .u16Hbb = 148, .u16Hfb = 528 + , .u16Vpw = 5, .u16Hpw = 44, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_1080P60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 1080, .u16Vbb = 36, .u16Vfb = 4 + , .u16Hact = 1920, .u16Hbb = 148, .u16Hfb = 88 + , .u16Vpw = 5, .u16Hpw = 44, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_576P50] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 50 + , .u16Vact = 576, .u16Vbb = 39, .u16Vfb = 5 + , .u16Hact = 720, .u16Hbb = 68, .u16Hfb = 12 + , .u16Vpw = 5, .u16Hpw = 64, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_480P60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 480, .u16Vbb = 30, .u16Vfb = 9 + , .u16Hact = 720, .u16Hbb = 60, .u16Hfb = 16 + , .u16Vpw = 6, .u16Hpw = 62, .bIdv = 0, .bIhs = 0, .bIvs = 0}, + [VO_OUTPUT_720x1280_60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 1280, .u16Vbb = 4, .u16Vfb = 6 + , .u16Hact = 720, .u16Hbb = 36, .u16Hfb = 128 + , .u16Vpw = 16, .u16Hpw = 64, .bIdv = 0, .bIhs = 0, .bIvs = 1}, + [VO_OUTPUT_1080x1920_60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 1920, .u16Vbb = 36, .u16Vfb = 6 + , .u16Hact = 1080, .u16Hbb = 148, .u16Hfb = 88 + , .u16Vpw = 16, .u16Hpw = 64, .bIdv = 0, .bIhs = 0, .bIvs = 1}, + [VO_OUTPUT_480x800_60] = {.bSynm = 1, .bIop = 1, .u16FrameRate = 60 + , .u16Vact = 800, .u16Vbb = 20, .u16Vfb = 20 + , .u16Hact = 480, .u16Hbb = 50, .u16Hfb = 50 + , .u16Vpw = 10, .u16Hpw = 10, .bIdv = 0, .bIhs = 0, .bIvs = 1}, +}; +static pthread_once_t once = PTHREAD_ONCE_INIT; +//static pthread_once_t vo_once = PTHREAD_ONCE_INIT; + +struct vo_pm_s { + VO_PM_OPS_S stOps; + CVI_VOID *pvData; +}; +static struct vo_pm_s apstVoPm[VO_MAX_DEV_NUM] = { 0 }; + +enum i80_op_type { + I80_OP_GO = 0, + I80_OP_TIMER, + I80_OP_DONE, + I80_OP_MAX, +}; + +enum i80_ctrl_type { + I80_CTRL_CMD = 0, + I80_CTRL_DATA, + I80_CTRL_EOL = I80_CTRL_DATA, + I80_CTRL_EOF, + I80_CTRL_END = I80_CTRL_EOF, + I80_CTRL_MAX +}; + +static CVI_U8 i80_ctrl[I80_CTRL_MAX] = { 0x31, 0x75, 0xff }; + +struct cvi_vo_ctx *gVoCtx; + +static CVI_S32 _check_vo_exist(CVI_S32 *pfd) +{ + *pfd = get_vo_fd(); + if (*pfd == -1) { + CVI_TRACE_VO(CVI_DBG_ERR, "Maybe no VO dev?\n"); + return CVI_FAILURE; + } + return CVI_SUCCESS; +} + +static CVI_S32 _vo_proc_mmap(void) +{ + CVI_S32 fd = -1; + + fd = get_vo_fd(); + + if (gVoCtx != NULL) { + CVI_TRACE_VO(CVI_DBG_DEBUG, "vo proc has already done mmap\n"); + return CVI_SUCCESS; + } + + gVoCtx = (struct cvi_vo_ctx *)mmap(NULL, VO_SHARE_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (gVoCtx == MAP_FAILED) { + CVI_TRACE_VO(CVI_DBG_ERR, "vo proc mmap fail!\n"); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +void vo_init(void) +{ + if (_vo_proc_mmap() != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "_vo_proc_mmap failed"); + } +} + +static CVI_S32 _vo_proc_unmap(void) +{ + if (gVoCtx == NULL) { + CVI_TRACE_VO(CVI_DBG_DEBUG, "VO proc no need to unmap\n"); + return CVI_SUCCESS; + } + + munmap((void *)gVoCtx, VO_SHARE_MEM_SIZE); + gVoCtx = NULL; + + return CVI_SUCCESS; +} + +/************************************************************************** + * Bin related APIs. + **************************************************************************/ +#define VO_BIN_GUARDMAGIC 0x12345678 +static VO_BIN_INFO_S vo_bin_info = { + .gamma_info = { + .enable = CVI_FALSE, + .osd_apply = CVI_FALSE, + .value = { + 0, 3, 7, 11, 15, 19, 23, 27, + 31, 35, 39, 43, 47, 51, 55, 59, + 63, 67, 71, 75, 79, 83, 87, 91, + 95, 99, 103, 107, 111, 115, 119, 123, + 127, 131, 135, 139, 143, 147, 151, 155, + 159, 163, 167, 171, 175, 179, 183, 187, + 191, 195, 199, 203, 207, 211, 215, 219, + 223, 227, 231, 235, 239, 243, 247, 251, + 255 + } + }, + .guard_magic = VO_BIN_GUARDMAGIC +}; + +VO_BIN_INFO_S *get_vo_bin_info_addr(void) +{ + return &vo_bin_info; +} + +CVI_U32 get_vo_bin_guardmagic_code(void) +{ + return VO_BIN_GUARDMAGIC; +} +#if 0 // skip in FPGA test +static CVI_U32 _getFileSize(FILE *fp, CVI_U64 *size) +{ + CVI_S32 ret = CVI_SUCCESS; + + MOD_CHECK_NULL_PTR(CVI_ID_VO, fp); + MOD_CHECK_NULL_PTR(CVI_ID_VO, size); + + fseek(fp, 0L, SEEK_END); + *size = ftell(fp); + rewind(fp); + + return ret; +} + +static CVI_S32 CVI_VO_SetVOParamFromBin(void) +{ + CVI_S32 ret = CVI_SUCCESS; + FILE *fp = NULL; + CVI_U8 *buf; + CVI_CHAR binName[BIN_FILE_LENGTH]; + CVI_U64 file_size; + + ret = CVI_BIN_GetBinName(binName); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "GetBinName failure\n"); + } + + fp = fopen(binName, "rb"); + if (fp == NULL) { + CVI_TRACE_VO(CVI_DBG_ERR, "Cant find bin(%s)\n", binName); + return CVI_FAILURE; + } + CVI_TRACE_VO(CVI_DBG_DEBUG, "Bin exist (%s)\n", binName); + + _getFileSize(fp, &file_size); + + buf = (CVI_U8 *)malloc(file_size); + if (buf == NULL) { + CVI_TRACE_VO(CVI_DBG_ERR, "Allocae memory failed!\n"); + fclose(fp); + return CVI_FAILURE; + } + + //fread info buffer and calling CVI_BIN + fread(buf, file_size, 1, fp); + ret = CVI_BIN_LoadParamFromBin(CVI_BIN_ID_VO, buf); + free(buf); + + { + struct vdev *d; + //set gamma with HW from bin or default value + d = get_dev_info(VDEV_TYPE_DISP, 0); + vo_set_gamma_ctrl(d->fd, &vo_bin_info.gamma_info); + } + return CVI_SUCCESS; +} +#endif + +void vo_layer_init(void) +{ + PROC_AMP_CTRL_S ctrl; + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + } + + for (CVI_U8 i = PROC_AMP_BRIGHTNESS; i < PROC_AMP_MAX; ++i) { + CVI_VO_GetLayerProcAmpCtrl(0, i, &ctrl); + gVoCtx->proc_amp[i] = ctrl.default_value; + } +} + +CVI_S32 CVI_VO_Suspend(void) +{ + CVI_S32 s32Ret; + CVI_S32 fd = -1; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (vo_sdk_suspend(fd) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "vo sdk suspend fail\n"); + return CVI_FAILURE; + } + + for (VO_DEV VoDev = 0; VoDev < VO_MAX_DEV_NUM; ++VoDev) { + if (apstVoPm[VoDev].stOps.pfnPanelSuspend) { + s32Ret = apstVoPm[VoDev].stOps.pfnPanelSuspend(apstVoPm[VoDev].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "Panel[%d] suspend failed with %#x!\n", VoDev, s32Ret); + return s32Ret; + } + } + } + + CVI_TRACE_VO(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_Resume(void) +{ + VO_LAYER VoLayer = 0; + VO_CHN VoChn = 0; + CVI_S32 s32Ret; + CVI_S32 fd = -1; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + for (VO_DEV VoDev = 0; VoDev < VO_MAX_DEV_NUM; ++VoDev) { + if (!gVoCtx->is_dev_enable[VoDev]) + continue; + + if (apstVoPm[VoDev].stOps.pfnPanelResume) { + s32Ret = apstVoPm[VoDev].stOps.pfnPanelResume(apstVoPm[VoDev].pvData); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "Panel[%d] resume failed with %#x!\n", VoDev, s32Ret); + return s32Ret; + } + } + gVoCtx->is_dev_enable[VoDev] = CVI_FALSE; + CVI_VO_SetPubAttr(VoDev, &gVoCtx->stPubAttr); + gVoCtx->is_dev_enable[VoDev] = CVI_TRUE; + } + + if (gVoCtx->is_layer_enable[VoLayer]) { + gVoCtx->is_layer_enable[VoLayer] = CVI_FALSE; + CVI_VO_SetVideoLayerAttr(VoLayer, &gVoCtx->stLayerAttr); + gVoCtx->is_layer_enable[VoLayer] = CVI_TRUE; + } + if (gVoCtx->is_chn_enable[VoLayer][VoChn]) { + if (vo_sdk_resume(fd) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "vo sdk resume fail\n"); + return CVI_FAILURE; + } + } + + CVI_TRACE_VO(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_VO_SetPubAttr(VO_DEV VoDev, const VO_PUB_ATTR_S *pstPubAttr) +{ + CVI_S32 fd = -1; + struct vo_pub_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoDev = VoDev; + CVI_TRACE_VO(CVI_DBG_DEBUG, "VoDev(%d) INTF type(0x%x) Sync(%d)\n", VoDev + , pstPubAttr->enIntfType, pstPubAttr->enIntfSync); + + memcpy(&cfg.pstPubAttr, pstPubAttr,sizeof(VO_PUB_ATTR_S)); + + if (VoDev == 0 && (!gVoCtx)) { + //pthread_once(&vo_once, vo_init); + CVI_TRACE_VO(CVI_DBG_DEBUG, "gVoCtx == null"); + vo_init(); + } + + if (vo_sdk_set_pubattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) Set Pub Attr fail\n", VoDev); + return CVI_FAILURE; + } + + return CVI_SUCCESS; + +} + +CVI_S32 CVI_VO_GetPubAttr(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr) +{ + CVI_S32 fd = -1; + struct vo_pub_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoDev = VoDev; + + if (vo_sdk_get_pubattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) Get Pub Attr fail\n", VoDev); + return CVI_FAILURE; + } + + memcpy(pstPubAttr, &cfg.pstPubAttr, sizeof(VO_PUB_ATTR_S)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_I80Init(VO_DEV VoDev, const VO_I80_INSTR_S *pi80Instr, CVI_U8 size) +{ + CVI_S32 fd = -1; + CVI_U32 sw_cmd; + + MOD_CHECK_NULL_PTR(CVI_ID_VO, pi80Instr); + CHECK_VO_DEV_VALID(VoDev); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + if (gVoCtx->stPubAttr.enIntfType != VO_INTF_I80) { + CVI_TRACE_VO(CVI_DBG_ERR, "VO DEV(%d) interface(%d) is not I80.\n", + VoDev, gVoCtx->stPubAttr.enIntfType); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + vo_set_i80_sw_mode(fd, CVI_TRUE); + for (int i = 0; i < size; i++) { + if (pi80Instr[i].data_type > 1) { + CVI_TRACE_VO(CVI_DBG_ERR, "VO I80 instr type(%d) invalid.\n", pi80Instr[i].data_type); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + sw_cmd = (i80_ctrl[pi80Instr[i].data_type] << 8) | pi80Instr[i].data; + vo_send_i80_cmd(fd, sw_cmd); + + if (pi80Instr[i].delay) + usleep(pi80Instr[i].delay); + } + // pull high i80-lane + vo_send_i80_cmd(fd, 0xffff); + vo_send_i80_cmd(fd, 0x2ffff); + vo_set_i80_sw_mode(fd, CVI_FALSE); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_Enable(VO_DEV VoDev) +{ + CVI_S32 fd = -1; + struct vo_dev_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoDev = VoDev; + + if (vo_sdk_enable(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) Enable fail\n", VoDev); + return CVI_FAILURE; + } + +#if 0 // skip in FPGA test + //set vo parameter if bin has parameters + CVI_VO_SetVOParamFromBin(); +#endif + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_Disable(VO_DEV VoDev) +{ + CVI_S32 fd = -1; + struct vo_dev_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoDev = VoDev; + + if (vo_sdk_disable(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) Disable fail\n", VoDev); + return CVI_FAILURE; + } + + if (_vo_proc_unmap() != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "_vo_proc_mmap failed"); + return CVI_ERR_VO_NO_MEM; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SetVideoLayerCSC(VO_LAYER VoLayer, const VO_CSC_S *pstVideoCSC) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, pstVideoCSC); + CHECK_VO_LAYER_VALID(VoLayer); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetVideoLayerCSC(VO_LAYER VoLayer, VO_CSC_S *pstVideoCSC) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, pstVideoCSC); + CHECK_VO_LAYER_VALID(VoLayer); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_EnableVideoLayer(VO_LAYER VoLayer) +{ + CVI_S32 fd = -1; + struct vo_video_layer_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + if (vo_sdk_enable_videolayer(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Enable Video Layer fail\n", VoLayer); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_DisableVideoLayer(VO_LAYER VoLayer) +{ + CVI_S32 fd = -1; + struct vo_video_layer_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + if (vo_sdk_disable_videolayer(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Disable Video Layer fail\n", VoLayer); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SetVideoLayerAttr(VO_LAYER VoLayer, const VO_VIDEO_LAYER_ATTR_S *pstLayerAttr) +{ + CVI_S32 fd = -1; + struct vo_video_layer_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + memcpy(&cfg.pstLayerAttr, pstLayerAttr, sizeof(VO_VIDEO_LAYER_ATTR_S)); + + if (vo_sdk_set_videolayerattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Video Layer Attr fail\n", VoLayer); + return CVI_FAILURE; + } + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + if (IS_FMT_YUV(gVoCtx->stLayerAttr.enPixFormat)) + pthread_once(&once, vo_layer_init); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetVideoLayerAttr(VO_LAYER VoLayer, VO_VIDEO_LAYER_ATTR_S *pstLayerAttr) +{ + CVI_S32 fd = -1; + struct vo_video_layer_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + + if (vo_sdk_get_videolayerattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Get Video Layer Attr fail\n", VoLayer); + return CVI_FAILURE; + } + memcpy(pstLayerAttr, &cfg.pstLayerAttr, sizeof(VO_VIDEO_LAYER_ATTR_S)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetLayerProcAmpCtrl(VO_LAYER VoLayer, PROC_AMP_E type, PROC_AMP_CTRL_S *ctrl) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, ctrl); + CHECK_VO_LAYER_VALID(VoLayer); + + if (!IS_FMT_YUV(gVoCtx->stLayerAttr.enPixFormat)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + if (type >= PROC_AMP_MAX) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) ProcAmp type(%d) invalid.\n", VoLayer, type); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + static PROC_AMP_CTRL_S ctrls[PROC_AMP_MAX] = { + { .minimum = 0, .maximum = 255, .step = 1, .default_value = 128 }, + { .minimum = 0, .maximum = 255, .step = 1, .default_value = 128 }, + { .minimum = 0, .maximum = 255, .step = 1, .default_value = 128 }, + { .minimum = 0, .maximum = 359, .step = 1, .default_value = 0 }, + }; + + *ctrl = ctrls[type]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetLayerProcAmp(VO_LAYER VoLayer, PROC_AMP_E type, CVI_S32 *value) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, value); + CHECK_VO_LAYER_VALID(VoLayer); + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + if (!IS_FMT_YUV(gVoCtx->stLayerAttr.enPixFormat)) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Only YUV format support.\n", VoLayer); + return CVI_ERR_VO_NOT_SUPPORT; + } + if (type >= PROC_AMP_MAX) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) ProcAmp type(%d) invalid.\n", VoLayer, type); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + *value = gVoCtx->proc_amp[type]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SetLayerProcAmp(VO_LAYER VoLayer, PROC_AMP_E type, CVI_S32 value) +{ + PROC_AMP_CTRL_S ctrl; + CVI_S32 fd = -1; + + CHECK_VO_LAYER_VALID(VoLayer); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + if (!IS_FMT_YUV(gVoCtx->stLayerAttr.enPixFormat)) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Only YUV format support.\n", VoLayer); + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (type >= PROC_AMP_MAX) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) ProcAmp type(%d) invalid.\n", VoLayer, type); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + CVI_VO_GetLayerProcAmpCtrl(VoLayer, type, &ctrl); + if ((value > ctrl.maximum) || (value < ctrl.minimum)) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) new value(%d) out of range(%d ~ %d).\n" + , VoLayer, value, ctrl.minimum, ctrl.maximum); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + + gVoCtx->proc_amp[type] = value; + + struct cvi_csc_cfg csc_cfg; + CVI_S32 b = (gVoCtx->proc_amp[PROC_AMP_BRIGHTNESS] >> 1) - 64; + float c = (float)gVoCtx->proc_amp[PROC_AMP_CONTRAST] / 128; + float s = (float)gVoCtx->proc_amp[PROC_AMP_SATURATION] / 128; + float h = (float)gVoCtx->proc_amp[PROC_AMP_HUE] * 2 * PI / 360; + float A = cos(h) * c * s; + float B = sin(h) * c * s; + float tmp; + + if (b > 0) { + csc_cfg.sub[0] = 0; + csc_cfg.add[0] = b * c; + csc_cfg.add[1] = csc_cfg.add[0]; + csc_cfg.add[2] = csc_cfg.add[0]; + } else { + csc_cfg.sub[0] = abs(b); + csc_cfg.add[0] = 0; + csc_cfg.add[1] = 0; + csc_cfg.add[2] = 0; + } + csc_cfg.sub[1] = 128; + csc_cfg.sub[2] = 128; + + csc_cfg.coef[0][0] = c * BIT(10); + tmp = B * -1.402; + csc_cfg.coef[0][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = A * 1.402; + csc_cfg.coef[0][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + csc_cfg.coef[1][0] = c * BIT(10); + tmp = A * -0.344 + B * 0.714; + csc_cfg.coef[1][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = B * -0.344 + A * -0.714; + csc_cfg.coef[1][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + csc_cfg.coef[2][0] = c * BIT(10); + tmp = A * 1.772; + csc_cfg.coef[2][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = B * 1.772; + csc_cfg.coef[2][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + + vo_set_csc(fd, &csc_cfg); + CVI_TRACE_VO(CVI_DBG_DEBUG, "coef[0][0]: %#4x coef[0][1]: %#4x coef[0][2]: %#4x\n" + , csc_cfg.coef[0][0], csc_cfg.coef[0][1] + , csc_cfg.coef[0][2]); + CVI_TRACE_VO(CVI_DBG_DEBUG, "coef[1][0]: %#4x coef[1][1]: %#4x coef[1][2]: %#4x\n" + , csc_cfg.coef[1][0], csc_cfg.coef[1][1] + , csc_cfg.coef[1][2]); + CVI_TRACE_VO(CVI_DBG_DEBUG, "coef[2][0]: %#4x coef[2][1]: %#4x coef[2][2]: %#4x\n" + , csc_cfg.coef[2][0], csc_cfg.coef[2][1] + , csc_cfg.coef[2][2]); + CVI_TRACE_VO(CVI_DBG_DEBUG, "sub[0]: %3d sub[1]: %3d sub[2]: %3d\n" + , csc_cfg.sub[0], csc_cfg.sub[1], csc_cfg.sub[2]); + CVI_TRACE_VO(CVI_DBG_DEBUG, "add[0]: %3d add[1]: %3d add[2]: %3d\n" + , csc_cfg.add[0], csc_cfg.add[1], csc_cfg.add[2]); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, const VO_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = -1; + struct vo_chn_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + memcpy(&cfg.pstChnAttr, pstChnAttr ,sizeof(VO_CHN_ATTR_S)); + + if (vo_sdk_set_chnattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Chn Attr fail\n", VoLayer); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = -1; + struct vo_chn_attr_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + if (vo_sdk_get_chnattr(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Chn Attr fail\n", VoLayer); + return CVI_FAILURE; + } + + memcpy(pstChnAttr, &cfg.pstChnAttr, sizeof(VO_CHN_ATTR_S)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetScreenFrame(VO_LAYER VoLayer, VIDEO_FRAME_INFO_S *pstVideoFrame, CVI_S32 s32MilliSec) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, pstVideoFrame); + CHECK_VO_LAYER_VALID(VoLayer); + + UNUSED(s32MilliSec); + return CVI_ERR_VO_NOT_SUPPORT; +} + +CVI_S32 CVI_VO_ReleaseScreenFrame(VO_LAYER VoLayer, const VIDEO_FRAME_INFO_S *pstVideoFrame) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VO, pstVideoFrame); + CHECK_VO_LAYER_VALID(VoLayer); + return CVI_ERR_VO_NOT_SUPPORT; +} + +CVI_S32 CVI_VO_SetDisplayBufLen(VO_LAYER VoLayer, CVI_U32 u32BufLen) +{ + CVI_S32 fd = -1; + struct vo_display_buflen_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.u32BufLen = u32BufLen; + + if (vo_sdk_set_displaybuflen(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Display BufLen (%d)fail\n", VoLayer, u32BufLen); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetDisplayBufLen(VO_LAYER VoLayer, CVI_U32 *pu32BufLen) +{ + CVI_S32 fd = -1; + struct vo_display_buflen_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + + if (vo_sdk_get_displaybuflen(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Get Display BufLen (%d)fail\n", VoLayer, cfg.u32BufLen); + return CVI_FAILURE; + } + + *pu32BufLen = cfg.u32BufLen; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_EnableChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CVI_S32 fd = -1; + struct vo_chn_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + if (vo_sdk_enable_chn(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Enable Chn(%d) fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_DisableChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CVI_S32 fd = -1; + struct vo_chn_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + if (vo_sdk_disable_chn(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Disable Chn(%d) fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SetChnRotation(VO_LAYER VoLayer, VO_CHN VoChn, ROTATION_E enRotation) +{ + CVI_S32 fd = -1; + struct vo_chn_rotation_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + cfg.enRotation = enRotation; + if (enRotation == ROTATION_180) { + CVI_TRACE_VO(CVI_DBG_ERR, "not support rotation(%d).\n", enRotation); + return CVI_ERR_VO_NOT_SUPPORT; + } else if (enRotation >= ROTATION_MAX) { + CVI_TRACE_VO(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation); + return CVI_ERR_VO_ILLEGAL_PARAM; + } + if (vo_sdk_set_chnrotation(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Chn(%d) Rotation fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetChnRotation(VO_LAYER VoLayer, VO_CHN VoChn, ROTATION_E *penRotation) +{ + CVI_S32 fd = -1; + struct vo_chn_rotation_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + if (vo_sdk_get_chnrotation(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Set Chn(%d) Rotation fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + *penRotation = cfg.enRotation; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_SendFrame(VO_LAYER VoLayer, VO_CHN VoChn, VIDEO_FRAME_INFO_S *pstVideoFrame, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = -1; + struct vo_snd_frm_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + cfg.s32MilliSec = s32MilliSec; + + memcpy(&cfg.stVideoFrame, pstVideoFrame, sizeof(VIDEO_FRAME_INFO_S)); + + if (vo_sdk_send_frame(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Chn(%d) send frame fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_ClearChnBuf(VO_LAYER VoLayer, VO_CHN VoChn, CVI_BOOL bClrAll) +{ + CVI_S32 fd = -1; + struct vo_clear_chn_buf_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + cfg.bClrAll = bClrAll; + + if (vo_sdk_clearchnbuf(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Chn(%d) clean buf fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_ShowChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CVI_S32 fd = -1; + + CHECK_VO_CHN_VALID(VoLayer, VoChn); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (vo_set_pattern(fd, CVI_VIP_PAT_OFF) != 0) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) VoChn(%d) Pattern Off failed.\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + gVoCtx->show = CVI_TRUE; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_HideChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CVI_S32 fd = -1; + + CHECK_VO_CHN_VALID(VoLayer, VoChn); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (vo_set_pattern(fd, CVI_VIP_PAT_BLACK) != 0) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) VoChn(%d) Pattern Black failed.\n", VoLayer, VoChn); + return CVI_FAILURE; + } + gVoCtx->show = CVI_FALSE; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_ShowPattern(VO_DEV VoDev, enum VO_PATTERN_MODE PatternId) +{ + CVI_S32 fd = -1; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (vo_set_pattern(fd, (enum cvi_vip_pattern)PatternId) != 0) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoDev(%d) set Pattern failed.\n", VoDev); + return CVI_FAILURE; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_CloseFd(void) +{ + vo_close(); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_PauseChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CHECK_VO_CHN_VALID(VoLayer, VoChn); + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + gVoCtx->pause = CVI_TRUE; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_ResumeChn(VO_LAYER VoLayer, VO_CHN VoChn) +{ + CHECK_VO_CHN_VALID(VoLayer, VoChn); + + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + gVoCtx->pause = CVI_FALSE; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_Get_Panel_Status(VO_LAYER VoLayer, VO_CHN VoChn, CVI_U32 *is_init) +{ + CVI_S32 fd = -1; + struct vo_panel_status_cfg cfg; + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + cfg.VoLayer = VoLayer; + cfg.VoChn = VoChn; + + if (vo_sdk_get_panelstatue(fd, &cfg) != CVI_SUCCESS) { + CVI_TRACE_VO(CVI_DBG_ERR, "VoLayer(%d) Chn(%d) Get Panel Status fail\n", VoLayer, VoChn); + return CVI_FAILURE; + } + + memcpy(&is_init, &cfg.is_init, sizeof(is_init)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_RegPmCallBack(VO_DEV VoDev, VO_PM_OPS_S *pstPmOps, void *pvData) +{ + CHECK_VO_DEV_VALID(VoDev); + MOD_CHECK_NULL_PTR(CVI_ID_VO, pstPmOps); + + apstVoPm[VoDev].stOps = *pstPmOps; + apstVoPm[VoDev].pvData = pvData; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_UnRegPmCallBack(VO_DEV VoDev) +{ + CHECK_VO_DEV_VALID(VoDev); + + memset(&apstVoPm[VoDev].stOps, 0, sizeof(apstVoPm[VoDev].stOps)); + apstVoPm[VoDev].pvData = NULL; + return CVI_SUCCESS; +} + +CVI_BOOL CVI_VO_IsEnabled(VO_DEV VoDev) +{ + if (!gVoCtx) { + CVI_TRACE_VO(CVI_DBG_NOTICE, "VO context not init yet.\n"); + return CVI_FAILURE; + } + + return gVoCtx->is_dev_enable[VoDev]; +} + +CVI_S32 CVI_VO_SetGammaInfo(VO_GAMMA_INFO_S *pinfo) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_VO, pinfo); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (!CVI_VO_IsEnabled(0)) + return CVI_ERR_VO_SYS_NOTREADY; + + vo_set_gamma_ctrl(fd, pinfo); + + memcpy(&vo_bin_info.gamma_info, pinfo, sizeof(VO_GAMMA_INFO_S)); + vo_bin_info.guard_magic = VO_BIN_GUARDMAGIC; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VO_GetGammaInfo(VO_GAMMA_INFO_S *pinfo) +{ + CVI_S32 fd = -1; + + MOD_CHECK_NULL_PTR(CVI_ID_VO, pinfo); + + if (_check_vo_exist(&fd)) { + return CVI_ERR_VO_NOT_SUPPORT; + } + + if (!CVI_VO_IsEnabled(0)) + return CVI_ERR_VO_SYS_NOTREADY; + + //calling HW + vo_get_gamma_ctrl(fd, pinfo); + + return CVI_SUCCESS; +} + + diff --git a/middleware/v2/modules/vpu/src/cvi_vpss.c b/middleware/v2/modules/vpu/src/cvi_vpss.c new file mode 100644 index 000000000..071e44f89 --- /dev/null +++ b/middleware/v2/modules/vpu/src/cvi_vpss.c @@ -0,0 +1,1591 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_buffer.h" +#include "cvi_base.h" +#include "cvi_vpss.h" +#include "cvi_sys.h" +#include "cvi_gdc.h" +#include "gdc_mesh.h" +#include "cvi_bin.h" +#include "vpss_bin.h" +#include "vpss_ioctl.h" + + +#define CHECK_VPSS_GDC_FMT(grp, chn, fmt) \ + do { \ + if (!GDC_SUPPORT_FMT(fmt)) { \ + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) invalid PixFormat(%d) for GDC.\n" \ + , grp, chn, (fmt)); \ + return CVI_ERR_VPSS_ILLEGAL_PARAM; \ + } \ + } while (0) + + + +struct cvi_gdc_mesh mesh[VPSS_MAX_GRP_NUM][VPSS_MAX_CHN_NUM]; + + +static inline CVI_S32 CHECK_VPSS_GRP_VALID(VPSS_GRP grp) +{ + if ((grp >= VPSS_MAX_GRP_NUM) || (grp < 0)) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "VpssGrp(%d) exceeds Max(%d)\n", grp, VPSS_MAX_GRP_NUM); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + return CVI_SUCCESS; +} + +static inline CVI_S32 CHECK_VPSS_CHN_VALID(VPSS_CHN VpssChn) +{ + if ((VpssChn >= VPSS_MAX_CHN_NUM) || (VpssChn < 0)) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Chn(%d) invalid.\n", VpssChn); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + return CVI_SUCCESS; +} + +/************************************************************************** + * Job related APIs. + **************************************************************************/ +static CVI_S32 _vpss_update_rotation_mesh(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, + ROTATION_E enRotation, CVI_U32 u32Width, CVI_U32 u32Height) +{ +#ifdef ARCH_CV183X + CVI_U64 paddr, paddr_old; + CVI_VOID *vaddr, *vaddr_old; + struct cvi_gdc_mesh *pmesh = &mesh[VpssGrp][VpssChn]; + + // acquire memory space for mesh. + if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "vpss_mesh", CVI_GDC_MESH_SIZE_ROT) != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) Can't acquire memory for rotation mesh.\n" + , VpssGrp, VpssChn); + return CVI_ERR_VPSS_NOMEM; + } + + SIZE_S in_size, out_size; + + in_size.u32Width = u32Width; + in_size.u32Height = u32Height; + if (enRotation == ROTATION_180) { + out_size = in_size; + } else { + out_size.u32Width = in_size.u32Height; + out_size.c = in_size.u32Width; + } + mesh_gen_rotation(in_size, out_size, enRotation, paddr, vaddr); + CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_ROT); + + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "Grp(%d) Chn(%d) mesh base(%#"PRIx64") vaddr(%p)\n" + , VpssGrp, VpssChn, paddr, vaddr); + + pthread_mutex_lock(&pmesh->lock); + if (pmesh->paddr != 0) { + paddr_old = pmesh->paddr; + vaddr_old = pmesh->vaddr; + } else { + paddr_old = 0; + vaddr_old = NULL; + } + pmesh->paddr = paddr; + pmesh->vaddr = vaddr; + pthread_mutex_unlock(&pmesh->lock); + if (paddr_old) + CVI_SYS_IonFree(paddr_old, vaddr_old); +#elif defined(ARCH_CV182X) + struct cvi_gdc_mesh *pmesh = &mesh[VpssGrp][VpssChn]; + + UNUSED(u32Width); + UNUSED(u32Height); + UNUSED(enRotation); + // TODO: dummy settings + pmesh->paddr = DEFAULT_MESH_PADDR; +#elif defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) + CVI_S32 fd = get_vpss_fd(); + struct cvi_gdc_mesh *pmesh = &mesh[VpssGrp][VpssChn]; + struct vpss_chn_rot_cfg cfg; + + UNUSED(u32Width); + UNUSED(u32Height); + // TODO: dummy settings + pmesh->paddr = DEFAULT_MESH_PADDR; + + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.enRotation = enRotation; + return vpss_set_chn_rotation(fd, &cfg); +#endif + return CVI_SUCCESS; +} + +static CVI_S32 _vpss_update_ldc_mesh(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, + const VPSS_LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation, CVI_U32 u32Width, CVI_U32 u32Height) +{ + CVI_U64 paddr, paddr_old; + CVI_VOID *vaddr, *vaddr_old; + struct cvi_gdc_mesh *pmesh = &mesh[VpssGrp][VpssChn]; + CVI_S32 s32Ret; + + if (!pstLDCAttr->bEnable) { + if (enRotation != ROTATION_0) + return _vpss_update_rotation_mesh(VpssGrp, VpssChn, enRotation, + u32Width, u32Height); + else { + CVI_S32 fd = get_vpss_fd(); + struct vpss_chn_ldc_cfg cfg; + + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.enRotation = enRotation; + cfg.stLDCAttr = *pstLDCAttr; + cfg.meshHandle = paddr; + return vpss_set_chn_ldc(fd, &cfg); + } + } + + s32Ret = CVI_GDC_GenLDCMesh(u32Width, u32Height, &pstLDCAttr->stAttr, + "vpss_mesh", &paddr, &vaddr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) gen mesh fail\n", + VpssGrp, VpssChn); + return s32Ret; + } + + pthread_mutex_lock(&pmesh->lock); + if (pmesh->paddr) { + paddr_old = pmesh->paddr; + vaddr_old = pmesh->vaddr; + } else { + paddr_old = 0; + vaddr_old = NULL; + } + pmesh->paddr = paddr; + pmesh->vaddr = vaddr; + pthread_mutex_unlock(&pmesh->lock); + if (paddr_old) + CVI_SYS_IonFree(paddr_old, vaddr_old); + + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "Grp(%d) Chn(%d) mesh base(%#"PRIx64") vaddr(%p)\n" + , VpssGrp, VpssChn, paddr, vaddr); + +#if defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) + CVI_S32 fd = get_vpss_fd(); + struct vpss_chn_ldc_cfg cfg; + + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.enRotation = enRotation; + cfg.stLDCAttr = *pstLDCAttr; + cfg.meshHandle = paddr; + return vpss_set_chn_ldc(fd, &cfg); +#endif + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_Suspend(void) +{ + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_Resume(void) +{ + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "+\n"); + + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "-\n"); + return CVI_SUCCESS; +} +/************************************************************************** + * Public APIs. + **************************************************************************/ +CVI_S32 CVI_VPSS_CreateGrp(VPSS_GRP VpssGrp, const VPSS_GRP_ATTR_S *pstGrpAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_crt_grp_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstGrpAttr); + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + memcpy(&cfg.stGrpAttr, pstGrpAttr, sizeof(cfg.stGrpAttr)); + + s32Ret = vpss_create_grp(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) VpssDev(%d) create group fail\n", + VpssGrp, pstGrpAttr->u8VpssDev); + return s32Ret; + } + // for chn rotation, ldc mesh gen + for (CVI_U8 i = 0; i < VPSS_MAX_CHN_NUM; ++i) + pthread_mutex_init(&mesh[VpssGrp][i].lock, NULL); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_DestroyGrp(VPSS_GRP VpssGrp) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_destroy_grp(fd, VpssGrp); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) destroy group fail\n", VpssGrp); + return s32Ret; + } + for (CVI_U8 i = 0; i < VPSS_MAX_CHN_NUM; ++i) + pthread_mutex_destroy(&mesh[VpssGrp][i].lock); + + return CVI_SUCCESS; +} + +VPSS_GRP CVI_VPSS_GetAvailableGrp(void) +{ + CVI_S32 fd = get_vpss_fd(); + VPSS_GRP grp = VPSS_INVALID_GRP; + + vpss_get_available_grp(fd, &grp); + + return grp; +} + +CVI_S32 CVI_VPSS_StartGrp(VPSS_GRP VpssGrp) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_str_grp_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + s32Ret = vpss_start_grp(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) start group fail\n", + VpssGrp); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_StopGrp(VPSS_GRP VpssGrp) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_stop_grp(fd, VpssGrp); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) stop group fail\n", VpssGrp); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_ResetGrp(VPSS_GRP VpssGrp) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_reset_grp(fd, VpssGrp); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) reset group fail\n", VpssGrp); + return s32Ret; + } + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetGrpAttr(VPSS_GRP VpssGrp, VPSS_GRP_ATTR_S *pstGrpAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_grp_attr cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstGrpAttr); + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + + s32Ret = vpss_get_grp_attr(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get grp attr fail\n", VpssGrp); + return s32Ret; + } + + memcpy(pstGrpAttr, &cfg.stGrpAttr, sizeof(*pstGrpAttr)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetGrpAttr(VPSS_GRP VpssGrp, const VPSS_GRP_ATTR_S *pstGrpAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_grp_attr cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstGrpAttr); + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + memcpy(&cfg.stGrpAttr, pstGrpAttr, sizeof(cfg.stGrpAttr)); + + s32Ret = vpss_set_grp_attr(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) set grp attr fail\n", + VpssGrp); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetGrpProcAmpCtrl(VPSS_GRP VpssGrp, PROC_AMP_E type, PROC_AMP_CTRL_S *ctrl) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_proc_amp_ctrl_cfg cfg = {0}; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, ctrl); + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.type = type; + s32Ret = vpss_get_proc_amp_ctrl(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get proc amp ctrl fail\n", VpssGrp); + return s32Ret; + } + *ctrl = cfg.ctrl; + + return CVI_SUCCESS; +} + +static void _vpss_proamp_2_csc(struct vpss_grp_csc_cfg *csc_cfg) +{ + // for grp proc-amp. + CVI_S32 *proc_amp = csc_cfg->proc_amp; + float h = (float)(proc_amp[PROC_AMP_HUE] - 50) * PI / 360; + float b_off = (proc_amp[PROC_AMP_BRIGHTNESS] - 50) * 2.56; + float C_gain = 1 + (proc_amp[PROC_AMP_CONTRAST] - 50) * 0.02; + float S = 1 + (proc_amp[PROC_AMP_SATURATION] - 50) * 0.02; + float A = cos(h) * C_gain * S; + float B = sin(h) * C_gain * S; + float C_diff, c_off, tmp; + CVI_U8 sub_0_l, add_0_l, add_1_l, add_2_l; + + if (proc_amp[PROC_AMP_CONTRAST] > 50) + C_diff = 256 / C_gain; + else + C_diff = 256 * C_gain; + c_off = 128 - (C_diff/2); + + if (b_off < 0) { + sub_0_l = abs(proc_amp[PROC_AMP_BRIGHTNESS] - 50) * 2.56; + add_0_l = 0; + add_1_l = 0; + add_2_l = 0; + } else { + sub_0_l = 0; + if ((C_gain * b_off) > 255) { + add_0_l = 255; + } else { + add_0_l = C_gain * b_off; + } + add_1_l = add_0_l; + add_2_l = add_0_l; + } + + if (proc_amp[PROC_AMP_CONTRAST] > 50) { + csc_cfg->sub[0] = sub_0_l + c_off; + csc_cfg->add[0] = add_0_l; + csc_cfg->add[1] = add_1_l; + csc_cfg->add[2] = add_2_l; + } else { + csc_cfg->sub[0] = sub_0_l; + csc_cfg->add[0] = add_0_l + c_off; + csc_cfg->add[1] = add_1_l + c_off; + csc_cfg->add[2] = add_2_l + c_off; + } + csc_cfg->sub[1] = 128; + csc_cfg->sub[2] = 128; + + csc_cfg->coef[0][0] = C_gain * BIT(10); + tmp = B * -1.402; + csc_cfg->coef[0][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = A * 1.402; + csc_cfg->coef[0][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + csc_cfg->coef[1][0] = C_gain * BIT(10); + tmp = A * -0.344 + B * 0.714; + csc_cfg->coef[1][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = B * -0.344 + A * -0.714; + csc_cfg->coef[1][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + csc_cfg->coef[2][0] = C_gain * BIT(10); + tmp = A * 1.772; + csc_cfg->coef[2][1] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + tmp = B * 1.772; + csc_cfg->coef[2][2] = (tmp >= 0) ? tmp * BIT(10) : (CVI_U16)((-tmp) * BIT(10)) | BIT(13); + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "coef[0][0]: %#4x coef[0][1]: %#4x coef[0][2]: %#4x\n" + , csc_cfg->coef[0][0], csc_cfg->coef[0][1] + , csc_cfg->coef[0][2]); + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "coef[1][0]: %#4x coef[1][1]: %#4x coef[1][2]: %#4x\n" + , csc_cfg->coef[1][0], csc_cfg->coef[1][1] + , csc_cfg->coef[1][2]); + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "coef[2][0]: %#4x coef[2][1]: %#4x coef[2][2]: %#4x\n" + , csc_cfg->coef[2][0], csc_cfg->coef[2][1] + , csc_cfg->coef[2][2]); + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "sub[0]: %3d sub[1]: %3d sub[2]: %3d\n" + , csc_cfg->sub[0], csc_cfg->sub[1], csc_cfg->sub[2]); + CVI_TRACE_VPSS(CVI_DBG_DEBUG, "add[0]: %3d add[1]: %3d add[2]: %3d\n" + , csc_cfg->add[0], csc_cfg->add[1], csc_cfg->add[2]); +} + +CVI_S32 CVI_VPSS_GetGrpProcAmp(VPSS_GRP VpssGrp, PROC_AMP_E type, CVI_S32 *value) +{ + CVI_S32 s32Ret; + CVI_S32 fd = get_vpss_fd(); + struct vpss_proc_amp_cfg cfg = {0}; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, value); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + if (type >= PROC_AMP_MAX) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) ProcAmp type(%d) invalid.\n", VpssGrp, type); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + + cfg.VpssGrp = VpssGrp; + s32Ret = vpss_get_proc_amp(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get proc amp fail\n", VpssGrp); + return s32Ret; + } + *value = cfg.proc_amp[type]; + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetGrpProcAmp(VPSS_GRP VpssGrp, PROC_AMP_E type, const CVI_S32 value) +{ + CVI_S32 s32Ret; + PROC_AMP_CTRL_S ctrl; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + if (type >= PROC_AMP_MAX) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) ProcAmp type(%d) invalid.\n", VpssGrp, type); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + + CVI_VPSS_GetGrpProcAmpCtrl(VpssGrp, type, &ctrl); + if ((value > ctrl.maximum) || (value < ctrl.minimum)) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) new value(%d) out of range(%d ~ %d).\n" + , VpssGrp, value, ctrl.minimum, ctrl.maximum); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + +#if defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) + CVI_S32 fd = get_vpss_fd(); + struct vpss_grp_csc_cfg csc_cfg; + struct vpss_proc_amp_cfg amp_cfg; + + amp_cfg.VpssGrp = VpssGrp; + s32Ret = vpss_get_proc_amp(fd, &_cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get proc amp fail\n", VpssGrp); + return s32Ret; + } + amp_cfg.proc_amp[type] = value; + + memset(&csc_cfg, 0, sizeof(csc_cfg)); + csc_cfg.VpssGrp = VpssGrp; + memcpy(csc_cfg.proc_amp, amp_cfg.proc_amp, sizeof(csc_cfg.proc_amp)); + _vpss_proamp_2_csc(&csc_cfg); + + s32Ret = vpss_set_grp_csc(fd, &csc_cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) set group csc fail\n", VpssGrp); + return s32Ret; + } +#endif + + return CVI_SUCCESS; +} + +static CVI_VOID _vpss_check_normalize(VPSS_CHN_ATTR_S *pstChnAttr) +{ + if (pstChnAttr->stNormalize.bEnable) { + for (CVI_U8 i = 0; i < 3; ++i) { + if (pstChnAttr->stNormalize.factor[i] >= 1.0f) { + pstChnAttr->stNormalize.factor[i] = 1.0f - 1.0f/8192; + CVI_TRACE_VPSS(CVI_DBG_WARN, "factor%d replaced with max value 8191/8192\n", i); + } + if (pstChnAttr->stNormalize.factor[i] < (1.0f/8192)) { + pstChnAttr->stNormalize.factor[i] = (1.0f/8192); + CVI_TRACE_VPSS(CVI_DBG_WARN, "factor%d replaced with min value 1/8192\n", i); + } + if (pstChnAttr->stNormalize.mean[i] > 255.0f) { + pstChnAttr->stNormalize.mean[i] = 255.0f; + CVI_TRACE_VPSS(CVI_DBG_WARN, "mean%d replaced with max value 255\n", i); + } + if (pstChnAttr->stNormalize.mean[i] < 0) { + pstChnAttr->stNormalize.mean[i] = 0; + CVI_TRACE_VPSS(CVI_DBG_WARN, "mean%d replaced with min value 0\n", i); + } + } + } +} + +/* Chn Settings */ +CVI_S32 CVI_VPSS_SetChnAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VPSS_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_attr attr = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstChnAttr); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memcpy(&attr.stChnAttr, pstChnAttr, sizeof(attr.stChnAttr)); + // Handle float poing in user space + _vpss_check_normalize(&attr.stChnAttr); + + s32Ret = vpss_set_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) set chn attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_ATTR_S *pstChnAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_attr attr = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstChnAttr); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_get_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + *pstChnAttr = attr.stChnAttr; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_EnableChn(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_en_chn_cfg cfg = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_enable_chn(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) enable fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_DisableChn(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_en_chn_cfg cfg = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_disable_chn(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) disable fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetChnCrop(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VPSS_CROP_INFO_S *pstCropInfo) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_crop_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstCropInfo); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.stCropInfo = *pstCropInfo; + + s32Ret = vpss_set_chn_crop(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) set chn crop fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnCrop(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CROP_INFO_S *pstCropInfo) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_crop_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstCropInfo); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_chn_crop(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn crop fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + *pstCropInfo = cfg.stCropInfo; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_ShowChn(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_en_chn_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_show_chn(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) show chn fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_HideChn(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_en_chn_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_hide_chn(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) hide chn fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetGrpCrop(VPSS_GRP VpssGrp, VPSS_CROP_INFO_S *pstCropInfo) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_grp_crop_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstCropInfo); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + + s32Ret = vpss_get_grp_crop(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get crop fail\n", VpssGrp); + return s32Ret; + } + + *pstCropInfo = cfg.stCropInfo; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetGrpCrop(VPSS_GRP VpssGrp, const VPSS_CROP_INFO_S *pstCropInfo) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_grp_crop_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstCropInfo); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.stCropInfo = *pstCropInfo; + + s32Ret = vpss_set_grp_crop(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) set crop fail\n", VpssGrp); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SendFrame(VPSS_GRP VpssGrp, const VIDEO_FRAME_INFO_S *pstVideoFrame, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_snd_frm_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstVideoFrame); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + memcpy(&cfg.stVideoFrame, pstVideoFrame, sizeof(cfg.stVideoFrame)); + cfg.s32MilliSec = s32MilliSec; + + s32Ret = vpss_send_frame(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) send frame fail\n", VpssGrp); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SendChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn + , const VIDEO_FRAME_INFO_S *pstVideoFrame, CVI_S32 s32MilliSec) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_frm_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstVideoFrame); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + memcpy(&cfg.stVideoFrame, pstVideoFrame, sizeof(cfg.stVideoFrame)); + cfg.s32MilliSec = s32MilliSec; + + s32Ret = vpss_send_chn_frame(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) send chn frame fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VIDEO_FRAME_INFO_S *pstFrameInfo, + CVI_S32 s32MilliSec) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_frm_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstFrameInfo); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.s32MilliSec = s32MilliSec; + + s32Ret = vpss_get_chn_frame(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn frame fail\n", VpssGrp, VpssChn); + return s32Ret; + } + memcpy(pstFrameInfo, &cfg.stVideoFrame, sizeof(*pstFrameInfo)); + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_ReleaseChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VIDEO_FRAME_INFO_S *pstVideoFrame) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_frm_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstVideoFrame); + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + memcpy(&cfg.stVideoFrame, pstVideoFrame, sizeof(cfg.stVideoFrame)); + + s32Ret = vpss_release_chn_frame(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) release chn frame fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnFd(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + return fd; +} + +CVI_S32 CVI_VPSS_CloseFd(void) +{ + vpss_close(); + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetModParam(const VPSS_MOD_PARAM_S *pstModParam) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstModParam); + + //todo: how to use vpssmod param... + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetModParam(VPSS_MOD_PARAM_S *pstModParam) +{ + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstModParam); + + pstModParam->u32VpssSplitNodeNum = 1; + pstModParam->u32VpssVbSource = 0; //vb from common vb pool + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetChnRotation(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, ROTATION_E enRotation) +{ + CVI_S32 s32Ret; + CVI_S32 fd = get_vpss_fd(); + struct vpss_chn_attr attr = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + struct vpss_chn_ldc_cfg ldc_cfg = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_get_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + CHECK_VPSS_GDC_FMT(VpssGrp, VpssChn, attr.stChnAttr.enPixelFormat); + + s32Ret = vpss_get_chn_ldc(fd, &ldc_cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn LDC attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + if (enRotation == ROTATION_180) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "not support rotation(%d).\n", enRotation); + return CVI_ERR_VI_NOT_SUPPORT; + } else if (enRotation >= ROTATION_MAX) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) invalid rotation(%d).\n" + , VpssGrp, VpssChn, enRotation); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } else if (enRotation == ldc_cfg.enRotation) { + CVI_TRACE_VPSS(CVI_DBG_INFO, "rotation(%d) not changed.\n", enRotation); + return CVI_SUCCESS; + } + + if (ldc_cfg.stLDCAttr.bEnable) + return _vpss_update_ldc_mesh(VpssGrp, VpssChn, &ldc_cfg.stLDCAttr, + enRotation, attr.stChnAttr.u32Width, attr.stChnAttr.u32Height); + else + return _vpss_update_rotation_mesh(VpssGrp, VpssChn, enRotation, + attr.stChnAttr.u32Width, attr.stChnAttr.u32Height); +} + +CVI_S32 CVI_VPSS_GetChnRotation(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, ROTATION_E *penRotation) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_rot_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, penRotation); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_chn_rotation(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn rotation fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + *penRotation = cfg.enRotation; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetChnAlign(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, CVI_U32 u32Align) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_align_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.u32Align = u32Align; + + s32Ret = vpss_set_chn_align(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) set chn align fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnAlign(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, CVI_U32 *pu32Align) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_align_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pu32Align); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_chn_align(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn align fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + *pu32Align = cfg.u32Align; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetChnScaleCoefLevel(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_SCALE_COEF_E enCoef) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_coef_level_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.enCoef = enCoef; + + s32Ret = vpss_set_coef_level(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) set chn ScaleCoefLevel fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnScaleCoefLevel(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_SCALE_COEF_E *penCoef) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_coef_level_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, penCoef); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_coef_level(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn ScaleCoefLevel fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + *penCoef = cfg.enCoef; + + return CVI_SUCCESS; +} + +/* CVI_VPSS_SetChnYRatio: Modify the y ratio of chn output. Only work for yuv format. + * + * @param VpssGrp: The Vpss Grp to work. + * @param VpssChn: The Vpss Chn to work. + * @param YRatio: Output's Y will be sacled by this ratio. + * @return: CVI_SUCCESS if OK. + */ +CVI_S32 CVI_VPSS_SetChnYRatio(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, CVI_FLOAT YRatio) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_yratio_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.YRatio = (CVI_U32)(YRatio * 100); + + s32Ret = vpss_set_chn_yratio(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) set chn Y Ratio fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetChnYRatio(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, CVI_FLOAT *pYRatio) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_yratio_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pYRatio); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_chn_yratio(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn Y Ratio fail\n", VpssGrp, VpssChn); + return s32Ret; + } + *pYRatio = (1.0f * cfg.YRatio) / 100.0; + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_SetChnLDCAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VPSS_LDC_ATTR_S *pstLDCAttr) +{ + CVI_S32 s32Ret; + CVI_S32 fd = get_vpss_fd(); + struct vpss_chn_rot_cfg rot_cfg = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + struct vpss_chn_attr attr = {.VpssGrp = VpssGrp, .VpssChn = VpssChn}; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstLDCAttr); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_get_chn_attr(fd, &attr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + CHECK_VPSS_GDC_FMT(VpssGrp, VpssChn, attr.stChnAttr.enPixelFormat); + + s32Ret = vpss_get_chn_rotation(fd, &rot_cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn rotation fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return _vpss_update_ldc_mesh(VpssGrp, VpssChn, pstLDCAttr, rot_cfg.enRotation, + attr.stChnAttr.u32Width, attr.stChnAttr.u32Height); +} + +CVI_S32 CVI_VPSS_GetChnLDCAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_LDC_ATTR_S *pstLDCAttr) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_ldc_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstLDCAttr); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + + s32Ret = vpss_get_chn_ldc(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn LDC attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + memcpy(pstLDCAttr, &cfg.stLDCAttr, sizeof(*pstLDCAttr)); + + return CVI_SUCCESS; +} + +/* CVI_VPSS_SetGrpParamfromBin: Apply the settings of scene from bin + * + * @param VpssGrp: the vpss grp to apply + * @param scene: the scene of settings stored in bin to use + * @return: result of the API + */ +CVI_S32 CVI_VPSS_SetGrpParamfromBin(VPSS_GRP VpssGrp, CVI_U8 scene) +{ + CVI_S32 s32Ret; + VPSS_BIN_DATA *pBinData; + struct vpss_grp_csc_cfg csc_cfg = {0}; + CVI_S32 fd = get_vpss_fd(); + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + if (scene > VPSS_MAX_GRP_NUM) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "scene(%d) is over max(%d)\n", scene, VPSS_MAX_GRP_NUM); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + if (get_loadbin_state()) { + pBinData = get_vpssbindata_addr(); + csc_cfg.VpssGrp = VpssGrp; + csc_cfg.scene = scene; + memcpy(csc_cfg.proc_amp, pBinData[scene].proc_amp, sizeof(csc_cfg.proc_amp)); + _vpss_proamp_2_csc(&csc_cfg); + + s32Ret = vpss_set_grp_csc(fd, &csc_cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) set group csc fail\n", VpssGrp); + return s32Ret; + } + CVI_TRACE_VPSS(CVI_DBG_INFO, "PqBin is exist, vpss grp param use pqbin value !!\n"); + } else { + CVI_TRACE_VPSS(CVI_DBG_INFO, "PqBin is not find, vpss grp param use default !!\n"); + } + + return CVI_SUCCESS; +} + +CVI_S32 CVI_VPSS_GetBinScene(VPSS_GRP VpssGrp, CVI_U8 *scene) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_scene cfg = {0}; + + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + s32Ret = vpss_get_binscene(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) get proc amp fail\n", VpssGrp); + return s32Ret; + } + + *scene = cfg.scene; + + return CVI_SUCCESS; + + +} + +CVI_S32 CVI_VPSS_AttachVbPool(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VB_POOL hVbPool) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_vb_pool_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.hVbPool = hVbPool; + return vpss_attach_vbpool(fd, &cfg); +} + +CVI_S32 CVI_VPSS_DetachVbPool(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_vb_pool_cfg cfg; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + return vpss_detach_vbpool(fd, &cfg); +} + +CVI_S32 CVI_VPSS_GetRegionLuma(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VIDEO_REGION_INFO_S *pstRegionInfo, + CVI_U64 *pu64LumaData, CVI_S32 s32MilliSec) +{ + CVI_S32 ret = 0; + VIDEO_FRAME_INFO_S stVideoFrame; + CVI_U8 *pstVirAddr; + SIZE_S stSize; + CVI_U32 u32X, u32Y, u32XStep, u32YStep, u32Num; + CVI_U32 u32MainStride; + CVI_S32 s32StartX, s32StartY; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstRegionInfo); + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pu64LumaData); + + ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (ret != CVI_SUCCESS) + return ret; + ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (ret != CVI_SUCCESS) + return ret; + + s32StartX = pstRegionInfo->pstRegion->s32X; + s32StartY = pstRegionInfo->pstRegion->s32Y; + stSize.u32Width = pstRegionInfo->pstRegion->u32Width; + stSize.u32Height = pstRegionInfo->pstRegion->u32Height; + if ((s32StartX < 0) || (s32StartY < 0)) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "region info(%d %d %d %d) invalid.\n" + , s32StartX, s32StartY, stSize.u32Width, stSize.u32Height); + return CVI_ERR_VPSS_ILLEGAL_PARAM; + } + + ret = CVI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stVideoFrame, s32MilliSec); + if (ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get buf fail\n", VpssGrp, VpssChn); + return CVI_ERR_VPSS_BUF_EMPTY; + } + + if ((s32StartX + stSize.u32Width > stVideoFrame.stVFrame.u32Width) || + (s32StartY + stSize.u32Height > stVideoFrame.stVFrame.u32Height) || + ((CVI_U32)s32StartX >= stVideoFrame.stVFrame.u32Width) || + ((CVI_U32)s32StartY >= stVideoFrame.stVFrame.u32Height) || + (stSize.u32Width > stVideoFrame.stVFrame.u32Width) || + (stSize.u32Height > stVideoFrame.stVFrame.u32Height)) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "size(%d %d %d %d) out of range.\n" + , s32StartX, s32StartY, stSize.u32Width, stSize.u32Height); + ret = CVI_ERR_VPSS_ILLEGAL_PARAM; + goto release_blk; + } + + if (!IS_FMT_YUV(stVideoFrame.stVFrame.enPixelFormat)) { + ret = CVI_ERR_VPSS_NOT_SUPPORT; + CVI_TRACE_VPSS(CVI_DBG_ERR, "only support yuv-fmt(%d).\n" + , stVideoFrame.stVFrame.enPixelFormat); + goto release_blk; + } + + size_t Luma_size = stVideoFrame.stVFrame.u32Length[0]; + + pstVirAddr = CVI_SYS_Mmap(stVideoFrame.stVFrame.u64PhyAddr[0], Luma_size); + if (pstVirAddr == NULL) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "mmap for stVideoFrame failed.\n"); + ret = CVI_FAILURE; + goto release_blk; + } + + u32MainStride = stVideoFrame.stVFrame.u32Stride[0]; + + u32Num = 0; + *pu64LumaData = 0; + u32XStep = stSize.u32Width > 9 ? stSize.u32Width / 9 : 1; + u32YStep = stSize.u32Height > 9 ? stSize.u32Height / 9 : 1; + + for (u32Y = s32StartY; u32Y < s32StartY + stSize.u32Height; u32Y += u32YStep) { + for (u32X = s32StartX; u32X < (s32StartX + stSize.u32Width); u32X += u32XStep) { + *pu64LumaData += *(pstVirAddr + u32X + u32Y * u32MainStride); + u32Num++; + } + } + + for (u32X = s32StartX + u32XStep / 2; u32X < (s32StartX + stSize.u32Width); u32X += u32XStep) { + for (u32Y = s32StartY + u32YStep / 2; u32Y < (s32StartY + stSize.u32Height); u32Y += u32YStep) { + *pu64LumaData += *(pstVirAddr + u32X + u32Y * u32MainStride); + u32Num++; + } + } + + *pu64LumaData = *pu64LumaData / u32Num; + + CVI_SYS_Munmap(pstVirAddr, Luma_size); +release_blk: + if (CVI_VPSS_ReleaseChnFrame(VpssGrp, VpssChn, &stVideoFrame) != CVI_SUCCESS) + return CVI_FAILURE; + return ret; +} + +CVI_S32 CVI_VPSS_TriggerSnapFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, CVI_U32 u32FrameCnt) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_snap_cfg cfg = {.VpssGrp = VpssGrp, .VpssChn = VpssChn, .frame_cnt = u32FrameCnt}; + + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + s32Ret = vpss_trigger_snap_frame(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) Trigger Snap Frame fail\n", VpssGrp, VpssChn); + return s32Ret; + } + + return CVI_SUCCESS; +} + +#if defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) +CVI_S32 CVI_VPSS_SetChnBufWrapAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, const VPSS_CHN_BUF_WRAP_S *pstVpssChnBufWrap) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_wrap_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstVpssChnBufWrap); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.wrap = *pstVpssChnBufWrap; + return vpss_set_chn_wrap(fd, &cfg); +} + +CVI_S32 CVI_VPSS_GetChnBufWrapAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_BUF_WRAP_S *pstVpssChnBufWrap) +{ + CVI_S32 fd = get_vpss_fd(); + CVI_S32 s32Ret; + struct vpss_chn_wrap_cfg cfg; + + MOD_CHECK_NULL_PTR(CVI_ID_VPSS, pstVpssChnBufWrap); + s32Ret = CHECK_VPSS_GRP_VALID(VpssGrp); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + s32Ret = CHECK_VPSS_CHN_VALID(VpssChn); + if (s32Ret != CVI_SUCCESS) + return s32Ret; + + cfg.VpssGrp = VpssGrp; + cfg.VpssChn = VpssChn; + cfg.wrap = *pstVpssChnBufWrap; + + s32Ret = vpss_get_chn_wrap(fd, &cfg); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn Wrap Attr fail\n", VpssGrp, VpssChn); + return s32Ret; + } + memcpy(pstVpssChnBufWrap, &cfg.wrap, sizeof(*pstVpssChnBufWrap)); + + return CVI_SUCCESS; +} + +CVI_U32 CVI_VPSS_GetWrapBufferSize(CVI_U32 u32Width, CVI_U32 u32Height, PIXEL_FORMAT_E enPixelFormat, + CVI_U32 u32BufLine, CVI_U32 u32BufDepth) +{ + CVI_U32 u32BufSize; + VB_CAL_CONFIG_S stCalConfig; + + if (u32Width < 64 || u32Height < 64) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "width(%d) or height(%d) too small\n", u32Width, u32Height); + return 0; + } + if (u32BufLine != 64 && u32BufLine != 128) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "u32BufLine(%d) invalid, only 64 or 128 lines\n", + u32BufLine); + return 0; + } + if (u32BufDepth < 2 || u32BufDepth > 32) { + CVI_TRACE_VPSS(CVI_DBG_ERR, "u32BufDepth(%d) invalid, 2 ~ 32\n", + u32BufDepth); + return 0; + } + + COMMON_GetPicBufferConfig(u32Width, u32Height, enPixelFormat, DATA_BITWIDTH_8 + , COMPRESS_MODE_NONE, DEFAULT_ALIGN, &stCalConfig); + + u32BufSize = stCalConfig.u32VBSize / u32Height; + u32BufSize *= u32BufLine * u32BufDepth; + CVI_TRACE_VPSS(CVI_DBG_INFO, "width(%d), height(%d), u32BufSize=%d\n", + u32Width, u32Height, u32BufSize); + + return u32BufSize; +} +#endif diff --git a/middleware/v2/modules/vpu/src/dump_register.c b/middleware/v2/modules/vpu/src/dump_register.c new file mode 100644 index 000000000..15537f124 --- /dev/null +++ b/middleware/v2/modules/vpu/src/dump_register.c @@ -0,0 +1,2228 @@ +#include +#include +#include +#include +#include +#include + +#include "cvi_base.h" +#include "cvi_vi.h" +#include "cvi_sys.h" +#include "vi_ioctl.h" +#include "cvi_isp.h" + +#define VDEV_CLOSED_CHK(_dev_type, _dev_id) \ + struct vdev *d; \ + d = get_dev_info(_dev_type, _dev_id); \ + if (IS_VDEV_CLOSED(d->state)) { \ + CVI_TRACE_VI(CVI_DBG_ERR, "vi dev(%d) state(%d) incorrect.", \ + _dev_id, d->state); \ + return CVI_ERR_VI_SYS_NOTREADY; \ + } + +#define CHECK_VI_NULL_PTR(ptr) \ + do { \ + if (ptr == NULL) { \ + CVI_TRACE_VI(CVI_DBG_ERR, " Invalid null pointer\n"); \ + return CVI_ERR_VI_INVALID_NULL_PTR; \ + } \ + } while (0) + +#define GET_BASE_VADDR(ip_info_id) \ + do { \ + paddr = ip_info_list[ip_info_id].str_addr; \ + size = ip_info_list[ip_info_id].size; \ + vaddr = CVI_SYS_Mmap(paddr, size); \ + } while (0) + +#define CLEAR_ACCESS_CNT(addr_ofs) \ + do { \ + val = vaddr + addr_ofs; \ + *val = 0x1; \ + } while (0) + +#define SET_BITS(addr_ofs, val_ofs) \ + do { \ + val = vaddr + addr_ofs; \ + data = *val | (0x1 << val_ofs); \ + *val = data; \ + } while (0) + +#define CLEAR_BITS(addr_ofs, val_ofs) \ + do { \ + val = vaddr + addr_ofs; \ + data = *val & (~(0x1 << val_ofs)); \ + *val = data; \ + } while (0) + +#define SET_REGISTER_COMMON(addr_ofs, val_ofs, on_off) \ + do { \ + if (!on_off) {/* off */ \ + CLEAR_BITS(addr_ofs, val_ofs); \ + } else {/* on */ \ + SET_BITS(addr_ofs, val_ofs); \ + } \ + } while (0) + +#define GET_REGISTER_COMMON(addr_ofs, val_ofs, ret) \ + do { \ + val = vaddr + addr_ofs; \ + data = *val; \ + ret = (data >> val_ofs) & 0x1; \ + } while (0) + +#define WAIT_IP_DISABLE(addr_ofs, val_ofs) \ + do { \ + do { \ + usleep(1); \ + val = vaddr + addr_ofs; \ + data = *val; \ + } while (((data >> val_ofs) & 0x1) != 0); \ + } while (0) + +#define SET_SW_MODE_ENABLE(addr_ofs, val_ofs, on_off) \ + SET_REGISTER_COMMON(addr_ofs, val_ofs, on_off) + +#define SET_SW_MODE_MEM_SEL(addr_ofs, val_ofs, mem_id) \ + SET_REGISTER_COMMON(addr_ofs, val_ofs, mem_id) + +#define FPRINTF_VAL() \ + do { \ + val = vaddr + offset; \ + fprintf(fp, "\t\"%s\": {\n", name); \ + fprintf(fp, "\t\t\"length\": %u,\n", length); \ + fprintf(fp, "\t\t\"lut\": [\n"); \ + fprintf(fp, "\t\t\t"); \ + for (CVI_U32 i = 0 ; i < length; i++) { \ + if (i == length - 1) { \ + fprintf(fp, "%u\n", *val); \ + } else if (i % 16 == 15) { \ + fprintf(fp, "%u,\n\t\t\t", *val); \ + } else { \ + fprintf(fp, "%u,\t", *val); \ + } \ + } \ + fprintf(fp, "\t\t]\n\t},\n"); \ + } while (0) + +#define FPRINTF_VAL2() \ + do { \ + val = vaddr + offset; \ + fprintf(fp, "\t\"%s\": {\n", name); \ + fprintf(fp, "\t\t\"length\": %u,\n", length); \ + fprintf(fp, "\t\t\"lut\": [\n"); \ + fprintf(fp, "\t\t\t"); \ + for (CVI_U32 i = 0 ; i < length; i++) { \ + if (i == length - 1) { \ + fprintf(fp, "%u\n", *(val++)); \ + } else if (i % 16 == 15) { \ + fprintf(fp, "%u,\n\t\t\t", *(val++)); \ + } else { \ + fprintf(fp, "%u,\t", *(val++)); \ + } \ + } \ + fprintf(fp, "\t\t]\n\t},\n"); \ + } while (0) + +#define FPRINTF_TBL(data_tbl) \ + do { \ + fprintf(fp, "\t\"%s\": {\n", name); \ + fprintf(fp, "\t\t\"length\": %u,\n", length); \ + fprintf(fp, "\t\t\"lut\": [\n"); \ + fprintf(fp, "\t\t\t"); \ + for (CVI_U32 i = 0 ; i < length; i++) { \ + if (i == length - 1) { \ + fprintf(fp, "%u\n", data_tbl[i]); \ + } else if (i % 16 == 15) { \ + fprintf(fp, "%u,\n\t\t\t", data_tbl[i]);\ + } else { \ + fprintf(fp, "%u,\t", data_tbl[i]); \ + } \ + } \ + fprintf(fp, "\t\t]\n\t},\n"); \ + } while (0) + +#define DUMP_LUT_BASE(data_tbl, data_mask, r_addr, r_trig, r_data) \ + do { \ + for (CVI_U32 i = 0 ; i < length; i++) { \ + val = vaddr + r_addr; \ + *val = i; \ + usleep(1); \ + \ + val = vaddr + r_trig; \ + data = (*val | (0x1 << 31)); \ + *val = data; \ + usleep(1); \ + \ + val = vaddr + r_data; \ + data = *val; \ + data_tbl[i] = (data & data_mask); \ + } \ + } while (0) + +#define DUMP_LUT_COMMON(data_tbl, data_mask, sw_mode, r_addr, r_trig, r_data) \ + do { \ + val = vaddr + sw_mode; \ + data = 0x1; \ + *val = data; \ + \ + DUMP_LUT_BASE(data_tbl, data_mask, r_addr, r_trig, r_data); \ + \ + val = vaddr + sw_mode; \ + data = 0x0; \ + *val = data; \ + } while (0) + +struct reg_tbl { + int addr_ofs; + int val_ofs; + int data; + int mask; +}; + +struct gamma_tbl { + enum IP_INFO_GRP ip_info_id; + char name[16]; + int length; + struct reg_tbl enable; + struct reg_tbl shdw_sel; + struct reg_tbl force_clk_enable; + struct reg_tbl prog_en; + struct reg_tbl raddr; + struct reg_tbl rdata_r; + struct reg_tbl rdata_gb; +}; + +static void _dump_gamma_table(FILE *fp, struct ip_info *ip_info_list, struct gamma_tbl *tbl) +{ + CVI_U32 paddr; + CVI_U32 size; + CVI_VOID *vaddr; + CVI_U32 *val; + + CVI_U32 length = tbl->length; + CVI_U32 data; + CVI_CHAR name[32]; + + CVI_U32 *data_gamma_r = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_g = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_b = calloc(1, sizeof(CVI_U32) * length); + + GET_BASE_VADDR(tbl->ip_info_id); + GET_REGISTER_COMMON(tbl->enable.addr_ofs, tbl->enable.val_ofs, tbl->enable.data); + GET_REGISTER_COMMON(tbl->shdw_sel.addr_ofs, tbl->shdw_sel.val_ofs, tbl->shdw_sel.data); + GET_REGISTER_COMMON(tbl->force_clk_enable.addr_ofs, tbl->force_clk_enable.val_ofs, tbl->force_clk_enable.data); + +#ifdef __SOC_MARS__ + //for 181x need read register at postraw done + CVI_U32 timeOut = 500; + CVI_U32 s32Ret = CVI_SUCCESS; + + s32Ret = CVI_ISP_GetVDTimeOut(0, ISP_VD_BE_END, timeOut); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_LOG(CVI_DBG_ERR, "wait Vd time out. s32Ret: %#x\n", s32Ret); + } +#endif + + SET_REGISTER_COMMON(tbl->enable.addr_ofs, tbl->enable.val_ofs, 0); + // SET_REGISTER_COMMON(tbl->shdw_sel.addr_ofs, tbl->shdw_sel.val_ofs, 0); + SET_REGISTER_COMMON(tbl->force_clk_enable.addr_ofs, tbl->force_clk_enable.val_ofs, 0); + WAIT_IP_DISABLE(tbl->enable.addr_ofs, tbl->enable.val_ofs); + SET_REGISTER_COMMON(tbl->prog_en.addr_ofs, tbl->prog_en.val_ofs, 1); +#ifdef __SOC_PHOBOS__ + if (tbl->ip_info_id == IP_INFO_ID_RGBGAMMA || + tbl->ip_info_id == IP_INFO_ID_YGAMMA || + tbl->ip_info_id == IP_INFO_ID_DCI) { + CVI_U8 r_sel = 0; + + GET_REGISTER_COMMON(tbl->prog_en.addr_ofs, 4, r_sel); + CVI_TRACE_VI(CVI_DBG_INFO, "mem[%d] work, mem[%d] IDLE\n", r_sel, r_sel ^ 0x1); + SET_REGISTER_COMMON(tbl->raddr.addr_ofs, tbl->raddr.val_ofs, r_sel ^ 0x1); + } +#endif + + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + tbl->raddr.addr_ofs; + data = (*val & (~tbl->raddr.mask)) | i; + *val = data; + + val = vaddr + tbl->rdata_r.addr_ofs; + data = (*val | (0x1 << tbl->rdata_r.val_ofs)); + *val = data; + + val = vaddr + tbl->rdata_r.addr_ofs; + data = *val; + data_gamma_r[i] = (data & tbl->rdata_r.mask); + + val = vaddr + tbl->rdata_gb.addr_ofs; + data = *val; + data_gamma_g[i] = (data & tbl->rdata_gb.mask); + data_gamma_b[i] = ((data >> tbl->rdata_gb.val_ofs) & tbl->rdata_gb.mask); + } + + SET_REGISTER_COMMON(tbl->prog_en.addr_ofs, tbl->prog_en.val_ofs, 0); + SET_REGISTER_COMMON(tbl->force_clk_enable.addr_ofs, tbl->force_clk_enable.val_ofs, tbl->force_clk_enable.data); + SET_REGISTER_COMMON(tbl->shdw_sel.addr_ofs, tbl->shdw_sel.val_ofs, tbl->shdw_sel.data); + SET_REGISTER_COMMON(tbl->enable.addr_ofs, tbl->enable.val_ofs, tbl->enable.data); + + memset(name, 0, sizeof(name)); + strcat(strcat(name, tbl->name), "_r"); + FPRINTF_TBL(data_gamma_r); + + memset(name, 0, sizeof(name)); + strcat(strcat(name, tbl->name), "_g"); + FPRINTF_TBL(data_gamma_g); + + memset(name, 0, sizeof(name)); + strcat(strcat(name, tbl->name), "_b"); + FPRINTF_TBL(data_gamma_b); + + CVI_SYS_Munmap(vaddr, size); + free(data_gamma_r); + free(data_gamma_g); + free(data_gamma_b); +} + +CVI_S32 dump_register_182x(VI_PIPE ViPipe, FILE *fp, VI_DUMP_REGISTER_TABLE_S *pstRegTbl) +{ + VDEV_CLOSED_CHK(VDEV_TYPE_ISP, ViPipe); + CHECK_VI_NULL_PTR(fp); + CHECK_VI_NULL_PTR(pstRegTbl); + +#ifdef ARCH_CV182X + CVI_S32 s32Ret = CVI_SUCCESS; + struct ip_info *ip_info_list; + struct isp_tuning_cfg *tun_buf_info; + + ip_info_list = calloc(1, sizeof(struct ip_info) * IP_INFO_ID_MAX); + tun_buf_info = calloc(1, sizeof(struct isp_tuning_cfg)); + + CVI_U32 paddr; + CVI_U32 size; + CVI_VOID *vaddr; + CVI_U32 *val; + + CVI_U32 ip_info_id; + CVI_U32 offset; + CVI_U32 length; + CVI_U32 data; + CVI_CHAR name[32]; + + s32Ret = vi_get_ip_dump_list(d->fd, ip_info_list); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_ip_dump_list ioctl\n"); + free(tun_buf_info); + free(ip_info_list); + return s32Ret; + } + + s32Ret = vi_get_tun_addr(d->fd, tun_buf_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_tun_addr ioctl\n"); + free(tun_buf_info); + free(ip_info_list); + return s32Ret; + } + + /* stop tuning update */ + if (ViPipe == 0) { + system("echo 1,1,1,1 > /sys/module/cv182x_vip/parameters/tuning_dis"); + } else if (ViPipe == 1) { + system("echo 2,1,1,1 > /sys/module/cv182x_vip/parameters/tuning_dis"); + } + /* In the worst case, have to wait two frames to stop tuning update. */ + usleep(80 * 1000); + /* start of file */ + fprintf(fp, "{\n"); + /* dump isp moudle register */ + for (CVI_U32 i = 0; i < IP_INFO_ID_MAX; i++) { + GET_BASE_VADDR(i); + val = vaddr; + + fprintf(fp, "\t\"0x%08X\": {\n", paddr); + for (CVI_U32 j = 0 ; j < (size / 0x4); j++) { + fprintf(fp, "\t\t\"h%02x\": %u,\n", (j * 4), *(val++)); + } + + // if (i != IP_INFO_ID_MAX - 1) + fprintf(fp, "\t\t\"size\": %u\n\t},\n", size); + // else + // fprintf(fp, "\t\t\"size\": %u\n\t}\n", size); + + CVI_SYS_Munmap(vaddr, size); + } + + /* dump look up table */ + struct cvi_vip_isp_fe_cfg *fe_addr; + struct cvi_vip_isp_be_cfg *be_addr; + struct cvi_vip_isp_post_cfg *post_addr; + + tun_buf_info->fe_vir[ViPipe] = + CVI_SYS_Mmap(tun_buf_info->fe_addr[ViPipe], sizeof(struct cvi_vip_isp_fe_cfg)); + tun_buf_info->be_vir[ViPipe] = + CVI_SYS_Mmap(tun_buf_info->be_addr[ViPipe], sizeof(struct cvi_vip_isp_be_cfg)); + tun_buf_info->post_vir[ViPipe] = + CVI_SYS_Mmap(tun_buf_info->post_addr[ViPipe], sizeof(struct cvi_vip_isp_post_cfg)); + fe_addr = (struct cvi_vip_isp_fe_cfg *)(tun_buf_info->fe_vir[ViPipe]); + be_addr = (struct cvi_vip_isp_be_cfg *)(tun_buf_info->be_vir[ViPipe]); + post_addr = (struct cvi_vip_isp_post_cfg *)(tun_buf_info->post_vir[ViPipe]); + + // LSCR_FE + // 182x lscr hardware limitation: only read even index + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "LSCR_FE\n"); + struct cvi_vip_isp_lscr_config *pre_fe_rlsc_cfg[2] = { + (struct cvi_vip_isp_lscr_config *)&(fe_addr->tun_cfg[0].lscr_cfg[0]), + (struct cvi_vip_isp_lscr_config *)&(fe_addr->tun_cfg[0].lscr_cfg[1]) + }; + + length = 32; + snprintf(name, sizeof(name), "lscr_fe_le_gain_lut"); + FPRINTF_TBL(pre_fe_rlsc_cfg[0]->gain_lut); + + snprintf(name, sizeof(name), "lscr_fe_le_gain_lut_ir"); + FPRINTF_TBL(pre_fe_rlsc_cfg[0]->gain_lut_ir); + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + snprintf(name, sizeof(name), "lscr_fe_se_gain_lut"); + FPRINTF_TBL(pre_fe_rlsc_cfg[1]->gain_lut); + + snprintf(name, sizeof(name), "lscr_fe_se_gain_lut_ir"); + FPRINTF_TBL(pre_fe_rlsc_cfg[1]->gain_lut_ir); + } + } + + // FPN + // register is write only + // use the fixed value + { + CVI_TRACE_VI(CVI_DBG_INFO, "FPN\n"); + length = 256; + CVI_U32 *data_offset = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gain = calloc(1, sizeof(CVI_U32) * length); + + for (CVI_U32 i = 0 ; i < length; i++) { + data = 200 + i * 4; + data_offset[i] = data; + data_gain[i] = data; + } + + snprintf(name, sizeof(name), "fpn_data_offset"); + FPRINTF_TBL(data_offset); + + snprintf(name, sizeof(name), "fpn_data_gain"); + FPRINTF_TBL(data_gain); + + free(data_offset); + free(data_gain); + } + + // IR_PREPROC + { + CVI_TRACE_VI(CVI_DBG_INFO, "IR_PRE_PROC_LE\n"); + ip_info_id = IP_INFO_ID_IR_PRE_PROC_LE; + GET_BASE_VADDR(ip_info_id); + + length = 128; + CVI_U32 *data_lut_r = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_lut_g = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_lut_b = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_lut_w = calloc(1, sizeof(CVI_U32) * length); + + SET_SW_MODE_ENABLE(0x04, 8, 1); + SET_SW_MODE_MEM_SEL(0x10, 8, 1); + // 0: ratio lut R, 1: ratio lut G, 2: ratio lut B, 3: w lut + for (CVI_U32 j = 0 ; j < 4; j++) { + CVI_U32 *data_lut; + + if (j == 0) { + data_lut = data_lut_r; + } else if (j == 1) { + data_lut = data_lut_g; + } else if (j == 2) { + data_lut = data_lut_b; + } else if (j == 3) { + data_lut = data_lut_w; + } + + val = vaddr + 0x04; + data = (*val & ~(0x3 << 16)); + *val = (data | (j << 16)); + + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x10; + data = (*val & (~0x3F)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x14; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x14; + data = *val; + data_lut[i] = (data & 0x3FFF); + } + } + SET_SW_MODE_ENABLE(0x04, 8, 0); + + snprintf(name, sizeof(name), "ir_preproc_le_r"); + FPRINTF_TBL(data_lut_r); + + snprintf(name, sizeof(name), "ir_preproc_le_g"); + FPRINTF_TBL(data_lut_g); + + snprintf(name, sizeof(name), "ir_preproc_le_b"); + FPRINTF_TBL(data_lut_b); + + snprintf(name, sizeof(name), "ir_preproc_le_w"); + FPRINTF_TBL(data_lut_w); + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + CVI_TRACE_VI(CVI_DBG_INFO, "IR_PRE_PROC_SE\n"); + ip_info_id = IP_INFO_ID_IR_PRE_PROC_SE; + GET_BASE_VADDR(ip_info_id); + + SET_SW_MODE_ENABLE(0x04, 8, 1); + SET_SW_MODE_MEM_SEL(0x10, 8, 1); + for (CVI_U32 j = 0 ; j < 4; j++) { + CVI_U32 *data_lut; + + if (j == 0) { + data_lut = data_lut_r; + } else if (j == 1) { + data_lut = data_lut_g; + } else if (j == 2) { + data_lut = data_lut_b; + } else if (j == 3) { + data_lut = data_lut_w; + } + + val = vaddr + 0x04; + data = (*val & ~(0x3 << 16)); + *val = (data | (j << 16)); + + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x10; + data = (*val & (~0x3F)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x14; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x14; + data = *val; + data_lut[i] = (data & 0x3FFF); + } + } + SET_SW_MODE_ENABLE(0x04, 8, 0); + + snprintf(name, sizeof(name), "ir_preproc_se_r"); + FPRINTF_TBL(data_lut_r); + + snprintf(name, sizeof(name), "ir_preproc_se_g"); + FPRINTF_TBL(data_lut_g); + + snprintf(name, sizeof(name), "ir_preproc_se_b"); + FPRINTF_TBL(data_lut_b); + + snprintf(name, sizeof(name), "ir_preproc_se_w"); + FPRINTF_TBL(data_lut_w); + } + + free(data_lut_r); + free(data_lut_g); + free(data_lut_b); + free(data_lut_w); + } + + // IR_WDMA_PROC + { + CVI_TRACE_VI(CVI_DBG_INFO, "IR_PROC\n"); + ip_info_id = IP_INFO_ID_IR_PROC; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 *data_gamma_curve = calloc(1, sizeof(CVI_U32) * length); + + DUMP_LUT_COMMON(data_gamma_curve, 0xFF, 0x14, 0x18, 0x1C, 0x1C); + snprintf(name, sizeof(name), "ir_wdma_proc"); + FPRINTF_TBL(data_gamma_curve); + + free(data_gamma_curve); + } + + // AF_GAMMA + // 182x has no af gamma + + // DPC + { + CVI_TRACE_VI(CVI_DBG_INFO, "DPC_LE\n"); + ip_info_id = IP_INFO_ID_DPC0; + GET_BASE_VADDR(ip_info_id); + + length = 2047; + CVI_U32 *data_dpc = calloc(1, sizeof(CVI_U32) * length); + + val = vaddr + 0x08; + data = *val & (~(0x3 << 2)); + *val = data; + + SET_SW_MODE_ENABLE(0x44, 31, 1); + DUMP_LUT_BASE(data_dpc, 0xFFFFFF, 0x48, 0x4C, 0x4C); + SET_SW_MODE_ENABLE(0x44, 31, 0); + + snprintf(name, sizeof(name), "dpc_le_bp_tbl"); + FPRINTF_TBL(data_dpc); + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + CVI_TRACE_VI(CVI_DBG_INFO, "DPC_SE\n"); + ip_info_id = IP_INFO_ID_DPC1; + GET_BASE_VADDR(ip_info_id); + + val = vaddr + 0x08; + data = *val & (~(0x3 << 2)); + *val = data; + + SET_SW_MODE_ENABLE(0x44, 31, 1); + DUMP_LUT_BASE(data_dpc, 0xFFFFFF, 0x48, 0x4C, 0x4C); + SET_SW_MODE_ENABLE(0x44, 31, 0); + + snprintf(name, sizeof(name), "dpc_se_bp_tbl"); + FPRINTF_TBL(data_dpc); + } + + free(data_dpc); + } + + // LSCR_BE + // 182x lscr hardware limitation: only read even index + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "LSCR_BE_LE\n"); + struct cvi_vip_isp_lscr_config *pre_be_rlsc_cfg[2] = { + (struct cvi_vip_isp_lscr_config *)&(be_addr->tun_cfg[0].lscr_cfg[0]), + (struct cvi_vip_isp_lscr_config *)&(be_addr->tun_cfg[0].lscr_cfg[1]) + }; + + length = 32; + snprintf(name, sizeof(name), "lscr_be_le_gain_lut_r"); + FPRINTF_TBL(pre_be_rlsc_cfg[0]->gain_lut); + + snprintf(name, sizeof(name), "lscr_be_le_gain_lut_g"); + FPRINTF_TBL(pre_be_rlsc_cfg[0]->gain_lut1); + + snprintf(name, sizeof(name), "lscr_be_le_gain_lut_b"); + FPRINTF_TBL(pre_be_rlsc_cfg[0]->gain_lut2); + + snprintf(name, sizeof(name), "lscr_be_le_gain_lut_ir"); + FPRINTF_TBL(pre_be_rlsc_cfg[0]->gain_lut_ir); + + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + CVI_TRACE_VI(CVI_DBG_INFO, "LSCR_BE_SE\n"); + snprintf(name, sizeof(name), "lscr_be_se_gain_lut_r"); + FPRINTF_TBL(pre_be_rlsc_cfg[1]->gain_lut); + + snprintf(name, sizeof(name), "lscr_be_se_gain_lut_g"); + FPRINTF_TBL(pre_be_rlsc_cfg[1]->gain_lut1); + + snprintf(name, sizeof(name), "lscr_be_se_gain_lut_b"); + FPRINTF_TBL(pre_be_rlsc_cfg[1]->gain_lut2); + + snprintf(name, sizeof(name), "lscr_be_se_gain_lut_ir"); + FPRINTF_TBL(pre_be_rlsc_cfg[1]->gain_lut_ir); + } + } + + // BNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "BNR\n"); + ip_info_id = IP_INFO_ID_BNR; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 8; + offset = 0x148; + snprintf(name, sizeof(name), "bnr_intensity_sel"); + FPRINTF_VAL(); + + length = 256; + offset = 0x228; + snprintf(name, sizeof(name), "bnr_weight_lut"); + FPRINTF_VAL(); + + length = 32; + offset = 0x424; + snprintf(name, sizeof(name), "bnr_lsc_gain_lut"); + FPRINTF_VAL(); + } + + // CA_CP + { + CVI_TRACE_VI(CVI_DBG_INFO, "CA_CP\n"); + ip_info_id = IP_INFO_ID_RGBTOP; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 *data_ca_cp = calloc(1, sizeof(CVI_U32) * length); + + SET_SW_MODE_ENABLE(0x60, 3, 1); + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x58; + data = (*val & ~0xFF) | i; + *val = data; + usleep(1); + + val = vaddr + 0x58; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x5C; + data = *val; + data_ca_cp[i] = (data & 0xFFFFFF); + } + SET_SW_MODE_ENABLE(0x60, 3, 0); + + snprintf(name, sizeof(name), "ca_cp"); + FPRINTF_TBL(data_ca_cp); + + free(data_ca_cp); + } + + // MLSC + // NO INDIRECT LUT + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC\n"); + MLSC_GAIN_LUT_S *MlscGainLut = &pstRegTbl->MlscGainLut; + + length = 1369; + if (MlscGainLut->RGain && MlscGainLut->GGain && MlscGainLut->BGain) { + snprintf(name, sizeof(name), "mlsc_gain_r"); + FPRINTF_TBL(MlscGainLut->RGain); + + snprintf(name, sizeof(name), "mlsc_gain_g"); + FPRINTF_TBL(MlscGainLut->GGain); + + snprintf(name, sizeof(name), "mlsc_gain_b"); + FPRINTF_TBL(MlscGainLut->BGain); + } else { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC is no data\n"); + } + } + + // MANR + // register is write only + + // RGB_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "GAMMA\n"); + ip_info_id = IP_INFO_ID_GAMMA; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 *data_gamma_r = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_g = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_b = calloc(1, sizeof(CVI_U32) * length); + + SET_SW_MODE_ENABLE(0x4, 8, 1); + SET_SW_MODE_MEM_SEL(0x14, 12, 1); + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x14; + data = (*val & (~0xFF)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = *val; + data_gamma_r[i] = (data & 0xFFF); + + val = vaddr + 0x1C; + data = *val; + data_gamma_g[i] = (data & 0xFFF); + data_gamma_b[i] = ((data >> 16) & 0xFFF); + } + SET_SW_MODE_ENABLE(0x4, 8, 0); + + snprintf(name, sizeof(name), "gamma_r"); + FPRINTF_TBL(data_gamma_r); + + snprintf(name, sizeof(name), "gamma_g"); + FPRINTF_TBL(data_gamma_g); + + snprintf(name, sizeof(name), "gamma_b"); + FPRINTF_TBL(data_gamma_b); + + free(data_gamma_r); + free(data_gamma_g); + free(data_gamma_b); + } + + // CLUT + // There is a probability that the clut register will not be read + // used tuning buffer + { + #if 1 + CVI_TRACE_VI(CVI_DBG_INFO, "CLUT\n"); + struct cvi_vip_isp_clut_config *clut_cfg = + (struct cvi_vip_isp_clut_config *)&(post_addr->tun_cfg[0].clut_cfg); + + length = 4913; + snprintf(name, sizeof(name), "clut_r"); + FPRINTF_TBL(clut_cfg->r_lut); + + snprintf(name, sizeof(name), "clut_g"); + FPRINTF_TBL(clut_cfg->g_lut); + + snprintf(name, sizeof(name), "clut_b"); + FPRINTF_TBL(clut_cfg->b_lut); + #else + CVI_TRACE_VI(CVI_DBG_INFO, "CLUT\n"); + ip_info_id = IP_INFO_ID_CLUT; + GET_BASE_VADDR(ip_info_id); + + CVI_U32 r_idx = 17; + CVI_U32 g_idx = 17; + CVI_U32 b_idx = 17; + CVI_U32 rgb_idx = 0; + + length = r_idx * g_idx * b_idx; + CVI_U32 data_clut_r[length]; + CVI_U32 data_clut_g[length]; + CVI_U32 data_clut_b[length]; + + SET_SW_MODE_ENABLE(0x0, 0, 0); // reg_clut_enable + SET_SW_MODE_ENABLE(0x0, 1, 0); // reg_clut_shdw_sel + + do { + usleep(10); + val = vaddr + 0x00; + data = *val; + } while ((data & 0x1) != 0); + + SET_SW_MODE_ENABLE(0x0, 3, 1); // reg_prog_en + + for (CVI_U32 i = 0 ; i < b_idx; i++) { + for (CVI_U32 j = 0 ; j < g_idx; j++) { + for (CVI_U32 k = 0 ; k < r_idx; k++) { + rgb_idx = i * g_idx * r_idx + j * r_idx + k; + + val = vaddr + 0x04; // reg_sram_r_idx/reg_sram_g_idx/reg_sram_b_idx + data = (i << 16) | (j << 8) | k; + *val = data; + usleep(1); + + val = vaddr + 0x0C; // reg_sram_rd + data = (0x1 << 31); + *val = data; + usleep(1); + + val = vaddr + 0x0C; // reg_sram_rdata + data = *val; + usleep(1); + + data_clut_r[rgb_idx] = (data >> 20) & 0x3FF; + data_clut_g[rgb_idx] = (data >> 10) & 0x3FF; + data_clut_b[rgb_idx] = data & 0x3FF; + } + } + } + + SET_SW_MODE_ENABLE(0x0, 3, 0); // reg_prog_en + SET_SW_MODE_ENABLE(0x0, 1, 1); // reg_clut_shdw_sel + + snprintf(name, sizeof(name), "clut_r"); + FPRINTF_TBL(data_clut_r); + + snprintf(name, sizeof(name), "clut_g"); + FPRINTF_TBL(data_clut_g); + + snprintf(name, sizeof(name), "clut_b"); + FPRINTF_TBL(data_clut_b); + #endif + } + + // DCI_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "DCI_GAMMA\n"); + ip_info_id = IP_INFO_ID_DCI; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 *data_gamma_r = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_g = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_gamma_b = calloc(1, sizeof(CVI_U32) * length); + + SET_SW_MODE_ENABLE(0x204, 8, 1); + SET_SW_MODE_MEM_SEL(0x214, 12, 1); + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x214; + data = (*val & (~0xFF)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x218; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x218; + data = *val; + data_gamma_r[i] = (data & 0xFFF); + + val = vaddr + 0x21C; + data = *val; + data_gamma_g[i] = (data & 0xFFF); + data_gamma_b[i] = ((data >> 16) & 0xFFF); + } + SET_SW_MODE_ENABLE(0x204, 8, 0); + + snprintf(name, sizeof(name), "dci_gamma_r"); + FPRINTF_TBL(data_gamma_r); + + snprintf(name, sizeof(name), "dci_gamma_g"); + FPRINTF_TBL(data_gamma_g); + + snprintf(name, sizeof(name), "dci_gamma_b"); + FPRINTF_TBL(data_gamma_b); + + free(data_gamma_r); + free(data_gamma_g); + free(data_gamma_b); + } + + // LTM + { + CVI_TRACE_VI(CVI_DBG_INFO, "LTM\n"); + ip_info_id = IP_INFO_ID_HDRLTM; + GET_BASE_VADDR(ip_info_id); + + length = 257; + CVI_U32 *data_dtone_curve = calloc(1, sizeof(CVI_U32) * length); + + DUMP_LUT_COMMON(data_dtone_curve, 0xFFF, 0xF0, 0xF4, 0xF8, 0xF8); + val = vaddr + 0xe8; //reg_dtone_curve_max + data_dtone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_dtone_curve"); + FPRINTF_TBL(data_dtone_curve); + + length = 513; + CVI_U32 *data_btone_curve = calloc(1, sizeof(CVI_U32) * length); + + DUMP_LUT_COMMON(data_btone_curve, 0xFFF, 0x110, 0x114, 0x118, 0x118); + val = vaddr + 0x108; //reg_btone_curve_max + data_btone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_btone_curve"); + FPRINTF_TBL(data_btone_curve); + + length = 769; + CVI_U32 *data_global_curve = calloc(1, sizeof(CVI_U32) * length); + + DUMP_LUT_COMMON(data_global_curve, 0xFFF, 0x130, 0x134, 0x138, 0x138); + val = vaddr + 0x128; //reg_global_curve_max + data_global_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_global_curve"); + FPRINTF_TBL(data_global_curve); + + free(data_dtone_curve); + free(data_btone_curve); + free(data_global_curve); + } + + // YNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "YNR\n"); + ip_info_id = IP_INFO_ID_YNR; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 6; + offset = 0x100; + snprintf(name, sizeof(name), "ynr_ns0_luma_th"); + FPRINTF_VAL(); + + length = 5; + offset = 0x104; + snprintf(name, sizeof(name), "ynr_ns0_slope"); + FPRINTF_VAL(); + + length = 6; + offset = 0x108; + snprintf(name, sizeof(name), "ynr_ns0_offset"); + FPRINTF_VAL(); + + length = 6; + offset = 0x110; + snprintf(name, sizeof(name), "ynr_ns1_luma_th"); + FPRINTF_VAL(); + + length = 5; + offset = 0x114; + snprintf(name, sizeof(name), "ynr_ns1_slope"); + FPRINTF_VAL(); + + length = 6; + offset = 0x118; + snprintf(name, sizeof(name), "ynr_ns1_offset"); + FPRINTF_VAL(); + + length = 8; + offset = 0x134; + snprintf(name, sizeof(name), "ynr_intensity_sel"); + FPRINTF_VAL(); + + length = 16; + offset = 0x138; + snprintf(name, sizeof(name), "ynr_motion_lut"); + FPRINTF_VAL(); + + length = 64; + offset = 0x228; + snprintf(name, sizeof(name), "ynr_weight_lut"); + FPRINTF_VAL(); + + length = 16; + offset = 0x260; + snprintf(name, sizeof(name), "ynr_res_mot_lut"); + FPRINTF_VAL(); + } + + // YCURVE + { + CVI_TRACE_VI(CVI_DBG_INFO, "YCURVE\n"); + ip_info_id = IP_INFO_ID_YCURVE; + GET_BASE_VADDR(ip_info_id); + + length = 64; + CVI_U32 *data_ycurve = calloc(1, sizeof(CVI_U32) * length); + + SET_SW_MODE_ENABLE(0x4, 8, 1); + SET_SW_MODE_MEM_SEL(0x14, 8, 1); + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x14; + data = (*val & ~(0x3F)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = *val; + data_ycurve[i] = (data & 0xFF); + } + SET_SW_MODE_ENABLE(0x4, 8, 0); + + snprintf(name, sizeof(name), "ycurve"); + FPRINTF_TBL(data_ycurve); + + free(data_ycurve); + } + + /* end of file */ + fprintf(fp, "\t\"end\": {}\n"); + fprintf(fp, "}"); + /* start tuning update */ + system("echo 0,0,0,0 > /sys/module/cv182x_vip/parameters/tuning_dis"); + + free(tun_buf_info); + free(ip_info_list); +#endif + return CVI_SUCCESS; +} + +CVI_S32 dump_register_183x(VI_PIPE ViPipe, FILE *fp, VI_DUMP_REGISTER_TABLE_S *pstRegTbl) +{ + VDEV_CLOSED_CHK(VDEV_TYPE_ISP, ViPipe); + CHECK_VI_NULL_PTR(fp); + CHECK_VI_NULL_PTR(pstRegTbl); + +#ifdef ARCH_CV183X + CVI_S32 s32Ret = CVI_SUCCESS; + struct ip_info ip_info_list[IP_INFO_ID_MAX]; + struct isp_tuning_cfg tun_buf_info; + + CVI_U32 paddr; + CVI_U32 size; + CVI_VOID *vaddr; + CVI_U32 *val; + + CVI_U32 ip_info_id; + CVI_U32 offset; + CVI_U32 length; + CVI_U32 data; + CVI_CHAR name[32]; + + s32Ret = vi_get_ip_dump_list(d->fd, ip_info_list); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_ip_dump_list ioctl\n"); + return CVI_FAILURE; + } + + memset(&tun_buf_info, 0, sizeof(struct isp_tuning_cfg)); + s32Ret = vi_get_tun_addr(d->fd, &tun_buf_info); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_tun_addr ioctl\n"); + return CVI_FAILURE; + } + + /* stop tuning update */ + if (ViPipe == 0) { + system("echo 1,1,1 > /sys/module/cv183x_vip/parameters/tuning_dis"); + } else if (ViPipe == 1) { + system("echo 2,1,1 > /sys/module/cv183x_vip/parameters/tuning_dis"); + } + /* In the worst case, have to wait two frames to stop tuning update. */ + usleep(80 * 1000); + /* start of file */ + fprintf(fp, "{\n"); + /* dump isp moudle register */ + for (CVI_U32 i = 0; i < IP_INFO_ID_MAX; i++) { + GET_BASE_VADDR(i); + val = vaddr; + + fprintf(fp, "\t\"0x%08X\": {\n", paddr); + for (CVI_U32 j = 0 ; j < (size / 0x4); j++) { + fprintf(fp, "\t\t\"h%02x\": %u,\n", (j * 4), *(val++)); + } + + // if (i != IP_INFO_ID_MAX - 1) + fprintf(fp, "\t\t\"size\": %u\n\t},\n", size); + // else + // fprintf(fp, "\t\t\"size\": %u\n\t}\n", size); + + CVI_SYS_Munmap(vaddr, size); + } + + /* dump look up table */ + // struct cvi_vip_isp_pre_cfg *pre_addr; + struct cvi_vip_isp_post_cfg *post_addr; + + tun_buf_info.pre_vir[ViPipe] = + CVI_SYS_Mmap(tun_buf_info.pre_addr[ViPipe], sizeof(struct cvi_vip_isp_pre_cfg)); + tun_buf_info.post_vir[ViPipe] = + CVI_SYS_Mmap(tun_buf_info.post_addr[ViPipe], sizeof(struct cvi_vip_isp_post_cfg)); + // pre_addr = (struct cvi_vip_isp_pre_cfg *)(tun_buf_info.pre_vir[ViPipe]); + post_addr = (struct cvi_vip_isp_post_cfg *)(tun_buf_info.post_vir[ViPipe]); + + // LSCR + { + CVI_TRACE_VI(CVI_DBG_INFO, "LSCR_LE\n"); + ip_info_id = (ViPipe == 0) ? IP_INFO_ID_LSCR0 : IP_INFO_ID_LSCR2_R1; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 32; + offset = 0x114; + snprintf(name, sizeof(name), "lscr_le_lsc_lut"); + FPRINTF_VAL(); + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + CVI_TRACE_VI(CVI_DBG_INFO, "LSCR_SE\n"); + ip_info_id = (ViPipe == 0) ? IP_INFO_ID_LSCR1 : IP_INFO_ID_LSCR3_R1; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 32; + offset = 0x114; + snprintf(name, sizeof(name), "lscr_se_lsc_lut"); + FPRINTF_VAL(); + } + } + + // AF_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "AF_GAMMA\n"); + ip_info_id = (ViPipe == 0) ? IP_INFO_ID_AF_GAMMA : IP_INFO_ID_AF_GAMMA_R1; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 data_af_gamma[length]; + + SET_SW_MODE_ENABLE(0x10, 0, 1); + SET_SW_MODE_MEM_SEL(0x10, 4, 1); + DUMP_LUT_BASE(data_af_gamma, 0xFF, 0x14, 0x18, 0x18); + SET_SW_MODE_ENABLE(0x10, 0, 0); + + snprintf(name, sizeof(name), "af_gamma"); + FPRINTF_TBL(data_af_gamma); + } + + // DPC + { + CVI_TRACE_VI(CVI_DBG_INFO, "DPC_LE\n"); + ip_info_id = IP_INFO_ID_DPC0; + GET_BASE_VADDR(ip_info_id); + + length = 4096; + CVI_U32 data_dpc[length]; + + val = vaddr + 0x08; // reg_dpc_staticbpc_enable + data = *val & (~(0x3 << 2)); + *val = data; + + SET_SW_MODE_ENABLE(0x44, 31, 1); + DUMP_LUT_BASE(data_dpc, 0xFFFFFF, 0x48, 0x4C, 0x4C); + SET_SW_MODE_ENABLE(0x44, 31, 0); + + val = vaddr + 0x08; + data = *val | (0x3 << 2); + *val = data; + + snprintf(name, sizeof(name), "dpc_le_bp_tbl"); + FPRINTF_TBL(data_dpc); + + if (vi_ctx.devAttr[ViPipe].stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) { + CVI_TRACE_VI(CVI_DBG_INFO, "DPC_SE\n"); + ip_info_id = IP_INFO_ID_DPC1; + GET_BASE_VADDR(ip_info_id); + + val = vaddr + 0x08; + data = *val & (~(0x3 << 2)); + *val = data; + + SET_SW_MODE_ENABLE(0x44, 31, 1); + DUMP_LUT_BASE(data_dpc, 0xFFFFFF, 0x48, 0x4C, 0x4C); + SET_SW_MODE_ENABLE(0x44, 31, 0); + + val = vaddr + 0x08; + data = *val | (0x3 << 2); + *val = data; + + snprintf(name, sizeof(name), "dpc_se_bp_tbl"); + FPRINTF_TBL(data_dpc); + } + } + + // MLSC + // NO INDIRECT LUT + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC\n"); + MLSC_GAIN_LUT_S *MlscGainLut = &pstRegTbl->MlscGainLut; + + length = 1369; + if (MlscGainLut->RGain && MlscGainLut->GGain && MlscGainLut->BGain) { + snprintf(name, sizeof(name), "mlsc_gain_r"); + FPRINTF_TBL(MlscGainLut->RGain); + + snprintf(name, sizeof(name), "mlsc_gain_g"); + FPRINTF_TBL(MlscGainLut->GGain); + + snprintf(name, sizeof(name), "mlsc_gain_b"); + FPRINTF_TBL(MlscGainLut->BGain); + } else { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC is no data\n"); + } + } + + // LTM + { + CVI_TRACE_VI(CVI_DBG_INFO, "LTM\n"); + ip_info_id = IP_INFO_ID_HDRLTM; + GET_BASE_VADDR(ip_info_id); + + length = 257; + CVI_U32 data_dtone_curve[length]; + + DUMP_LUT_COMMON(data_dtone_curve, 0xFFF, 0xF0, 0xF4, 0xF8, 0xF8); + val = vaddr + 0xe8; //reg_dtone_curve_max + data_dtone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_dtone_curve"); + FPRINTF_TBL(data_dtone_curve); + + length = 513; + CVI_U32 data_btone_curve[length]; + + DUMP_LUT_COMMON(data_btone_curve, 0xFFF, 0x110, 0x114, 0x118, 0x118); + val = vaddr + 0x108; //reg_btone_curve_max + data_btone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_btone_curve"); + FPRINTF_TBL(data_btone_curve); + + length = 769; + CVI_U32 data_global_curve[length]; + + DUMP_LUT_COMMON(data_global_curve, 0xFFF, 0x130, 0x134, 0x138, 0x138); + val = vaddr + 0x128; //reg_global_curve_max + data_global_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_global_curve"); + FPRINTF_TBL(data_global_curve); + } + + // BNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "BNR\n"); + ip_info_id = IP_INFO_ID_BNR; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 8; + offset = 0x148; + snprintf(name, sizeof(name), "bnr_intensity_sel"); + FPRINTF_VAL(); + + length = 256; + offset = 0x228; + snprintf(name, sizeof(name), "bnr_weight_lut"); + FPRINTF_VAL(); + + length = 32; + offset = 0x424; + snprintf(name, sizeof(name), "bnr_lsc_gain_lut"); + FPRINTF_VAL(); + } + // MANR + // register is write only + + // FPN + // register is write only + // use the fixed value + { + CVI_TRACE_VI(CVI_DBG_INFO, "FPN\n"); + length = 256; + CVI_U32 data_offset[length]; + CVI_U32 data_gain[length]; + + for (CVI_U32 i = 0 ; i < length; i++) { + data_offset[i] = i * 4; + data_gain[i] = 1024; + } + + snprintf(name, sizeof(name), "fpn_data_offset"); + FPRINTF_TBL(data_offset); + + snprintf(name, sizeof(name), "fpn_data_gain"); + FPRINTF_TBL(data_gain); + } + + // RGB_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "GAMMA\n"); + ip_info_id = IP_INFO_ID_GAMMA; + GET_BASE_VADDR(ip_info_id); + + length = 256; + CVI_U32 data_gamma_r[length]; + CVI_U32 data_gamma_g[length]; + CVI_U32 data_gamma_b[length]; + + SET_SW_MODE_ENABLE(0x10, 0, 1); + SET_SW_MODE_MEM_SEL(0x10, 4, 1); + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x14; + *val = i; + + val = vaddr + 0x18; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = *val; + data_gamma_r[i] = (data & 0xFFF); + + val = vaddr + 0x1C; + data = *val; + data_gamma_g[i] = (data & 0xFFF); + data_gamma_b[i] = ((data >> 16) & 0xFFF); + } + SET_SW_MODE_ENABLE(0x10, 0, 0); + + snprintf(name, sizeof(name), "gamma_r"); + FPRINTF_TBL(data_gamma_r); + + snprintf(name, sizeof(name), "gamma_g"); + FPRINTF_TBL(data_gamma_g); + + snprintf(name, sizeof(name), "gamma_b"); + FPRINTF_TBL(data_gamma_b); + } + + // HSV + // register is write only + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "HSV\n"); + struct cvi_vip_isp_hsv_config *hsv_cfg = + (struct cvi_vip_isp_hsv_config *)&(post_addr->tun_cfg[0].hsv_cfg); + + length = 769; + snprintf(name, sizeof(name), "hsv_h_lut"); + FPRINTF_TBL(hsv_cfg->h_lut); + + length = 513; + snprintf(name, sizeof(name), "hsv_s_lut"); + FPRINTF_TBL(hsv_cfg->s_lut); + + length = 769; + snprintf(name, sizeof(name), "hsv_sgain_lut"); + FPRINTF_TBL(hsv_cfg->sgain_lut); + + length = 769; + snprintf(name, sizeof(name), "hsv_vgain_lut"); + FPRINTF_TBL(hsv_cfg->vgain_lut); + } + + // CLUT + // There is a probability that the clut register will not be read + // used tuning buffer + { + #if 1 + CVI_TRACE_VI(CVI_DBG_INFO, "CLUT\n"); + struct cvi_vip_isp_3dlut_config *thrdlut_cfg = + (struct cvi_vip_isp_3dlut_config *)&(post_addr->tun_cfg[0].thrdlut_cfg); + + length = 3276; + snprintf(name, sizeof(name), "clut_h"); + FPRINTF_TBL(thrdlut_cfg->h_lut); + + snprintf(name, sizeof(name), "clut_s"); + FPRINTF_TBL(thrdlut_cfg->s_lut); + + snprintf(name, sizeof(name), "clut_v"); + FPRINTF_TBL(thrdlut_cfg->v_lut); + #else + CVI_TRACE_VI(CVI_DBG_INFO, "CLUT\n"); + ip_info_id = IP_INFO_ID_YUVTOP; + GET_BASE_VADDR(ip_info_id); + + CVI_U32 h_idx = 28; + CVI_U32 s_idx = 13; + CVI_U32 v_idx = 9; + CVI_U32 hsv_idx = 0; + + length = h_idx * s_idx * v_idx; + CVI_U64 data_clut[length]; + + SET_SW_MODE_ENABLE(0x50, 0, 0); + + for (CVI_U32 i = 0 ; i < v_idx; i++) { + for (CVI_U32 j = 0 ; j < s_idx; j++) { + for (CVI_U32 k = 0 ; k < h_idx; k++) { + hsv_idx = i * s_idx * h_idx + j * h_idx + k; + + val = vaddr + 0x44; + data = (k << 2) | (j << 7) | (i << 11); + *val = data; + usleep(1); + + val = vaddr + 0x44; + data = (data | (0x1 << 16)); + *val = data; + usleep(1); + + val = vaddr + 0x48; // LSB + data = *val; + + val = vaddr + 0x4C; // MSB + data_clut[hsv_idx] = ((CVI_U64)(*val & 0x3) << 32) | data; + } + } + } + + SET_SW_MODE_ENABLE(0x50, 0, 1); + + fprintf(fp, "\t\"clut_hsv\": {\n"); + fprintf(fp, "\t\t\"length\": %u,\n", length); + fprintf(fp, "\t\t\"lut\": [\n"); + fprintf(fp, "\t\t\t"); + for (CVI_U32 i = 0 ; i < length; i++) { + if (i == length - 1) { + fprintf(fp, "%"PRIu64"\n", data_clut[i]); + } else if (i % 16 == 15) { + fprintf(fp, "%"PRIu64",\n\t\t\t", data_clut[i]); + } else { + fprintf(fp, "%"PRIu64",\t", data_clut[i]); + } + } + fprintf(fp, "\t\t]\n\t},\n"); + #endif + } + + // YNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "YNR\n"); + ip_info_id = IP_INFO_ID_YNR; + GET_BASE_VADDR(ip_info_id); + CLEAR_ACCESS_CNT(0x8); + + length = 6; + offset = 0x100; + snprintf(name, sizeof(name), "ynr_ns0_luma_th"); + FPRINTF_VAL(); + + length = 5; + offset = 0x104; + snprintf(name, sizeof(name), "ynr_ns0_slope"); + FPRINTF_VAL(); + + length = 6; + offset = 0x108; + snprintf(name, sizeof(name), "ynr_ns0_offset_th"); + FPRINTF_VAL(); + + length = 6; + offset = 0x110; + snprintf(name, sizeof(name), "ynr_ns1_luma_th"); + FPRINTF_VAL(); + + length = 5; + offset = 0x114; + snprintf(name, sizeof(name), "ynr_ns1_slope"); + FPRINTF_VAL(); + + length = 6; + offset = 0x118; + snprintf(name, sizeof(name), "ynr_ns1_offset_th"); + FPRINTF_VAL(); + + length = 8; + offset = 0x134; + snprintf(name, sizeof(name), "ynr_intensity_sel"); + FPRINTF_VAL(); + + length = 64; + offset = 0x228; + snprintf(name, sizeof(name), "ynr_weight_lut_h"); + FPRINTF_VAL(); + } + + // YCURVE + { + CVI_TRACE_VI(CVI_DBG_INFO, "YCURVE\n"); + ip_info_id = IP_INFO_ID_YCURVE; + GET_BASE_VADDR(ip_info_id); + + length = 64; + CVI_U32 data_ycurve[length]; + + SET_SW_MODE_ENABLE(0x10, 0, 1); + SET_SW_MODE_MEM_SEL(0x10, 4, 1); + DUMP_LUT_BASE(data_ycurve, 0xFF, 0x14, 0x18, 0x18); + SET_SW_MODE_ENABLE(0x10, 0, 0); + + snprintf(name, sizeof(name), "ycurve"); + FPRINTF_TBL(data_ycurve); + } + + // DCI + // NO INDIRECT LUT + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "DCI\n"); + struct cvi_vip_isp_dci_config *dci_cfg = + (struct cvi_vip_isp_dci_config *)&(post_addr->tun_cfg[0].dci_cfg); + + length = 256; + snprintf(name, sizeof(name), "dci_map_lut"); + FPRINTF_TBL(dci_cfg->map_lut); + } + + /* end of file */ + fprintf(fp, "\t\"end\": {}\n"); + fprintf(fp, "}"); + /* start tuning update */ + system("echo 0,0,0 > /sys/module/cv183x_vip/parameters/tuning_dis"); + +#endif + return CVI_SUCCESS; +} + +CVI_S32 dump_hw_register(VI_PIPE ViPipe, FILE *fp, VI_DUMP_REGISTER_TABLE_S *pstRegTbl) +{ + VDEV_CLOSED_CHK(VDEV_TYPE_ISP, ViPipe); + CHECK_VI_NULL_PTR(fp); + CHECK_VI_NULL_PTR(pstRegTbl); + +#if defined(__SOC_MARS__) || defined(__SOC_PHOBOS__) + CVI_S32 s32Ret = CVI_SUCCESS; + VI_DEV_ATTR_S stDevAttr; + struct ip_info *ip_info_list; + + ip_info_list = calloc(1, sizeof(struct ip_info) * IP_INFO_ID_MAX); + + CVI_U32 paddr; + CVI_U32 size; + CVI_VOID *vaddr; + CVI_U32 *val; + + CVI_U32 ip_info_id; + CVI_U32 offset; + CVI_U32 length; + CVI_U32 data; + CVI_CHAR name[32]; + + s32Ret = vi_sdk_get_dev_attr(d->fd, (int)ViPipe, &stDevAttr); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_sdk_get_dev_attr ioctl\n"); + free(ip_info_list); + return s32Ret; + } + + s32Ret = vi_get_ip_dump_list(d->fd, ip_info_list); + if (s32Ret != CVI_SUCCESS) { + CVI_TRACE_VI(CVI_DBG_ERR, "vi_get_ip_dump_list ioctl\n"); + free(ip_info_list); + return s32Ret; + } +#ifdef __SOC_MARS__ + /* stop tuning update */ + if (ViPipe == 0) { + system("echo 1,1,1,1 > /sys/module/cv181x_vi/parameters/tuning_dis"); + } else if (ViPipe == 1) { + system("echo 2,1,1,1 > /sys/module/cv181x_vi/parameters/tuning_dis"); + } +#else + /* stop tuning update */ + if (ViPipe == 0) { + system("echo 1,1,1,1 > /sys/module/cv180x_vi/parameters/tuning_dis"); + } +#endif + /* In the worst case, have to wait two frames to stop tuning update. */ + usleep(80 * 1000); + /* start of file */ + fprintf(fp, "{\n"); + /* dump isp moudle register */ + for (CVI_U32 i = 0; i < IP_INFO_ID_MAX; i++) { + CVI_TRACE_VI(CVI_DBG_INFO, "%d\n", i); + + GET_BASE_VADDR(i); + val = vaddr; + + fprintf(fp, "\t\"0x%08X\": {\n", paddr); + for (CVI_U32 j = 0 ; j < (size / 0x4); j++) { + fprintf(fp, "\t\t\"h%02x\": %u,\n", (j * 4), *(val++)); + } + fprintf(fp, "\t\t\"size\": %u\n\t},\n", size); + + CVI_SYS_Munmap(vaddr, size); + } + + /* dump look up table */ + // BNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "BNR\n"); + ip_info_id = IP_INFO_ID_BNR; + + CVI_U8 shdw_sel = 0; + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, shdw_sel); + SET_REGISTER_COMMON(0x0, 0, 0); // reg_shadow_rd_sel + + CLEAR_ACCESS_CNT(0x8); + + length = 8; + offset = 0x148; + snprintf(name, sizeof(name), "bnr_intensity_sel"); + FPRINTF_VAL(); + + length = 256; + offset = 0x228; + snprintf(name, sizeof(name), "bnr_weight_lut"); + FPRINTF_VAL(); + + SET_REGISTER_COMMON(0x0, 0, shdw_sel); // reg_shadow_rd_sel + } + + // DPC + { + CVI_TRACE_VI(CVI_DBG_INFO, "DPC\n"); + + CVI_U8 enable = 0; + // CVI_U8 shdw_sel = 0; + CVI_U8 force_clk_enable = 0; +#ifdef __SOC_MARS__ + CVI_U8 idx = (stDevAttr.stWDRAttr.enWDRMode == WDR_MODE_2To1_LINE) ? 2 : 1; + CVI_U32 *data_dpc = NULL; + CVI_CHAR name_list[2][16] = {"dpc_le_bp_tbl", "dpc_se_bp_tbl"}; + enum IP_INFO_GRP ip_info_id_list[2] = {IP_INFO_ID_DPC0, IP_INFO_ID_DPC1}; +#else + CVI_U8 idx = 1; + CVI_U32 *data_dpc = NULL; + CVI_CHAR name_list[1][16] = {"dpc_le_bp_tbl"}; + enum IP_INFO_GRP ip_info_id_list[1] = {IP_INFO_ID_DPC0}; +#endif + + length = 2047; + + for (CVI_U8 i = 0; i < idx; i++) { + GET_BASE_VADDR(ip_info_id_list[i]); + data_dpc = calloc(1, sizeof(CVI_U32) * length); + + GET_REGISTER_COMMON(0x8, 0, enable); + // GET_REGISTER_COMMON(0x4, 0, shdw_sel); + GET_REGISTER_COMMON(0x8, 8, force_clk_enable); + + SET_REGISTER_COMMON(0x8, 0, 0); // reg_dpc_enable + // SET_REGISTER_COMMON(0x4, 0, 0); // reg_shdw_read_sel + SET_REGISTER_COMMON(0x8, 8, 0); // reg_force_clk_enable + WAIT_IP_DISABLE(0x8, 0); + SET_REGISTER_COMMON(0x44, 31, 1); // reg_dpc_mem_prog_mode + + DUMP_LUT_BASE(data_dpc, 0xFFFFFF, 0x48, 0x4C, 0x4C); + + SET_REGISTER_COMMON(0x44, 31, 0); // reg_dpc_mem_prog_mode + SET_REGISTER_COMMON(0x8, 8, force_clk_enable); // reg_force_clk_enable + // SET_REGISTER_COMMON(0x4, 0, shdw_sel); // reg_shdw_read_sel + SET_REGISTER_COMMON(0x8, 0, enable); // reg_dpc_enable + + snprintf(name, sizeof(name), name_list[i]); + FPRINTF_TBL(data_dpc); + + free(data_dpc); + CVI_SYS_Munmap(vaddr, size); + } + } + + // MLSC + // NO INDIRECT LUT + // use the isp tun buffer + { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC\n"); + MLSC_GAIN_LUT_S *MlscGainLut = &pstRegTbl->MlscGainLut; + + length = 1369; + if (MlscGainLut->RGain && MlscGainLut->GGain && MlscGainLut->BGain) { + snprintf(name, sizeof(name), "mlsc_gain_r"); + FPRINTF_TBL(MlscGainLut->RGain); + + snprintf(name, sizeof(name), "mlsc_gain_g"); + FPRINTF_TBL(MlscGainLut->GGain); + + snprintf(name, sizeof(name), "mlsc_gain_b"); + FPRINTF_TBL(MlscGainLut->BGain); + } else { + CVI_TRACE_VI(CVI_DBG_INFO, "MLSC is no data\n"); + } + } + + // RGB_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "RGB_GAMMA\n"); + + struct gamma_tbl rgb_gamma = { + .ip_info_id = IP_INFO_ID_RGBGAMMA, + .name = "rgb_gamma", + .length = 256, + .enable = { + .addr_ofs = 0x0, + .val_ofs = 0, + }, + .shdw_sel = { + .addr_ofs = 0x0, + .val_ofs = 1, + }, + .force_clk_enable = { + .addr_ofs = 0x0, + .val_ofs = 2, + }, + .prog_en = { + .addr_ofs = 0x4, + .val_ofs = 8, + }, + .raddr = { + .addr_ofs = 0x14, + .mask = 0xFF, + .val_ofs = 12, + }, + .rdata_r = { + .addr_ofs = 0x18, + .val_ofs = 31, + .mask = 0xFFF, + }, + .rdata_gb = { + .addr_ofs = 0x1C, + .val_ofs = 16, + .mask = 0xFFF, + }, + }; + + _dump_gamma_table(fp, ip_info_list, &rgb_gamma); + } + + //Y_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "Y_GAMMA\n"); + + struct gamma_tbl y_gamma = { + .ip_info_id = IP_INFO_ID_YGAMMA, + .name = "y_gamma", + .length = 256, + .enable = { + .addr_ofs = 0x0, + .val_ofs = 0, + }, + .shdw_sel = { + .addr_ofs = 0x0, + .val_ofs = 1, + }, + .force_clk_enable = { + .addr_ofs = 0x0, + .val_ofs = 2, + }, + .prog_en = { + .addr_ofs = 0x4, + .val_ofs = 8, + }, + .raddr = { + .addr_ofs = 0x14, + .mask = 0xFF, + .val_ofs = 12, + }, + .rdata_r = { + .addr_ofs = 0x18, + .val_ofs = 31, + .mask = 0xFFFF, + }, + .rdata_gb = { + .addr_ofs = 0x1C, + .val_ofs = 16, + .mask = 0xFFF, + }, + }; + + _dump_gamma_table(fp, ip_info_list, &y_gamma); + } + + // CLUT + { + CVI_TRACE_VI(CVI_DBG_INFO, "CLUT\n"); + ip_info_id = IP_INFO_ID_CLUT; + + CVI_U32 r_idx = 17; + CVI_U32 g_idx = 17; + CVI_U32 b_idx = 17; + CVI_U32 rgb_idx = 0; + CVI_U32 *data_clut_r = NULL; + CVI_U32 *data_clut_g = NULL; + CVI_U32 *data_clut_b = NULL; + CVI_U8 enable = 0; + CVI_U8 shdw_sel = 0; + // CVI_U8 force_clk_enable = 0; + + length = r_idx * g_idx * b_idx; + data_clut_r = calloc(1, sizeof(CVI_U32) * length); + data_clut_g = calloc(1, sizeof(CVI_U32) * length); + data_clut_b = calloc(1, sizeof(CVI_U32) * length); + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, enable); + GET_REGISTER_COMMON(0x0, 1, shdw_sel); + // GET_REGISTER_COMMON(0x0, 2, force_clk_enable); + + SET_REGISTER_COMMON(0x0, 0, 0); // reg_clut_enable + SET_REGISTER_COMMON(0x0, 1, 0); // reg_clut_shdw_sel + // SET_REGISTER_COMMON(0x0, 2, 0); // reg_force_clk_enable + WAIT_IP_DISABLE(0x0, 0); + SET_REGISTER_COMMON(0x0, 3, 1); // reg_prog_en + + for (CVI_U32 i = 0 ; i < b_idx; i++) { + for (CVI_U32 j = 0 ; j < g_idx; j++) { + for (CVI_U32 k = 0 ; k < r_idx; k++) { + rgb_idx = i * g_idx * r_idx + j * r_idx + k; + + val = vaddr + 0x04; // reg_sram_r_idx/reg_sram_g_idx/reg_sram_b_idx + data = (i << 16) | (j << 8) | k; + *val = data; + usleep(1); + + val = vaddr + 0x0C; // reg_sram_rd + data = (0x1 << 31); + *val = data; + usleep(1); + + val = vaddr + 0x0C; // reg_sram_rdata + data = *val; + usleep(1); + + data_clut_r[rgb_idx] = (data >> 20) & 0x3FF; + data_clut_g[rgb_idx] = (data >> 10) & 0x3FF; + data_clut_b[rgb_idx] = data & 0x3FF; + } + } + } + + SET_REGISTER_COMMON(0x0, 3, 0); // reg_prog_en + // SET_REGISTER_COMMON(0x0, 2, force_clk_enable); // reg_force_clk_enable + SET_REGISTER_COMMON(0x0, 1, shdw_sel); // reg_clut_shdw_sel + SET_REGISTER_COMMON(0x0, 0, enable); // reg_clut_enable + + snprintf(name, sizeof(name), "clut_r"); + FPRINTF_TBL(data_clut_r); + + snprintf(name, sizeof(name), "clut_g"); + FPRINTF_TBL(data_clut_g); + + snprintf(name, sizeof(name), "clut_b"); + FPRINTF_TBL(data_clut_b); + + CVI_SYS_Munmap(vaddr, size); + free(data_clut_r); + free(data_clut_g); + free(data_clut_b); + } + + // LTM + { + CVI_TRACE_VI(CVI_DBG_INFO, "LTM\n"); + ip_info_id = IP_INFO_ID_HDRLTM; + + CVI_U8 enable = 0; + CVI_U8 shdw_sel = 0; + CVI_U8 force_clk_enable = 0; + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, enable); + GET_REGISTER_COMMON(0x0, 5, shdw_sel); + GET_REGISTER_COMMON(0x0, 31, force_clk_enable); + + SET_REGISTER_COMMON(0x0, 0, 0); // reg_ltm_enable + SET_REGISTER_COMMON(0x0, 5, 0); // reg_shdw_read_sel + SET_REGISTER_COMMON(0x0, 31, 0); // reg_force_clk_enable + WAIT_IP_DISABLE(0x0, 0); + + // dark tone + length = 257; + CVI_U32 *data_dtone_curve = calloc(1, sizeof(CVI_U32) * length); + + SET_REGISTER_COMMON(0x34, 17, 1); // reg_lut_prog_en_dark + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x34; + data = (*val & ~(0x3FF)) | i; // reg_lut_dbg_raddr[0,9] + data = (data | (0x1 << 15)); // reg_lut_dbg_read_en_1t + *val = data; + usleep(1); + + val = vaddr + 0x4C; // reg_lut_dbg_rdata + data = *val; + data_dtone_curve[i] = data; + } + SET_REGISTER_COMMON(0x34, 17, 0); // reg_lut_prog_en_dark + val = vaddr + 0x44; //reg_dark_lut_max + data_dtone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_dtone_curve"); + FPRINTF_TBL(data_dtone_curve); + free(data_dtone_curve); + + // bright tone +#ifdef __SOC_MARS__ + length = 513; +#else + length = 257; +#endif + CVI_U32 *data_btone_curve = calloc(1, sizeof(CVI_U32) * length); + + SET_REGISTER_COMMON(0x34, 16, 1); // reg_lut_prog_en_bright + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x34; + data = (*val & ~(0x3FF)) | i; // reg_lut_dbg_raddr[0,9] + data = (data | (0x1 << 15)); // reg_lut_dbg_read_en_1t + *val = data; + usleep(1); + + val = vaddr + 0x4C; + data = *val; + data_btone_curve[i] = data; + } + + SET_REGISTER_COMMON(0x34, 16, 0); // reg_lut_prog_en_bright + val = vaddr + 0x40; //reg_bright_lut_max + data_btone_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_btone_curve"); + FPRINTF_TBL(data_btone_curve); + free(data_btone_curve); + + // global tone +#ifdef __SOC_MARS__ + length = 769; +#else + length = 257; +#endif + CVI_U32 *data_global_curve = calloc(1, sizeof(CVI_U32) * length); + + SET_REGISTER_COMMON(0x34, 18, 1); // reg_lut_prog_en_global + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x34; + data = (*val & ~(0x3FF)) | i; // reg_lut_dbg_raddr[0,9] + data = (data | (0x1 << 15)); // reg_lut_dbg_read_en_1t + *val = data; + usleep(1); + + val = vaddr + 0x4C; + data = *val; + data_global_curve[i] = data; + } + SET_REGISTER_COMMON(0x34, 18, 0); // reg_lut_prog_en_global + val = vaddr + 0x48; //reg_global_lut_max + data_global_curve[length - 1] = *val; + snprintf(name, sizeof(name), "ltm_global_curve"); + FPRINTF_TBL(data_global_curve); + free(data_global_curve); + + SET_REGISTER_COMMON(0x0, 31, force_clk_enable); // reg_force_clk_enable + SET_REGISTER_COMMON(0x0, 5, shdw_sel); // reg_shdw_read_sel + SET_REGISTER_COMMON(0x0, 0, enable); // reg_ltm_enable + + CVI_SYS_Munmap(vaddr, size); + } + + // CA_CP + { + CVI_TRACE_VI(CVI_DBG_INFO, "CA_CP\n"); + length = 256; + ip_info_id = IP_INFO_ID_CA; + + CVI_U8 enable = 0; + CVI_U8 shdw_sel = 0; + CVI_U8 ca_cp_mode = 0; + CVI_U32 *data_cacp_y = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_cacp_u = calloc(1, sizeof(CVI_U32) * length); + CVI_U32 *data_cacp_v = calloc(1, sizeof(CVI_U32) * length); + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, enable); + GET_REGISTER_COMMON(0x0, 4, shdw_sel); + GET_REGISTER_COMMON(0x0, 1, ca_cp_mode); + + SET_REGISTER_COMMON(0x0, 0, 0); // reg_cacp_enable + SET_REGISTER_COMMON(0x0, 4, 0); // reg_cacp_shdw_read_sel + WAIT_IP_DISABLE(0x0, 0); + SET_REGISTER_COMMON(0x0, 3, 1); // reg_cacp_mem_sw_mode + + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x0C; + data = (*val & ~0xFF) | i; + *val = data; + usleep(1); + + val = vaddr + 0x0C; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x10; + data = *val; + + if (ca_cp_mode) { + data_cacp_y[i] = ((data >> 16) & 0xFF); + data_cacp_u[i] = ((data >> 8) & 0xFF); + data_cacp_v[i] = (data & 0xFF); + } else { + data_cacp_y[i] = (data & 0x7FF); + } + } + + SET_REGISTER_COMMON(0x0, 3, 0); // reg_cacp_mem_sw_mode + SET_REGISTER_COMMON(0x0, 4, shdw_sel); // reg_cacp_shdw_read_sel + SET_REGISTER_COMMON(0x0, 0, enable); // reg_cacp_enable + + if (ca_cp_mode) { + snprintf(name, sizeof(name), "ca_cp_y"); + FPRINTF_TBL(data_cacp_y); + snprintf(name, sizeof(name), "ca_cp_u"); + FPRINTF_TBL(data_cacp_u); + snprintf(name, sizeof(name), "ca_cp_v"); + FPRINTF_TBL(data_cacp_v); + } else { + snprintf(name, sizeof(name), "ca_y_ratio"); + FPRINTF_TBL(data_cacp_y); + } + + CVI_SYS_Munmap(vaddr, size); + free(data_cacp_y); + free(data_cacp_u); + free(data_cacp_v); + } + + // YNR + { + CVI_TRACE_VI(CVI_DBG_INFO, "YNR\n"); + ip_info_id = IP_INFO_ID_YNR; + + CVI_U8 shdw_sel = 0; + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, shdw_sel); + + SET_REGISTER_COMMON(0x0, 0, 0); // reg_shadow_rd_sel + CLEAR_ACCESS_CNT(0x8); + + length = 6; + offset = 0x00C; + snprintf(name, sizeof(name), "ynr_ns0_luma_th"); + FPRINTF_VAL2(); + + length = 5; + offset = 0x024; + snprintf(name, sizeof(name), "ynr_ns0_slope"); + FPRINTF_VAL2(); + + length = 6; + offset = 0x038; + snprintf(name, sizeof(name), "ynr_ns0_offset"); + FPRINTF_VAL2(); + + length = 6; + offset = 0x050; + snprintf(name, sizeof(name), "ynr_ns1_luma_th"); + FPRINTF_VAL2(); + + length = 5; + offset = 0x068; + snprintf(name, sizeof(name), "ynr_ns1_slope"); + FPRINTF_VAL2(); + + length = 6; + offset = 0x07C; + snprintf(name, sizeof(name), "ynr_ns1_offset"); + FPRINTF_VAL2(); + + length = 16; + offset = 0x098; + snprintf(name, sizeof(name), "ynr_motion_lut"); + FPRINTF_VAL2(); + + length = 16; + offset = 0x260; + snprintf(name, sizeof(name), "ynr_res_mot_lut"); + FPRINTF_VAL2(); + + length = 64; + offset = 0x200; + snprintf(name, sizeof(name), "ynr_weight_lut"); + FPRINTF_VAL(); + + SET_REGISTER_COMMON(0x0, 0, shdw_sel); // reg_shadow_rd_sel + + CVI_SYS_Munmap(vaddr, size); + } + + // YCURVE + { + CVI_TRACE_VI(CVI_DBG_INFO, "YCURVE\n"); + length = 64; + ip_info_id = IP_INFO_ID_YCURVE; + + CVI_U8 enable = 0; + CVI_U8 shdw_sel = 0; + CVI_U8 force_clk_enable = 0; + CVI_U32 *data_ycurve = calloc(1, sizeof(CVI_U32) * length); + + GET_BASE_VADDR(ip_info_id); + GET_REGISTER_COMMON(0x0, 0, enable); + GET_REGISTER_COMMON(0x0, 1, shdw_sel); + GET_REGISTER_COMMON(0x0, 2, force_clk_enable); + + SET_REGISTER_COMMON(0x0, 0, 0); // reg_ycur_enable + SET_REGISTER_COMMON(0x0, 1, 0); // reg_ycur_shdw_sel + SET_REGISTER_COMMON(0x0, 2, 0); // reg_force_clk_enable + WAIT_IP_DISABLE(0x0, 0); + SET_REGISTER_COMMON(0x4, 8, 1); // reg_ycur_prog_en +#ifdef __SOC_PHOBOS__ + CVI_U8 r_sel = 0; + + GET_REGISTER_COMMON(0x4, 4, r_sel); + CVI_TRACE_VI(CVI_DBG_INFO, "mem[%d] work, mem[%d] IDLE\n", r_sel, r_sel ^ 0x1); + SET_REGISTER_COMMON(0x14, 12, r_sel ^ 0x1); +#endif + for (CVI_U32 i = 0 ; i < length; i++) { + val = vaddr + 0x14; + data = (*val & ~(0x3F)) | i; + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = (*val | (0x1 << 31)); + *val = data; + usleep(1); + + val = vaddr + 0x18; + data = *val; + data_ycurve[i] = (data & 0xFF); + } + + SET_REGISTER_COMMON(0x4, 8, 0); // reg_ycur_prog_en + SET_REGISTER_COMMON(0x0, 2, force_clk_enable); // reg_force_clk_enable + SET_REGISTER_COMMON(0x0, 1, shdw_sel); // reg_ycur_shdw_sel + SET_REGISTER_COMMON(0x0, 0, enable); // reg_ycur_enable + + snprintf(name, sizeof(name), "ycurve"); + FPRINTF_TBL(data_ycurve); + + free(data_ycurve); + CVI_SYS_Munmap(vaddr, size); + } + + // DCI_GAMMA + { + CVI_TRACE_VI(CVI_DBG_INFO, "DCI_GAMMA\n"); + + struct gamma_tbl dci_gamma = { + .ip_info_id = IP_INFO_ID_DCI, + .name = "dci_gamma", + .length = 256, + .enable = { + .addr_ofs = 0x0C, + .val_ofs = 0, + }, + .shdw_sel = { + .addr_ofs = 0x14, + .val_ofs = 4, + }, + .force_clk_enable = { + .addr_ofs = 0x0C, + .val_ofs = 8, + }, + .prog_en = { + .addr_ofs = 0x204, + .val_ofs = 8, + }, + .raddr = { + .addr_ofs = 0x214, + .mask = 0xFF, + .val_ofs = 12, + }, + .rdata_r = { + .addr_ofs = 0x218, + .val_ofs = 31, + .mask = 0xFFF, + }, + .rdata_gb = { + .addr_ofs = 0x21C, + .val_ofs = 16, + .mask = 0xFFF, + }, + }; + + _dump_gamma_table(fp, ip_info_list, &dci_gamma); + } + + /* end of file */ + fprintf(fp, "\t\"end\": {}\n"); + fprintf(fp, "}"); + /* start tuning update */ +#ifdef __SOC_MARS__ + system("echo 0,0,0,0 > /sys/module/cv181x_vi/parameters/tuning_dis"); +#else + system("echo 0,0,0,0 > /sys/module/cv180x_vi/parameters/tuning_dis"); +#endif + free(ip_info_list); +#endif + return CVI_SUCCESS; +} diff --git a/middleware/v2/modules/vpu/src/dwa_ioctl.c b/middleware/v2/modules/vpu/src/dwa_ioctl.c new file mode 100644 index 000000000..81d591b30 --- /dev/null +++ b/middleware/v2/modules/vpu/src/dwa_ioctl.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +#include "dwa_ioctl.h" + +CVI_S32 gdc_begin_job(CVI_S32 fd, struct gdc_handle_data *cfg) +{ + return ioctl(fd, CVI_DWA_BEGIN_JOB, cfg); +} + +CVI_S32 gdc_end_job(CVI_S32 fd, struct gdc_handle_data *cfg) +{ + return ioctl(fd, CVI_DWA_END_JOB, cfg); +} + +CVI_S32 gdc_cancel_job(CVI_S32 fd, struct gdc_handle_data *cfg) +{ + return ioctl(fd, CVI_DWA_CANCEL_JOB, cfg); +} + +CVI_S32 gdc_add_rotation_task(CVI_S32 fd, struct gdc_task_attr *attr) +{ + return ioctl(fd, CVI_DWA_ADD_ROT_TASK, attr); +} + +CVI_S32 gdc_add_ldc_task(CVI_S32 fd, struct gdc_task_attr *attr) +{ + return ioctl(fd, CVI_DWA_ADD_LDC_TASK, attr); +} + +CVI_S32 gdc_set_chn_buf_wrap(CVI_S32 fd, const struct dwa_buf_wrap_cfg *cfg) +{ + return ioctl(fd, CVI_DWA_SET_BUF_WRAP, cfg); +} + +CVI_S32 gdc_get_chn_buf_wrap(CVI_S32 fd, struct dwa_buf_wrap_cfg *cfg) +{ + return ioctl(fd, CVI_DWA_GET_BUF_WRAP, cfg); +} diff --git a/middleware/v2/modules/vpu/src/gdc_mesh.c b/middleware/v2/modules/vpu/src/gdc_mesh.c new file mode 100644 index 000000000..36c358edc --- /dev/null +++ b/middleware/v2/modules/vpu/src/gdc_mesh.c @@ -0,0 +1,3102 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cvi_base.h" +#include +#include +#include + +#include "cvi_gdc.h" +#include "gdc_mesh.h" + + +#define DEWARP_COORD_MBITS 13 +#define DEWARP_COORD_NBITS 18 +#define NUMBER_Y_LINE_A_SUBTILE 4 + +#define MESH_ID_FST 0xfffa // frame start +#define MESH_ID_FSS 0xfffb // slice start +#define MESH_ID_FSP 0xfffc // tile start +#define MESH_ID_FTE 0xfffd // tile end +#define MESH_ID_FSE 0xfffe // slice end +#define MESH_ID_FED 0xffff // frame end +#define MESH_HOR_DEFAULT 16 +#define MESH_VER_DEFAULT 16 +#define MESH_MAX_SIZE (32 * 32) +#define CLIP(x, min, max) MAX(MIN(x, max), min) + +static int meshHor = MESH_HOR_DEFAULT; +static int meshVer = MESH_HOR_DEFAULT; +// 0--1 +// | | +// 2--3 +int MESH_EDGE[4][2] = { + { 0, 1 }, + { 1, 3 }, + { 2, 0 }, + { 3, 2 } +}; + +int mesh_coordinate_float2fixed(float src_x_mesh_tbl[][4], float src_y_mesh_tbl[][4], float dst_x_mesh_tbl[][4], + float dst_y_mesh_tbl[][4], int mesh_tbl_num, int isrc_x_mesh_tbl[][4], + int isrc_y_mesh_tbl[][4], int idst_x_mesh_tbl[][4], int idst_y_mesh_tbl[][4]) +{ + int64_t MAX_VAL; + int64_t MIN_VAL; + double tmp_val; + int64_t val; + + MAX_VAL = 1; + MAX_VAL <<= (DEWARP_COORD_MBITS + DEWARP_COORD_NBITS); + MAX_VAL -= 1; + MIN_VAL = -1 * MAX_VAL; + + for (int i = 0; i < mesh_tbl_num; i++) { + for (int j = 0; j < 4; j++) { + tmp_val = (src_x_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + isrc_x_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (src_y_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + isrc_y_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (dst_x_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + idst_x_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (dst_y_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + idst_y_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + } + } + + return 0; +} + +int mesh_scan_preproc_3(int dst_width, int dst_height + , const float dst_x_mesh_tbl[][4], const float dst_y_mesh_tbl[][4] + , int mesh_tbl_num, uint16_t *mesh_scan_id_order, int X_TILE_NUMBER + , int NUM_Y_LINE_A_SUBTILE, int Y_TILE_NUMBER, int MAX_MESH_NUM_A_TILE) +{ + int tile_idx_x, tile_idx_y; + int current_dst_mesh_y_line_intersection_cnt, mesh_num_cnt = 0; + + int id_idx = 0; + int tmp_mesh_cnt = MAX_MESH_NUM_A_TILE * 4; + int *tmp_mesh_scan_id_order = (int *)malloc(sizeof(int) * (MAX_MESH_NUM_A_TILE * 4)); + int NUM_X_LINE_A_TILE = ceil((float)dst_width / (float)X_TILE_NUMBER / 2.0) * 2; + int NUM_Y_LINE_A_TILE = + (int)(ceil(ceil((float)dst_height / (float)Y_TILE_NUMBER) / (float)NUMBER_Y_LINE_A_SUBTILE)) * + NUMBER_Y_LINE_A_SUBTILE; + + mesh_scan_id_order[id_idx++] = MESH_ID_FST; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "X_TILE_NUMBER(%d) Y_TILE_NUMBER(%d)\n", X_TILE_NUMBER, Y_TILE_NUMBER); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "NUM_X_LINE_A_TILE(%d) NUM_Y_LINE_A_TILE(%d)\n" + , NUM_X_LINE_A_TILE, NUM_Y_LINE_A_TILE); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "NUM_Y_LINE_A_SUBTILE(%d)\n", NUM_Y_LINE_A_SUBTILE); + + for (tile_idx_y = 0; tile_idx_y < Y_TILE_NUMBER; tile_idx_y++) { + // src_y = (1st line of this tile ) + // dst_y = (1st line of next tile ) + int src_y = CLIP((tile_idx_y * NUM_Y_LINE_A_TILE), 0, dst_height); + int dst_y = CLIP((src_y + NUM_Y_LINE_A_TILE), 0, dst_height); + + for (tile_idx_x = 0; tile_idx_x < X_TILE_NUMBER; tile_idx_x++) { + mesh_scan_id_order[id_idx++] = MESH_ID_FSS; + + int src_x = CLIP((tile_idx_x * NUM_X_LINE_A_TILE), 0, dst_width); + int dst_x = CLIP((src_x + NUM_X_LINE_A_TILE), 0, dst_width); + + // label starting position (slice) and its size ( x & y ) + mesh_scan_id_order[id_idx++] = src_x; + mesh_scan_id_order[id_idx++] = dst_x - src_x; + mesh_scan_id_order[id_idx++] = src_y; + mesh_scan_id_order[id_idx++] = dst_y - src_y; + + for (int y = src_y; y < dst_y; y++) { + // if first line of a tile, then initialization + if (y % NUM_Y_LINE_A_SUBTILE == 0) { + mesh_num_cnt = 0; + for (int i = 0; i < tmp_mesh_cnt; i++) + tmp_mesh_scan_id_order[i] = -1; + + // frame separator ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FSP; + } + + for (int m = 0; m < mesh_tbl_num; m++) { + current_dst_mesh_y_line_intersection_cnt = 0; + int is_mesh_incorp_yline = 0; + int min_x = MIN(MIN(dst_x_mesh_tbl[m][0], dst_x_mesh_tbl[m][1]), + MIN(dst_x_mesh_tbl[m][2], dst_x_mesh_tbl[m][3])); + int max_x = MAX(MAX(dst_x_mesh_tbl[m][0], dst_x_mesh_tbl[m][1]), + MAX(dst_x_mesh_tbl[m][2], dst_x_mesh_tbl[m][3])); + int min_y = MIN(MIN(dst_y_mesh_tbl[m][0], dst_y_mesh_tbl[m][1]), + MIN(dst_y_mesh_tbl[m][2], dst_y_mesh_tbl[m][3])); + int max_y = MAX(MAX(dst_y_mesh_tbl[m][0], dst_y_mesh_tbl[m][1]), + MAX(dst_y_mesh_tbl[m][2], dst_y_mesh_tbl[m][3])); + if (min_y <= y && y <= max_y && min_x <= src_x && dst_x <= max_x) + is_mesh_incorp_yline = 1; + + if (!is_mesh_incorp_yline) { + for (int k = 0; k < 4; k++) { + float knot_dst_a_y = dst_y_mesh_tbl[m][MESH_EDGE[k][0]]; + float knot_dst_b_y = dst_y_mesh_tbl[m][MESH_EDGE[k][1]]; + float knot_dst_a_x = dst_x_mesh_tbl[m][MESH_EDGE[k][0]]; + float knot_dst_b_x = dst_x_mesh_tbl[m][MESH_EDGE[k][1]]; + float delta_a_y = (float)y - knot_dst_a_y; + float delta_b_y = (float)y - knot_dst_b_y; + int intersect_x = 0; + + if ((src_x <= knot_dst_a_x) && (knot_dst_a_x <= dst_x)) + intersect_x = 1; + if ((src_x <= knot_dst_b_x) && (knot_dst_b_x <= dst_x)) + intersect_x = 1; + + // check whether if vertex connection + if ((delta_a_y == 0.f) && (intersect_x == 1)) { + current_dst_mesh_y_line_intersection_cnt += 2; + } + // check whether if edge connection + else if ((delta_a_y * delta_b_y < 0) && (intersect_x == 1)) { + current_dst_mesh_y_line_intersection_cnt += 2; + } + // otherwise no connection + } // finish check in a mesh + } + + if ((current_dst_mesh_y_line_intersection_cnt > 0) || (is_mesh_incorp_yline == 1)) { + // check the mesh in list or not + int isInList = 0; + + for (int i = 0; i < mesh_num_cnt; i++) { + if (m == tmp_mesh_scan_id_order[i]) { + isInList = 1; + break; + } + } + // not in the list, then add the mesh to list + if (!isInList) { + tmp_mesh_scan_id_order[mesh_num_cnt] = m; + mesh_num_cnt++; + } + } + } + + // x direction reorder + if (((y % NUM_Y_LINE_A_SUBTILE) == (NUM_Y_LINE_A_SUBTILE - 1)) || (y == dst_height - 1)) { + for (int i = 0; i < mesh_num_cnt - 1; i++) { + for (int j = 0; j < mesh_num_cnt - 1 - i; j++) { + int m0 = tmp_mesh_scan_id_order[j]; + int m1 = tmp_mesh_scan_id_order[j + 1]; + float knot_m0_x0 = dst_x_mesh_tbl[m0][0]; + float knot_m0_x1 = dst_x_mesh_tbl[m0][1]; + float knot_m0_x2 = dst_x_mesh_tbl[m0][2]; + float knot_m0_x3 = dst_x_mesh_tbl[m0][3]; + float knot_m1_x0 = dst_x_mesh_tbl[m1][0]; + float knot_m1_x1 = dst_x_mesh_tbl[m1][1]; + float knot_m1_x2 = dst_x_mesh_tbl[m1][2]; + float knot_m1_x3 = dst_x_mesh_tbl[m1][3]; + + int m0_min_x = MIN(MIN(knot_m0_x0, knot_m0_x1), + MIN(knot_m0_x2, knot_m0_x3)); + int m1_min_x = MIN(MIN(knot_m1_x0, knot_m1_x1), + MIN(knot_m1_x2, knot_m1_x3)); + + if (m0_min_x > m1_min_x) { + int tmp = tmp_mesh_scan_id_order[j]; + + tmp_mesh_scan_id_order[j] = + tmp_mesh_scan_id_order[j + 1]; + tmp_mesh_scan_id_order[j + 1] = tmp; + } + } + } + + // mesh ID insertion + for (int i = 0; i < mesh_num_cnt; i++) { + mesh_scan_id_order[id_idx++] = tmp_mesh_scan_id_order[i]; + } + + // tile end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FTE; + } + } + + // frame slice end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FSE; + } + } + + // frame end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FED; + + free(tmp_mesh_scan_id_order); + + return id_idx; +} + +int mesh_tbl_reorder_and_parse_3(uint16_t *mesh_scan_tile_mesh_id_list, int mesh_id_list_entry_num, + int isrc_x_mesh_tbl[][4], int isrc_y_mesh_tbl[][4], int idst_x_mesh_tbl[][4], + int idst_y_mesh_tbl[][4], int X_TILE_NUMBER, + int Y_TILE_NUMBER, int Y_SUBTILE_NUMBER, int **reorder_mesh_tbl, + int *reorder_mesh_tbl_entry_num, uint16_t *reorder_mesh_id_list, + int *reorder_mesh_id_list_entry_num, uint64_t mesh_tbl_phy_addr) +{ + int mesh = -1; + int reorder_mesh; + int mesh_id_idx = 0; + int mesh_idx = 0; + int *reorder_id_map = (int *)malloc(sizeof(int) * 128 * 128); + + int *reorder_mesh_slice_tbl = reorder_mesh_tbl[0]; // initial mesh_tbl to + + int i = 0; + //int ext_mem_addr_alignment = 32; + + (void) mesh_id_list_entry_num; + (void)Y_SUBTILE_NUMBER; + + // frame start ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + + for (int k = 0; k < Y_TILE_NUMBER; k++) { + for (int j = 0; j < X_TILE_NUMBER; j++) { + reorder_mesh_tbl[j + k * X_TILE_NUMBER] = reorder_mesh_slice_tbl + mesh_idx; + + reorder_mesh = 0; +#if 1 // (JAMMY) clear to -1 + for (int l = 0; l < 128 * 128; l++) { + reorder_id_map[l] = -1; + } +#else + memset(reorder_id_map, 0xff, sizeof(sizeof(int) * 128 * 128)); +#endif + + // slice start ID + mesh = mesh_scan_tile_mesh_id_list[i++]; + reorder_mesh_id_list[mesh_id_idx++] = mesh; + +#if 0 // (JAMMY) replace with phy-addr later. + // reorder mesh table address -> reorder mesh id list header + uintptr_t addr = (uintptr_t)reorder_mesh_tbl[j + k * X_TILE_NUMBER]; + + reorder_mesh_id_list[mesh_id_idx++] = addr & 0x0000000fff; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0000fff000) >> 12; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0fff000000) >> 24; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0xf000000000) >> 36; +#else + CVI_U64 addr = mesh_tbl_phy_addr + + ((uintptr_t)reorder_mesh_tbl[j + k * X_TILE_NUMBER] + - (uintptr_t)reorder_mesh_tbl[0]); + + reorder_mesh_id_list[mesh_id_idx++] = addr & 0x0000000fff; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0000fff000) >> 12; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0fff000000) >> 24; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0xf000000000) >> 36; +#endif + + // slice src and width -> reorder mesh id list header + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile x src + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile width + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile y src + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile height + + while (mesh_scan_tile_mesh_id_list[i] != MESH_ID_FSE) { + mesh = mesh_scan_tile_mesh_id_list[i++]; + if (mesh == MESH_ID_FST || mesh == MESH_ID_FSS) { + continue; + } else if (mesh == MESH_ID_FSP || /* mesh == MESH_ID_FED */ mesh == MESH_ID_FTE) { + reorder_mesh_id_list[mesh_id_idx++] = mesh; // meta-data header + } else /* if (mesh != MESH_ID_FED) */ { + if (reorder_id_map[mesh] == -1) { + reorder_id_map[mesh] = reorder_mesh; + reorder_mesh++; + + for (int l = 0; l < 4; l++) { + reorder_mesh_slice_tbl[mesh_idx++] = isrc_x_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = isrc_y_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = idst_x_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = idst_y_mesh_tbl[mesh][l]; + } + } + + reorder_mesh_id_list[mesh_id_idx++] = reorder_id_map[mesh]; + } + } + + // slice end ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + } + } + + // frame end ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + + *reorder_mesh_tbl_entry_num = mesh_idx; + *reorder_mesh_id_list_entry_num = mesh_id_idx; + + free(reorder_id_map); + + return 0; +} + +struct mesh_param { + CVI_U32 width; // dst frame's width + CVI_U32 height; // dst frame's height + void *mesh_id_addr; + void *mesh_tbl_addr; + CVI_U64 mesh_tbl_phy_addr; + CVI_U8 slice_num_w; + CVI_U8 slice_num_h; + CVI_U16 mesh_num; +}; + +static bool is_rect_overlap(POINT_S l1, POINT_S r1, POINT_S l2, POINT_S r2) +{ + // If one rectangle is on left side of other + if (l1.s32X > r2.s32X || l2.s32X > r1.s32X) + return false; + + // If one rectangle is above other + if (l1.s32Y > r2.s32Y || l2.s32Y > r1.s32Y) + return false; + + return true; +} + +static void _generate_mesh_id(struct mesh_param *param, POINT_S dst_mesh_tbl[][4]) +{ + const int NUM_X_LINE_A_SLICE = DIV_UP(param->width, param->slice_num_w); + const int NUM_Y_LINE_A_SLICE = ALIGN(DIV_UP(param->height, param->slice_num_h), NUMBER_Y_LINE_A_SUBTILE); + CVI_U16 *mesh_id = param->mesh_id_addr; + CVI_U16 slice_idx_x, slice_idx_y; + CVI_U32 id_idx = 0; + + mesh_id[id_idx++] = MESH_ID_FST; + for (slice_idx_y = 0; slice_idx_y < param->slice_num_h; slice_idx_y++) { + int src_y = CLIP((slice_idx_y * NUM_Y_LINE_A_SLICE), 0, param->height); + int dst_y = CLIP((src_y + NUM_Y_LINE_A_SLICE), 0, param->height); + for (slice_idx_x = 0; slice_idx_x < param->slice_num_w; slice_idx_x++) { + int src_x = CLIP((slice_idx_x * NUM_X_LINE_A_SLICE), 0, param->width); + int dst_x = CLIP((src_x + NUM_X_LINE_A_SLICE), 0, param->width); + + mesh_id[id_idx++] = MESH_ID_FSS; + mesh_id[id_idx++] = param->mesh_tbl_phy_addr & 0x0fff; + mesh_id[id_idx++] = (param->mesh_tbl_phy_addr >> 12) & 0x0fff; + mesh_id[id_idx++] = (param->mesh_tbl_phy_addr >> 24) & 0x0fff; + mesh_id[id_idx++] = (param->mesh_tbl_phy_addr >> 36) & 0x000f; + mesh_id[id_idx++] = src_x; + mesh_id[id_idx++] = (dst_x - src_x); + mesh_id[id_idx++] = src_y; + mesh_id[id_idx++] = (dst_y - src_y); + + for (int y = src_y; y < dst_y; y += NUMBER_Y_LINE_A_SUBTILE) { + POINT_S l1, r1, l2, r2; + + l1.s32X = src_x; + l1.s32Y = y; + r1.s32X = dst_x; + r1.s32Y = y + NUMBER_Y_LINE_A_SUBTILE; + mesh_id[id_idx++] = MESH_ID_FSP; + for (int m = 0; m < param->mesh_num; ++m) { + // To reduce time consumption + // assumption: dst mesh is ordered (left->right, up->down) + if (dst_mesh_tbl[m][3].s32Y < l1.s32Y) continue; + if (dst_mesh_tbl[m][0].s32Y > r1.s32Y) break; + + l2.s32X = dst_mesh_tbl[m][0].s32X; + l2.s32Y = dst_mesh_tbl[m][0].s32Y; + r2.s32X = dst_mesh_tbl[m][3].s32X; + r2.s32Y = dst_mesh_tbl[m][3].s32Y; + if (is_rect_overlap(l1, r1, l2, r2)) + mesh_id[id_idx++] = m; + } + mesh_id[id_idx++] = MESH_ID_FTE; + } + mesh_id[id_idx++] = MESH_ID_FSE; + } + } + mesh_id[id_idx++] = MESH_ID_FED; + + for (int i = 0; i < 32; ++i) + mesh_id[id_idx++] = 0x00; +} + +/** + * generate_mesh_on_faces: generate mesh based on the nodes describing the faces. + * + * @param param: mesh parameters. + * @param pstAttr: affine's attributes + */ +static void generate_mesh_on_faces(struct mesh_param *param, const AFFINE_ATTR_S *pstAttr) +{ + const CVI_U8 w_knot_num = param->width/pstAttr->stDestSize.u32Width + 1; + const CVI_U8 h_knot_num = param->height/pstAttr->stDestSize.u32Height + 1; + // Limit slice's width/height to avoid unnecessary DRAM write(by bg-color) + CVI_U16 width_slice = 0, height_slice = 0; + CVI_U16 i, j, x, y, knot_idx; + POINT_S dst_knot_tbl[w_knot_num * h_knot_num]; + POINT_S dst_mesh_tbl[param->mesh_num][4]; + CVI_U16 tbl_idx = 0; + CVI_U32 *mesh_tbl = param->mesh_tbl_addr; + + // generate node + for (j = 0; j < h_knot_num; ++j) { + y = j * pstAttr->stDestSize.u32Height; + for (i = 0; i < w_knot_num; ++i) { + knot_idx = j * w_knot_num + i; + x = i * pstAttr->stDestSize.u32Width; + dst_knot_tbl[knot_idx].s32X = x; + dst_knot_tbl[knot_idx].s32Y = y; + } + } + + // map node to each mesh + for (i = 0; i < param->mesh_num; ++i) { + knot_idx = i + (i / (param->width/pstAttr->stDestSize.u32Width)); // there is 1 more node than mesh each row + + dst_mesh_tbl[i][0] = dst_knot_tbl[knot_idx]; + dst_mesh_tbl[i][1] = dst_knot_tbl[knot_idx + 1]; + dst_mesh_tbl[i][2] = dst_knot_tbl[knot_idx + w_knot_num]; + dst_mesh_tbl[i][3] = dst_knot_tbl[knot_idx + w_knot_num + 1]; + + if (dst_mesh_tbl[i][1].s32X > width_slice) width_slice = dst_mesh_tbl[i][1].s32X; + if (dst_mesh_tbl[i][2].s32Y > height_slice) height_slice = dst_mesh_tbl[i][2].s32Y; + + for (j = 0; j < 4; ++j) { + mesh_tbl[tbl_idx++] = pstAttr->astRegionAttr[i][j].x * (double)(1 << DEWARP_COORD_NBITS); + mesh_tbl[tbl_idx++] = pstAttr->astRegionAttr[i][j].y * (double)(1 << DEWARP_COORD_NBITS); + mesh_tbl[tbl_idx++] = dst_mesh_tbl[i][j].s32X * (double)(1 << DEWARP_COORD_NBITS); + mesh_tbl[tbl_idx++] = dst_mesh_tbl[i][j].s32Y * (double)(1 << DEWARP_COORD_NBITS); + } + } + + param->width = width_slice; + param->height = height_slice; + _generate_mesh_id(param, dst_mesh_tbl); +} + +void mesh_gen_affine(SIZE_S in_size, SIZE_S out_size, const AFFINE_ATTR_S *pstAffineAttr + , uint64_t mesh_phy_addr, void *mesh_vir_addr) +{ + const int MAX_MESH_NUM_A_TILE = 4; + int X_TILE_NUMBER, Y_TILE_NUMBER; + int owidth, oheight; + int Y_SUBTILE_NUMBER; + CVI_U32 mesh_id_size, mesh_tbl_size; + CVI_U64 mesh_id_phy_addr, mesh_tbl_phy_addr; + + owidth = out_size.u32Width; + oheight = out_size.u32Height; + X_TILE_NUMBER = DIV_UP(in_size.u32Width, 122); + Y_TILE_NUMBER = 8; + + // calculate mesh_id/mesh_tbl's size in bytes. + Y_SUBTILE_NUMBER = ceil((float)out_size.u32Height / (float)NUMBER_Y_LINE_A_SUBTILE); + mesh_tbl_size = X_TILE_NUMBER * Y_TILE_NUMBER * 16 * sizeof(CVI_U32); + mesh_id_size = MAX_MESH_NUM_A_TILE * Y_SUBTILE_NUMBER * X_TILE_NUMBER * sizeof(CVI_U16); + + // Decide the position of mesh in memory. + mesh_id_phy_addr = mesh_phy_addr; + mesh_tbl_phy_addr = ALIGN(mesh_phy_addr + mesh_id_size, 0x1000); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "phy-addr of mesh id(%#"PRIx64") mesh_tbl(%#"PRIx64")\n" + , mesh_id_phy_addr, mesh_tbl_phy_addr); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_size(%d) mesh_tbl_size(%d)\n", mesh_id_size, mesh_tbl_size); + + struct mesh_param param; + + param.width = owidth; + param.height = oheight; + param.mesh_id_addr = mesh_vir_addr; + param.mesh_tbl_addr = mesh_vir_addr + (mesh_tbl_phy_addr - mesh_id_phy_addr);; + param.mesh_tbl_phy_addr = mesh_tbl_phy_addr; + param.slice_num_w = 1; + param.slice_num_h = 1; + param.mesh_num = pstAffineAttr->u32RegionNum; + generate_mesh_on_faces(¶m, pstAffineAttr); + +} + + +/* For fisheye + * + */ + +//#define M_PI 3.14159265358979323846264338327950288 +#define minmax(a,b,c) (((a)<(b))? (b):((a)>(c))? (c):(a)) +#define UI_CTRL_VALUE_CENTER 180 // range from -16 ~ 16, "16" is the center of value 0 ~32 + +typedef enum _PROJECTION_MODE { + PROJECTION_PANORAMA_360, + PROJECTION_PANORAMA_180, + PROJECTION_REGION, + PROJECTION_LDC, +} PROJECTION_MODE; + +typedef struct _FORMAT_8BITS_RGB { + unsigned R; + unsigned G; + unsigned B; +} FORMAT_8BITS_RGB; + +typedef struct _COORDINATE2D { + double xcor; + double ycor; +}COORDINATE2D; + +typedef struct _MESH_STRUCT { + COORDINATE2D knot[4]; + + int idx; +}MESH_STRUCT; + +#define MAX_REGION_NUM 5 +#define MESHINFO_DEBUG 0 +#define MAX_FRAME_MESH_NUM 4096 + +#define UI_CTRL_VALUE_CENTER 180 // range from -16 ~ 16, "16" is the center of value 0 ~32 + +typedef struct _FISHEYE_ATTR { + + bool Enable; // dewarp engine on/off + bool BgEnable; // given background color enable. + + int RgnNum; // dewarp Region Number. + int TotalMeshNum; // total mesh numbes + int OutW_disp; // output display frame width + int OutH_disp; // output display frame height + int InCenterX; // input fisheye center position X + int InCenterY; // input fisheye center position Y + int InRadius; // input fisheye radius in pixels. + + double Hoffset; // fish-eye image center horizontal offset. + double VOffset; // fish-eye image center vertical offset. + double TCoef; // KeyStone Corection coefficient. + double FStrength; // Fan Correction coefficient. + + USAGE_MODE UsageMode; // Panorama.360, Panorama.180, Mode1~Mode7. total = 9 for now. + FISHEYE_MOUNT_MODE_E MntMode; // CEILING/ FLOOR/ WALL + FORMAT_8BITS_RGB BgColor; // give background color RGB. + + //MESH_STRUCT DstRgnMeshInfo[16384]; // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + //MESH_STRUCT SrcRgnMeshInfo[16384]; // frame-based src mesh info. + + MESH_STRUCT DstRgnMeshInfo[MAX_FRAME_MESH_NUM]; // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT SrcRgnMeshInfo[MAX_FRAME_MESH_NUM]; // frame-based src mesh info. + + int SliceX_Num; // How many tile is sliced in a frame horizontally. + int SliceY_Num; // How many tile is sliced in a frame vertically. + + int rotate_index; +} FISHEYE_ATTR; + +typedef struct _FISHEYE_REGION_ATTR { + int RgnIndex; // region index + float InRadius; // For Panorama.360 mode, inner radius. + float OutRadius; // For Panorama.360 mode, outer radius. + int Pan; // Region PTZ-Pan. + int Tilt; // Region PTZ-Tilt. + int HorZoom; // adjust horizontal zoom in Region PTZ. + int VerZoom; // adjust vertical zoom in Region PTZ. + int OutX; // region initial position x on display frame. + int OutY; // region initial position y on display frame. + int OutW; // region width. + int OutH; // region height. + int MeshHor; // mesh counts horizontal + int MeshVer; // mesh counts vertical + + // to give region default view center + double ThetaX; // User set rotation angle around X-axis, create angle between vector to Z-axis. (start position @ [0,0,1]) + double ThetaY; // User set rotation angle around Y-axis, + double ThetaZ; // User set rotation angle around Z-axis, + + double ZoomH; // User Set for Region + double ZoomV; // User Set for Region + int PanEnd; // For Panorama Case Only + bool RegionValid; // label valid/ invalid for each region + + MESH_STRUCT DstRgnMeshInfo[MAX_FRAME_MESH_NUM]; // initial buffer to store destination mesh info. max: 32*32 + MESH_STRUCT SrcRgnMeshInfo[MAX_FRAME_MESH_NUM]; // initial buffer to store source mesh info + PROJECTION_MODE ViewMode; // projection method. ex: Panorama.360, Panorama.180, Region +} FISHEYE_REGION_ATTR; + +typedef struct Vector3D { + double x; + double y; + double z; +} Vector3D; + +typedef struct Vector2D { + double x; + double y; +} Vector2D; + +typedef struct RotMatrix3D { + double coef[4][4]; +} RotMatrix3D; + + +void Normalize3D(Vector3D* v) +{ + double x3d, y3d, z3d, d; + + x3d = v->x; + y3d = v->y; + z3d = v->z; + d = sqrt(x3d * x3d + y3d * y3d + z3d * z3d); + v->x = x3d / d; + v->y = y3d / d; + v->z = z3d / d; +} + +void Equidistant_Panorama(Vector3D* v3d, Vector2D* v2d, double f) +{ + double rd, theta; + + // calculate theta from the angle between (0,0,1) and (x3d, y3d, z3d) + //theta = acos(v3d->z); //bastian + + theta = v3d->z; + + if (theta == 0.0) { + theta += 1e-64; + } + +#if 0 + // calculate rd = f * theta + rd = f * (theta / (M_PI / 2)); + phy = atan(rd / f); + + // calculate new distorted vector (x,y,z) = (0,0,1) * (1-rd/ri) + (x3d, y3d, z3d) * (rd/ri) + Vector3D v3d_p; + v3d_p.x = v3d->x * phy / theta; + v3d_p.y = v3d->y * phy / theta; + v3d_p.z = v3d->z * phy / theta + (1 - phy / theta); + + // calculate the target point (xi, yi) on image at z = f + v2d->x = (f / v3d_p.z) * v3d_p.x; + v2d->y = (f / v3d_p.z) * v3d_p.y; + +#else + // calculate rd = f * theta + // assume: fisheye image 2D' radius rd + // if it's equidistant: r = focal*incident_angle + // max incident angle = PI/2 + rd = f * (theta / (M_PI / 2)); + + // ( 0,0 ) & (v3d->x, v3d->y): find equation y = ax + b + // a = v3d.y/v3d.x + // if incident angle from space ( x, y ), + double L_a = v3d->y / v3d->x; + + v2d->x = (v3d->x >= 0) ? (-sqrt((rd * rd) / (L_a * L_a + 1))) : sqrt((rd * rd) / (L_a * L_a + 1)); + v2d->y = L_a * v2d->x; + +#endif +} + +void Equidistant(Vector3D* v3d, Vector2D* v2d, double f) +{ + double rd, ri, theta, phy; + + Normalize3D(v3d); + + // calculate theta from the angle between (0,0,1) and (x3d, y3d, z3d) + theta = acos(v3d->z); + + // calculate ri = f tan(theta) + ri = f * tan(theta); + if (theta == 0.0) { + ri += 1e-64; + theta += 1e-64; + } + + // calculate rd = f * theta + rd = f * (theta / (M_PI / 2)); + phy = atan(rd / f); + + // calculate new distorted vector (x,y,z) = (0,0,1) * (1-rd/ri) + (x3d, y3d, z3d) * (rd/ri) + Vector3D v3d_p; + + v3d_p.x = v3d->x * phy / theta; + v3d_p.y = v3d->y * phy / theta; + v3d_p.z = v3d->z * phy / theta + (1 - phy / theta); + + // calculate the target point (xi, yi) on image at z = f + v2d->x = (f / v3d_p.z) * v3d_p.x; + v2d->y = (f / v3d_p.z) * v3d_p.y; +} + +void Rotate3D(Vector3D* v3d, RotMatrix3D* mat) +{ + //int i, j; + Vector3D v1; + + v1.x = mat->coef[0][0] * v3d->x + mat->coef[0][1] * v3d->y + + mat->coef[0][2] * v3d->z + mat->coef[0][3]; + v1.y = mat->coef[1][0] * v3d->x + mat->coef[1][1] * v3d->y + + mat->coef[1][2] * v3d->z + mat->coef[1][3]; + v1.z = mat->coef[2][0] * v3d->x + mat->coef[2][1] * v3d->y + + mat->coef[2][2] * v3d->z + mat->coef[2][3]; + + v3d->x = v1.x; + v3d->y = v1.y; + v3d->z = v1.z; +} + +void GenRotMatrix3D(Vector3D* v3d, RotMatrix3D* mat) +{ + // generate the rotation matrix to + // rotate vector [0,0,1] to v3d + +#if 1 + double phy1, phy2; + Vector3D v1, v2; + + // 1. rotate v3d along X axis to have the vector lies in X-Z plane, i.e. y=0 and x is postive + // cos(phy1) * v3d->y + sin(phy1) * v3d->z = 0; + // solve phy1 + // v3d->y * cos(phy1) = -v3d->z * sin(phy1) + // -v3d->y / v3d->z = tan(phy1) + // phy1 = atan(-v3d->y/v3d->z) + // if(v3d->x <0) phy1 += MI_PI; + // update new v3d by Rx(phy1) + + + //從最後已經作完乘法的旋轉矩陣來看,如果要分別求得 θy, θx, θz ,其計算方式為: + //θy = arctan(r13 / r33) + //θx = arcsin(-r23) + //θz = arctan(r21 / r22) + + phy1 = atan(-v3d->y / v3d->z); + + v1.x = v3d->x; + v1.y = v3d->y * cos(phy1) + v3d->z * sin(phy1); + v1.z = -v3d->y * sin(phy1) + v3d->z * cos(phy1); + + // 2. rotate v3d along Y axis to have the vector lies in Z axis, i.e. x=0, y=0 and z is positive + // v3d->x * cos(phy2) - v3d->z * sin(phy2) = 0 + // v3d->x / v3d->z = tan(phy2) + // phy2 = atan(v3d->x / v3d->z) + // v3d->z = v3d->x * sin(phy2) + v3d->z*cos(phy2) + // if (v3d->z < 0) phy2 += M_PI; + phy2 = atan(v1.x / v1.z); + v2.z = v1.x * sin(phy2) + v1.z * cos(phy2); + if (v2.z < 0) phy2 += M_PI; + + v2.x = v1.x * cos(phy2) - v1.z * sin(phy2); + v2.y = v1.y; + v2.z = v1.x * sin(phy2) + v1.z * cos(phy2); + + // do the reverse rotation + // Rotation matrix = Rx(-phy1)*Ry(-phy2) + mat->coef[0][0] = cos(-phy2); + mat->coef[0][1] = 0; + mat->coef[0][2] = -sin(-phy2); + mat->coef[0][3] = 0; + mat->coef[1][0] = sin(-phy1) * sin(-phy2); + mat->coef[1][1] = cos(-phy1); + mat->coef[1][2] = sin(-phy1) * cos(-phy2); + mat->coef[1][3] = 0; + mat->coef[2][0] = cos(-phy1) * sin(-phy2); + mat->coef[2][1] = -sin(-phy1); + mat->coef[2][2] = cos(-phy1) * cos(-phy2); + mat->coef[2][3] = 0; + mat->coef[3][0] = 0; + mat->coef[3][1] = 0; + mat->coef[3][2] = 0; + mat->coef[3][3] = 1; +#else + mat->coef[0][0] = cos(θy) * cos(θz) - sin(θx) * sin(θy) * sin(θz); + mat->coef[0][1] = -cos(θx) * sin(θz); + mat->coef[0][2] = sin(θy) * cos(θz) + sin(θx) * cos(θy) * sin(θz); + mat->coef[0][3] = 0; + mat->coef[1][0] = cos(θy) * sin(θz) + sin(θx) * sin(θy) * cos(θz); + mat->coef[1][1] = cos(θx) * cos(θz); + mat->coef[1][2] = sin(θy) * sin(θz) - sin(θx) * cos(θy) * cos(θz); + mat->coef[1][3] = 0; + mat->coef[2][0] = -cos(θx) * sin(θy); + mat->coef[2][1] = sin(θx); + mat->coef[2][2] = cos(θx) * cos(θy); + mat->coef[2][3] = 0; + mat->coef[3][0] = 0; + mat->coef[3][1] = 0; + mat->coef[3][2] = 0; + mat->coef[3][3] = 1; +#endif +} + +void GenRotMatrix3D_YXZ(RotMatrix3D* mat, FISHEYE_REGION_ATTR* FISHEYE_REGION_IDX) +{ + // This Rotation Matrix Order = R = Rz*Rx*Ry + // rotation order = θy -> θx -> θz + //_LOAD_REGION_CONFIG; + // initital position + double tmp_phy_x = FISHEYE_REGION_IDX->ThetaX; //phy_x; + double tmp_phy_y = FISHEYE_REGION_IDX->ThetaY; //phy_y; // Not Used for Now. + double tmp_phy_z = FISHEYE_REGION_IDX->ThetaZ; //phy_z; + + //_LOAD_REGION_CONFIG(FISHEYE_CONFIG, FISHEYE_REGION); + // UI Control + double ctrl_tilt, ctrl_pan;// = minmax(FISHEYE_REGION_IDX[rgn_idx].Tilt - UI_CTRL_VALUE_CENTER, -UI_CTRL_VALUE_CENTER, UI_CTRL_VALUE_CENTER); + //double ctrl_pan = minmax(FISHEYE_REGION_IDX[rgn_idx].Pan - UI_CTRL_VALUE_CENTER, -UI_CTRL_VALUE_CENTER, UI_CTRL_VALUE_CENTER); + + if (FISHEYE_REGION_IDX->ViewMode == PROJECTION_REGION) + { + ctrl_tilt = minmax(FISHEYE_REGION_IDX->Tilt - UI_CTRL_VALUE_CENTER, -UI_CTRL_VALUE_CENTER, UI_CTRL_VALUE_CENTER); + ctrl_pan = minmax(FISHEYE_REGION_IDX->Pan - UI_CTRL_VALUE_CENTER, -UI_CTRL_VALUE_CENTER, UI_CTRL_VALUE_CENTER); + } + else + { + // not used in panorama case + ctrl_pan = 0; + ctrl_tilt = 0; + } + + tmp_phy_x += (ctrl_tilt * M_PI / 2)/(2* UI_CTRL_VALUE_CENTER); + tmp_phy_y += 0; + tmp_phy_z += (ctrl_pan * M_PI)/(2* UI_CTRL_VALUE_CENTER); + + mat->coef[0][0] = cos(tmp_phy_y) * cos(tmp_phy_z) - sin(tmp_phy_x) * sin(tmp_phy_y) * sin(tmp_phy_z); + mat->coef[0][1] = -cos(tmp_phy_x) * sin(tmp_phy_z); + mat->coef[0][2] = sin(tmp_phy_y) * cos(tmp_phy_z) + sin(tmp_phy_x) * cos(tmp_phy_y) * sin(tmp_phy_z); + mat->coef[0][3] = 0; + mat->coef[1][0] = cos(tmp_phy_y) * sin(tmp_phy_z) + sin(tmp_phy_x) * sin(tmp_phy_y) * cos(tmp_phy_z); + mat->coef[1][1] = cos(tmp_phy_x) * cos(tmp_phy_z); + mat->coef[1][2] = sin(tmp_phy_y) * sin(tmp_phy_z) - sin(tmp_phy_x) * cos(tmp_phy_y) * cos(tmp_phy_z); + mat->coef[1][3] = 0; + mat->coef[2][0] = -cos(tmp_phy_x) * sin(tmp_phy_y); + mat->coef[2][1] = sin(tmp_phy_x); + mat->coef[2][2] = cos(tmp_phy_x) * cos(tmp_phy_y); + mat->coef[2][3] = 0; + mat->coef[3][0] = 0; + mat->coef[3][1] = 0; + mat->coef[3][2] = 0; + mat->coef[3][3] = 1; +} + +void _do_mesh_rotate(int rotate_index, int view_h, int view_w, double xin, double yin, double *xout, double *yout) +{ + double RMATRIX[2][2]; + + if (rotate_index == 0) //00 degrees + { + RMATRIX[0][0] = 1; + RMATRIX[0][1] = 0; + RMATRIX[1][0] = 0; + RMATRIX[1][1] = 1; + } + else if (rotate_index == 1) //-90 degrees + { + RMATRIX[0][0] = 0; + RMATRIX[0][1] = 1; + RMATRIX[1][0] = -1; + RMATRIX[1][1] = 0; + } + else if (rotate_index == 2) // + 90 degrees + { + RMATRIX[0][0] = -1; + RMATRIX[0][1] = 0; + RMATRIX[1][0] = 0; + RMATRIX[1][1] = -1; + } + else + { + RMATRIX[0][0] = 0; + RMATRIX[0][1] = -1; + RMATRIX[1][0] = 1; + RMATRIX[1][1] = 0; + } + + *xout = RMATRIX[0][0] * xin + RMATRIX[1][0] * yin; + *yout = RMATRIX[0][1] * xin + RMATRIX[1][1] * yin; + + +#if 0 + //printf("view_h = %d\n", view_h); + //printf("view_w = %d\n", view_w); + + printf(" RMATRIX[0][0] = %f\n", RMATRIX[0][0]); + printf(" RMATRIX[0][1] = %f\n", RMATRIX[0][1]); + printf(" RMATRIX[1][0] = %f\n", RMATRIX[1][0]); + printf(" RMATRIX[1][1] = %f\n", RMATRIX[1][1]); + + printf("xin = %f\n", xin); + printf("yin = %f\n", yin); + printf("xout = %f\n", xout); + printf("yout = %f\n", yout); + system("pause"); +#endif + + if (rotate_index == 0) { + *xout = *xout; + *yout = *yout; + } else if (rotate_index == 1) { + *xout = *xout + (view_h - 1); + *yout = *yout; + } else if (rotate_index == 2) { + *xout = *xout + (view_w - 1); + *yout = *yout + (view_h - 1); + } else { + *xout = *xout + 0; + *yout = *yout + (view_w - 1); + } +} + +void _get_frame_mesh_list(FISHEYE_ATTR* FISHEYE_CONFIG, FISHEYE_REGION_ATTR* FISHEYE_REGION) +{ + // pack all regions' mesh info, including src & dst. + int rgnNum = FISHEYE_CONFIG->RgnNum; + int meshNumRgn; + int frameMeshIdx = 0; + int rotate_index = FISHEYE_CONFIG->rotate_index; + int view_w = FISHEYE_CONFIG->OutW_disp; + int view_h = FISHEYE_CONFIG->OutH_disp; + + for (int i = 0; i < rgnNum; i++) { + if (FISHEYE_REGION[i].RegionValid == 1) { + meshNumRgn = (FISHEYE_REGION[i].MeshHor * FISHEYE_REGION[i].MeshVer); + + // go through each region loop + for (int meshidx = 0; meshidx < meshNumRgn; meshidx++) { + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) { + // do rotaion: + double x_src = FISHEYE_REGION[i].SrcRgnMeshInfo[meshidx].knot[knotidx].xcor; + double y_src = FISHEYE_REGION[i].SrcRgnMeshInfo[meshidx].knot[knotidx].ycor; + double x_dst = FISHEYE_REGION[i].DstRgnMeshInfo[meshidx].knot[knotidx].xcor; + double y_dst = FISHEYE_REGION[i].DstRgnMeshInfo[meshidx].knot[knotidx].ycor; + + double x_dst_out, y_dst_out; + _do_mesh_rotate(rotate_index, view_h, view_w, x_dst, y_dst, &x_dst_out, &y_dst_out); + + FISHEYE_CONFIG->DstRgnMeshInfo[frameMeshIdx].knot[knotidx].xcor = x_dst_out; //FISHEYE_REGION[i].DstRgnMeshInfo[meshidx].knot[knotidx].xcor; + FISHEYE_CONFIG->DstRgnMeshInfo[frameMeshIdx].knot[knotidx].ycor = y_dst_out; //FISHEYE_REGION[i].DstRgnMeshInfo[meshidx].knot[knotidx].ycor; + FISHEYE_CONFIG->SrcRgnMeshInfo[frameMeshIdx].knot[knotidx].xcor = x_src; //FISHEYE_REGION[i].SrcRgnMeshInfo[meshidx].knot[knotidx].xcor; + FISHEYE_CONFIG->SrcRgnMeshInfo[frameMeshIdx].knot[knotidx].ycor = y_src; //FISHEYE_REGION[i].SrcRgnMeshInfo[meshidx].knot[knotidx].ycor; + } + frameMeshIdx += 1; + } + } + } + + // update mesh index number + FISHEYE_CONFIG->TotalMeshNum = frameMeshIdx; +} + +void _Panorama180View2(FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx, FISHEYE_MOUNT_MODE_E MOUNT, double x0, double y0, double r) +{ + if (FISHEYE_REGION[rgn_idx].ViewMode != PROJECTION_PANORAMA_180) + return; + if (MOUNT != FISHEYE_WALL_MOUNT) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mount_mode(%d) not supported in Panorama180\n", MOUNT); + return; + } + + int view_w = FISHEYE_REGION[rgn_idx].OutW; + int view_h = FISHEYE_REGION[rgn_idx].OutH; + int tot_mesh_cnt = FISHEYE_REGION[rgn_idx].MeshHor * FISHEYE_REGION[rgn_idx].MeshVer; + + //printf("view_w = %d, view_h = %d, \n", view_w, view_h); + //printf("mesh_horcnt = %d,\n", mesh_horcnt); + //printf("mesh_vercnt = %d,\n", mesh_vercnt); + + + // UI PARAMETERS + int _UI_horViewOffset = FISHEYE_REGION[rgn_idx].Pan; // value range = 0 ~ 360, => -180 ~ 0 ~ +180 + int _UI_verViewOffset = FISHEYE_REGION[rgn_idx].Tilt; // value = 0 ~ 360, center = 180 ( original ) => -180 ~ 0 ~ + 180 + int _UI_horViewRange = FISHEYE_REGION[rgn_idx].ZoomH; // value = 0 ~ 4095, symmeterically control horizontal View Range, ex: value = 4095 => hor view angle = -90 ~ + 90 + int _UI_verViewRange = FISHEYE_REGION[rgn_idx].ZoomV; // value = 0 ~ 4095, symmetrically control vertical view range. ex: value = 4096, ver view angle = -90 ~ + 90 + + _UI_verViewRange = (_UI_verViewRange == 4095) ? 4096 : _UI_verViewRange; + _UI_horViewRange = (_UI_horViewRange == 4095) ? 4096 : _UI_horViewRange; + + //printf("_UI_horViewOffset = %d,\n", _UI_horViewOffset); + //printf("_UI_verViewOffset = %d,\n", _UI_verViewOffset); + //printf("_UI_horViewRange = %d,\n", _UI_horViewRange); + //printf("_UI_verViewRange = %d,\n", _UI_verViewRange); + + // calculate default view range: + double view_range_ver_degs = (double)_UI_verViewRange * 90 / 4096; + double view_range_hor_degs = (double)_UI_horViewRange * 90 / 4096; + double va_ver_degs = view_range_ver_degs; + double va_hor_degs = view_range_hor_degs; + + // calculate offsets + double va_hor_offset = ((double)_UI_horViewOffset - 180) * 90 / 360; + double va_ver_offset = ((double)_UI_verViewOffset - 180) * 90 / 360; + + //printf("va_hor_offset = %f,\n", va_hor_offset); + //printf("va_ver_offset = %f,\n", va_ver_offset); + + // Offset to shift view angle + double va_ver_start = minmax(90 - va_ver_degs + va_ver_offset, 0, 90); + double va_ver_end = minmax(90 + va_ver_degs + va_ver_offset, 90, 180); + double va_hor_start = minmax(90 - va_hor_degs + va_hor_offset, 0, 90); + double va_hor_end = minmax(90 + va_hor_degs + va_hor_offset, 90, 180); + + //printf("va_ver_start = %f,\n", va_ver_start); + //printf("va_ver_end = %f,\n", va_ver_end); + //printf("va_hor_start = %f,\n", va_hor_start); + //printf("va_hor_end = %f,\n", va_hor_end); + + //system("pause"); + + RotMatrix3D mat0; + + Vector3D pix3d; + Vector2D dist2d; + int X_offset = FISHEYE_REGION[rgn_idx].OutX + FISHEYE_REGION[rgn_idx].OutW / 2; + int Y_offset = FISHEYE_REGION[rgn_idx].OutY + FISHEYE_REGION[rgn_idx].OutH / 2; + + for (int i = 0; i < tot_mesh_cnt; i++) + { + //printf("i = %d,", i); + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) + { + double x = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor - X_offset; + double y = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].ycor - Y_offset; + //double z = r; + + // initial pseudo plane cooridinates as vp3d + //double theta_hor_cur = va_hor_start + ((2 * va_hor_degs * (view_w / 2 - x)) / (double)view_w); + double theta_hor_cur = va_hor_start + (((va_hor_end - va_hor_start) * (view_w / 2 - x)) / (double)view_w); + double theta_hor_cur_rad = M_PI / 2 - (theta_hor_cur * M_PI) / 180; //θx + + double theta_ver_cur = va_ver_start + (((va_ver_end - va_ver_start) * (view_h / 2 - y)) / (double)view_h); + double theta_ver_cur_rad = M_PI / 2 - (theta_ver_cur * M_PI) / 180; //θy + + //if (knotidx == 0) + //{ + // printf("(x,y)=(%f,%f) FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor = %f, ", x, y, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor); + // printf("hor_deg = %f, ver_deg = %f,\n\r",theta_hor_cur, theta_ver_cur); + // //printf("hor_rad = %f, ver_rad = %f, \n\r", theta_hor_cur_rad, theta_ver_cur_rad); + //} + + double theta_x = theta_hor_cur_rad; + double theta_y = theta_ver_cur_rad; + double theta_z = (M_PI / 2); + + FISHEYE_REGION[rgn_idx].ThetaX = theta_x; + FISHEYE_REGION[rgn_idx].ThetaY = theta_y; + FISHEYE_REGION[rgn_idx].ThetaZ = theta_z; + + GenRotMatrix3D_YXZ(&mat0, &FISHEYE_REGION[rgn_idx]); + + pix3d.x = 0; + pix3d.y = 0; + pix3d.z = 1; + + Rotate3D(&pix3d, &mat0); + + // generate new 3D vector thru rotated pixel + //Normalize3D(&pix3d); + + // generate 2D location on distorted image + //Equidistant_Panorama(&pix3d, &dist2d, r); + Equidistant(&pix3d, &dist2d, r); + + // update source mesh-info here + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].xcor = dist2d.x + x0; + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].ycor = dist2d.y + y0; + + //printf("(x2d)(%f,%f),\n\r",dist2d.x + x0, dist2d.y + y0); + + } + } +} + +void _Panorama360View2( FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx, FISHEYE_MOUNT_MODE_E MOUNT, double x0, double y0, double r) +{ + if (FISHEYE_REGION[rgn_idx].ViewMode != PROJECTION_PANORAMA_360) + return; + if ((MOUNT != FISHEYE_CEILING_MOUNT) && (MOUNT != FISHEYE_DESKTOP_MOUNT)) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mount_mode(%d) not supported in Panorama360\n", MOUNT); + return; + } + + int view_w = FISHEYE_REGION[rgn_idx].OutW; + int view_h = FISHEYE_REGION[rgn_idx].OutH; + int tot_mesh_cnt = FISHEYE_REGION[rgn_idx].MeshHor * FISHEYE_REGION[rgn_idx].MeshVer; + + //Vector2D vp2d; + //Vector3D vp3d; + //RotMatrix3D mat0; + + Vector3D pix3d; + Vector2D dist2d; + + // UI PARAMETERS + //float _UI_start_angle = FISHEYE_REGION[rgn_idx].Pan; // value from 0=360, 0 ~ 356 is the range of adjustment. + float _UI_view_offset = FISHEYE_REGION[rgn_idx].Tilt; // value = 0 ~ 360, center = 180 ( original ), OR create offset to shift OutRadius & InRadius ( = adjust theta angle in our implementation ) + float _UI_inradius = FISHEYE_REGION[rgn_idx].InRadius; // value = 0 ~ 4095 + float _UI_outradius = FISHEYE_REGION[rgn_idx].OutRadius; // value = 0 ~ 4095 + float _UI_zoom_outradius = FISHEYE_REGION[rgn_idx].ZoomV; // a ratio to zoom OutRadius length. + + _UI_inradius = (_UI_inradius >= 4095) ? 4096 : _UI_inradius; + _UI_outradius = (_UI_outradius >= 4095) ? 4096 : _UI_outradius; + _UI_zoom_outradius = (_UI_zoom_outradius >= 4095) ? 4096 : _UI_zoom_outradius; + + int start_angle_degrees = FISHEYE_REGION[rgn_idx].Pan; + int end_angle__degrees = FISHEYE_REGION[rgn_idx].PanEnd; + + + float raw_outradius_pxl = (_UI_outradius * r )/ 4096; + float raw_inradius_pxl = (_UI_inradius * r )/ 4096; + float radiusOffset = (raw_outradius_pxl * (_UI_view_offset - 180)) / 360; + + float inradius_pxl_final = MIN(r, MAX(0, raw_inradius_pxl + radiusOffset)); + float outradius_pxl_final = MIN(r, MAX(inradius_pxl_final, raw_inradius_pxl + (MAX(0, (raw_outradius_pxl - raw_inradius_pxl)) * _UI_zoom_outradius) / 4096 + radiusOffset)); + + //printf("r = %f,\n", r); + + //printf("raw_outradius_pxl = %f,\n", raw_outradius_pxl); + //printf("raw_inradius_pxl = %f,\n", raw_inradius_pxl); + //printf("radiusOffset = %f,\n", radiusOffset); + //printf("inradius_pxl_final = %f,\n", inradius_pxl_final); + //printf("outradius_pxl_final = %f,\n", outradius_pxl_final); + + float va_ver_end_rads = inradius_pxl_final * M_PI / (2 * r);//_UI_inradius * M_PI / 1024; // for Equidistant =>rd = f*theta, rd_max = f*PI/2 = r ( in code), f = 2r/PI. => theta = rd/f = rd*PI/2r + float va_ver_start_rads = outradius_pxl_final * M_PI / (2 * r);//_UI_outradius * M_PI / 1024; + float va_ver_rads = MIN( M_PI/2, va_ver_start_rads - va_ver_end_rads); + + //printf("va_ver_end_rads = %f,\n", va_ver_end_rads); + //printf("va_ver_start_rads = %f,\n", va_ver_start_rads); + //printf("va_ver_rads = %f,\n", va_ver_rads); + + + //printf("( %d, %d, %d, %f, %f, %d,) \n", rgn_idx, _UI_start_angle, _UI_view_offset, _UI_inradius, _UI_outradius, _UI_zoom_outradius); + //printf("start_angle_degrees = %d, end_angle__degrees = %d, va_ver_degs = %f, va_ver_start_degs = %f, \n\r", start_angle_degrees, end_angle__degrees, va_ver_rads, va_ver_start_rads); + //system("pause"); + + + int total_angle = (360 + (end_angle__degrees - start_angle_degrees)) % 360; + int half_w = view_w / 2; + int half_h = view_h / 2; + int X_offset = FISHEYE_REGION[rgn_idx].OutX + FISHEYE_REGION[rgn_idx].OutW / 2; + int Y_offset = FISHEYE_REGION[rgn_idx].OutY + FISHEYE_REGION[rgn_idx].OutH / 2; + + for (int i = 0; i < tot_mesh_cnt; i++) + { + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) + { + double phi_degrees, phi_rad, theta_rv; + + double x = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor - X_offset; + double y = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].ycor - Y_offset; + + if(MOUNT == FISHEYE_DESKTOP_MOUNT) { + phi_degrees = (total_angle * (half_w - x )) / (double)view_w; + phi_rad = (((start_angle_degrees + phi_degrees) * M_PI)) / 180; + //theta_rv = (((va_ver_degs * M_PI) / 180) * (y + (view_h / 2))) / (double)(view_h); + theta_rv = ( va_ver_rads * (y + half_h)) / (double)(view_h); + } else if (MOUNT == FISHEYE_CEILING_MOUNT) { + phi_degrees = (total_angle * (half_w + x)) / (double)view_w; + phi_rad = (((start_angle_degrees + phi_degrees) * M_PI)) / 180; + //theta_rv = (((va_ver_degs * M_PI) / 180) * ((view_h / 2) - y)) / (double)(view_h); + theta_rv = ( va_ver_rads * (half_h - y)) / (double)(view_h); + } + + + // 2D plane cooridnate to cylinder + // rotation initial @ [x, y, z] = [1, 0, 0]; + double xc = 1 * cos(-phi_rad) + 0 * sin(-phi_rad); + double yc = -1 * sin(-phi_rad) + 0 * cos(-phi_rad); + double zc = theta_rv + va_ver_end_rads; + + //Rotate3D(&pix3d, &mat0); + pix3d.x = xc; + pix3d.y = yc; + pix3d.z = zc; + //Equidistant(&pix3d, &dist2d, r); + + Equidistant_Panorama(&pix3d, &dist2d, r); + + // update source mesh-info here + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].xcor = dist2d.x + x0; + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].ycor = dist2d.y + y0; + } + } + +} + +void _LDC_View(FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx, double x0, double y0) +{ + if (FISHEYE_REGION[rgn_idx].ViewMode != PROJECTION_LDC) + return; + + int view_w = FISHEYE_REGION[rgn_idx].OutW; + int view_h = FISHEYE_REGION[rgn_idx].OutH; + int mesh_horcnt = FISHEYE_REGION[rgn_idx].MeshHor; + int mesh_vercnt = FISHEYE_REGION[rgn_idx].MeshVer; + + + // register: + bool bAspect = (bool)FISHEYE_REGION[0].ZoomV; + int XYRatio = minmax(FISHEYE_REGION[0].Pan, 0, 100); + int XRatio = minmax(FISHEYE_REGION[0].ThetaX, 0, 100); + int YRatio = minmax(FISHEYE_REGION[0].ThetaZ, 0, 100); + int CenterXOffset = minmax(FISHEYE_REGION[0].InRadius, -511, 511); + int CenterYOffset = minmax(FISHEYE_REGION[0].OutRadius, -511, 511); + int DistortionRatio = minmax(FISHEYE_REGION[0].PanEnd, -300, 500); + + + double norm = sqrt((view_w / 2) * (view_w / 2) + (view_h / 2) * (view_h / 2)); + + + // internal link to register: + double k = (double)DistortionRatio / 1000.0; + double ud_gain = (1 + k * (((double)view_h / 2) * (double)view_h / 2) / norm / norm); + double lr_gain = (1 + k * (((double)view_w / 2) * (double)view_w / 2) / norm / norm); + + + double Aspect_gainX = MAX2(ud_gain, lr_gain); + double Aspect_gainY = MAX2(ud_gain, lr_gain); + + + Vector2D dist2d; + + // go through all meshes in thus regions + for (int i = 0; i < (mesh_horcnt * mesh_vercnt); i++) { + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) { + // display window center locate @ (0,0), mesh info shife back to center O. + // for each region, rollback center is (0,0) + double x = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor + - FISHEYE_REGION[rgn_idx].OutX - FISHEYE_REGION[rgn_idx].OutW / 2; + double y = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].ycor + - FISHEYE_REGION[rgn_idx].OutY - FISHEYE_REGION[rgn_idx].OutH / 2; + + + x = minmax(x - CenterXOffset, -view_w / 2 + 1, view_w / 2 - 1); + y = minmax(y - CenterYOffset, -view_h / 2 + 1, view_h / 2 - 1); + + + x = x / Aspect_gainX; + y = y / Aspect_gainY; + + if (bAspect == true) { + x = x * (1 - 0.333 * (100 - XYRatio)/100); + y = y * (1 - 0.333 * (100 - XYRatio)/100); + } else { + x = x * (1 - 0.333 * (100 - XRatio)/100); + y = y * (1 - 0.333 * (100 - YRatio)/100); + } + + double rd = sqrt(x * x + y * y); + + // Zooming In/Out Control by ZoomH & ZoomV + // 1.0 stands for +- 50% of zoomH ratio. => set as + dist2d.x = x * (1 + k * ((rd / norm) * (rd / norm))); + dist2d.y = y * (1 + k * ((rd / norm) * (rd / norm))); + + // update source mesh-info here + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].xcor = dist2d.x + x0 + CenterXOffset; + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].ycor = dist2d.y + y0 + CenterYOffset; + } + } +} + +void _RegionView2( FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx, FISHEYE_MOUNT_MODE_E MOUNT, double x0, double y0, double r) +{ + if (FISHEYE_REGION[rgn_idx].ViewMode != PROJECTION_REGION) + return; + + //int view_w = FISHEYE_REGION[rgn_idx].OutW; + //int view_h = FISHEYE_REGION[rgn_idx].OutH; + int tot_mesh_cnt = FISHEYE_REGION[rgn_idx].MeshHor * FISHEYE_REGION[rgn_idx].MeshVer; + + // rotation matrix to point out view center of this region. + RotMatrix3D mat0; + GenRotMatrix3D_YXZ(&mat0, &FISHEYE_REGION[rgn_idx]); + + Vector3D pix3d; + Vector2D dist2d; + int X_offset = FISHEYE_REGION[rgn_idx].OutX + FISHEYE_REGION[rgn_idx].OutW / 2; + int Y_offset = FISHEYE_REGION[rgn_idx].OutY + FISHEYE_REGION[rgn_idx].OutH / 2; + double w_ratio = 1.0 * (FISHEYE_REGION[rgn_idx].ZoomH - 2048) / 2048; + double h_ratio = 1.0 * (FISHEYE_REGION[rgn_idx].ZoomV - 2048) / 2048; + + // go through all meshes in thus regions + // mat0 is decided by view angle defined in re gion config. + for (int i = 0; i < tot_mesh_cnt; i++) + { + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) + { + // display window center locate @ (0,0), mesh info shife back to center O. + // for each region, rollback center is (0,0) + double x = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].xcor - X_offset; + double y = FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[i].knot[knotidx].ycor - Y_offset; + double z = r; + + + if (MOUNT == FISHEYE_DESKTOP_MOUNT) { + x = -x; + y = -y; + } + + + // Zooming In/Out Control by ZoomH & ZoomV + // 1.0 stands for +- 50% of zoomH ratio. => set as + x = x *(1 + w_ratio); + y = y *(1 + h_ratio); + + //printf("(x,y)=(%f,%f)\n\r", x, y); + + pix3d.x = x; + pix3d.y = y; + pix3d.z = z; + + // Region Porjection Model + Rotate3D(&pix3d, &mat0); + Equidistant(&pix3d, &dist2d, r); + + // update source mesh-info here + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].xcor = dist2d.x + x0; + FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].ycor = dist2d.y + y0; + //printf("rgn(%d) mesh(%d) node(%d) (%lf %lf)\n", rgn_idx, i, knotidx, FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].xcor, FISHEYE_REGION[rgn_idx].SrcRgnMeshInfo[i].knot[knotidx].ycor); + } + } +} + +void _get_region_src_mesh_list(FISHEYE_MOUNT_MODE_E MOUNT, FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx, double x0, double y0, double r) +{ + // ViewModeType to decide mapping & UI contrl parameters. + PROJECTION_MODE ViewModeType = FISHEYE_REGION[rgn_idx].ViewMode; + + if (ViewModeType == PROJECTION_REGION) + _RegionView2( FISHEYE_REGION, rgn_idx, MOUNT, x0, y0, r); + else if (ViewModeType == PROJECTION_PANORAMA_360) + _Panorama360View2( FISHEYE_REGION, rgn_idx, MOUNT, x0, y0, r); + else if (ViewModeType == PROJECTION_PANORAMA_180) + _Panorama180View2(FISHEYE_REGION, rgn_idx, MOUNT, x0, y0, r); + else if (ViewModeType == PROJECTION_LDC) + _LDC_View(FISHEYE_REGION, rgn_idx, x0, y0); + else + printf("ERROR!!! THIS CASE SHOULDNOTHAPPEN!!!!!!\n\r"); +} + +void _get_region_dst_mesh_list(FISHEYE_REGION_ATTR* FISHEYE_REGION, int rgn_idx) +{ + if (FISHEYE_REGION[rgn_idx].RegionValid != 1) + return; + + // Destination Mesh-Info Allocation + int view_w = FISHEYE_REGION[rgn_idx].OutW; + int view_h = FISHEYE_REGION[rgn_idx].OutH; + int mesh_horcnt = FISHEYE_REGION[rgn_idx].MeshHor; + int mesh_vercnt = FISHEYE_REGION[rgn_idx].MeshVer; + + //printf("view_w(%d) view_h(%d) mesh_horcnt(%d) mesh_vercnt(%d)\n", view_w, view_h, mesh_horcnt, mesh_vercnt); + int knot_horcnt = mesh_horcnt + 1; + int knot_vercnt = mesh_vercnt + 1; + // tmp internal buffer + // maximum knot number = 1024 (pre-set) + COORDINATE2D *meshknot_hit_buf = malloc(sizeof(COORDINATE2D) * (knot_horcnt * knot_vercnt + 1)); + + // 1st loop: to find mesh infos. on source ( backward projection ) + // hit index for buffer + int knotcnt = 0; + int mesh_w = (view_w / mesh_horcnt); + int mesh_h = (view_h / mesh_vercnt); + int half_w = view_w / 2; + int half_h = view_h / 2; + //printf("mesh_w(%d) mesh_h(%d)\n", mesh_w, mesh_h); +#if 0 + for (int y = -half_h; y < half_h; ++y) { + bool yknot_hit = ((y + half_h) % mesh_h) == 0; + bool LastMeshFixY = ((y + half_h) == (mesh_h * mesh_vercnt)) && (view_h != mesh_h * mesh_vercnt); + + for (int x = -half_w; x < half_w; x++) { + bool xknot_hit = ((x + half_w) % mesh_w) == 0; + bool hitknot = ((xknot_hit && yknot_hit) + || (((x + 1) == (half_w)) && yknot_hit) + || (xknot_hit && ((y + 1) == (half_h))) + || (((x + 1) == (half_w)) && ((y + 1) == (half_h)))); + + // LastMeshFix is to fix unequal mesh block counts. + bool LastMeshFixX = ((x + half_w) == (mesh_w * mesh_horcnt)) && (view_w != mesh_w * mesh_horcnt); + + hitknot = hitknot && !(LastMeshFixX || LastMeshFixY); + + if (hitknot) { + meshknot_hit_buf[knotcnt].xcor = FISHEYE_REGION[rgn_idx].OutX + (x + half_w); + meshknot_hit_buf[knotcnt].ycor = FISHEYE_REGION[rgn_idx].OutY + (y + half_h); + //printf("%d(%lf %lf)\n", knotcnt, meshknot_hit_buf[knotcnt].xcor, meshknot_hit_buf[knotcnt].ycor); + knotcnt += 1; + } + } + } +#else + int y = -half_h; + for (int j = knot_horcnt; j > 0; --j) { + int x = -half_w; + for (int i = knot_horcnt; i > 0; --i) { + meshknot_hit_buf[knotcnt].xcor = FISHEYE_REGION[rgn_idx].OutX + (x + half_w); + meshknot_hit_buf[knotcnt].ycor = FISHEYE_REGION[rgn_idx].OutY + (y + half_h); + //printf("%d(%lf %lf)\n", knotcnt, meshknot_hit_buf[knotcnt].xcor, meshknot_hit_buf[knotcnt].ycor); + knotcnt += 1; + x += mesh_w; + if (i == 2) + x = half_w; + } + y += mesh_h; + if (j == 2) + y = half_h; + } +#endif + + meshknot_hit_buf[knotcnt].xcor = 0xFFFFFFFF; //End of Knot List. + meshknot_hit_buf[knotcnt].ycor = 0xFFFFFFFF; //End of Knot List + CVI_TRACE_GDC(CVI_DBG_DEBUG, "knotcnt(%d)\n", knotcnt); + // tmp for debug + + for (int j = 0; j < mesh_vercnt; j++) { + for (int i = 0; i < mesh_horcnt; i++) { + int meshidx = j * mesh_horcnt + i; + int knotidx = j * (mesh_horcnt + 1) + i; // knot num = mesh num +1 ( @ horizon ) + + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].xcor = meshknot_hit_buf[knotidx].xcor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].ycor = meshknot_hit_buf[knotidx].ycor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].xcor = meshknot_hit_buf[knotidx + 1].xcor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].ycor = meshknot_hit_buf[knotidx + 1].ycor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].xcor = meshknot_hit_buf[knotidx + (mesh_horcnt + 1)].xcor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].ycor = meshknot_hit_buf[knotidx + (mesh_horcnt + 1)].ycor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].xcor = meshknot_hit_buf[knotidx + 1 + (mesh_horcnt + 1)].xcor; + FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].ycor = meshknot_hit_buf[knotidx + 1 + (mesh_horcnt + 1)].ycor; + + //printf("mesh[%d] = (%f,%f),(%f,%f),(%f,%f),(%f,%f)\n\r", meshidx, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].xcor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].ycor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].xcor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].ycor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].xcor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].ycor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].xcor, FISHEYE_REGION[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].ycor); + //system("pause"); + } + } + + free(meshknot_hit_buf); +} + +/* aspect_ratio_resize: calculate the new rect to keep aspect ratio + * according to given in/out size. + * + * @param in: input video size. + * @param out: output display size. + * + * @return: the rect which describe the video on output display. + */ +RECT_S aspect_ratio_resize(SIZE_S in, SIZE_S out) +{ + RECT_S rect; + float ratio = MIN2((float)out.u32Width / in.u32Width, (float)out.u32Height / in.u32Height); + + rect.u32Height = (float)in.u32Height * ratio + 0.5; + rect.u32Width = (float)in.u32Width * ratio + 0.5; + rect.s32X = (out.u32Width - rect.u32Width) >> 1; + rect.s32Y = (out.u32Height - rect.u32Height) >> 1; + return rect; +} + +void _LOAD_REGION_CONFIG(FISHEYE_ATTR* FISHEYE_CONFIG, FISHEYE_REGION_ATTR* FISHEYE_REGION) +{ + // to make sure parameters aligned to frame ratio + double width_sec = FISHEYE_CONFIG->OutW_disp / 40; + double height_sec = FISHEYE_CONFIG->OutH_disp / 40; + + // load default settings + if (FISHEYE_CONFIG->UsageMode == MODE_02_1O4R ) + { + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 8; + FISHEYE_REGION[0].MeshHor = 8; + FISHEYE_REGION[0].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[0].ThetaX = M_PI / 4; + FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ThetaY = 0; + FISHEYE_REGION[0].ZoomH = 2048; // zooming factor for horizontal: 0 ~ 4095 to control view + FISHEYE_REGION[0].ZoomV = 2048; // zooming factor for vertical: 0 ~ 4095 to control view + FISHEYE_REGION[0].Pan = UI_CTRL_VALUE_CENTER; // center = 180, value = 0 ~ 360 => value = +- 180 degrees + FISHEYE_REGION[0].Tilt = UI_CTRL_VALUE_CENTER; // center = 180, value = 0 ~ 360 => value = +-30 degrees + FISHEYE_REGION[0].OutW = (width_sec * 15); + FISHEYE_REGION[0].OutH = (height_sec * 20); + FISHEYE_REGION[0].OutX = 0; + FISHEYE_REGION[0].OutY = 0; + + FISHEYE_REGION[1].RegionValid = 1; + FISHEYE_REGION[1].MeshVer = 8; + FISHEYE_REGION[1].MeshHor = 8; + FISHEYE_REGION[1].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[1].ThetaX = M_PI / 4; + FISHEYE_REGION[1].ThetaZ = M_PI / 2; + FISHEYE_REGION[1].ThetaY = 0; + FISHEYE_REGION[1].ZoomH = 2048; + FISHEYE_REGION[1].ZoomV = 2048; + FISHEYE_REGION[1].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[1].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[1].OutW = (width_sec * 15); + FISHEYE_REGION[1].OutH = (height_sec * 20); + FISHEYE_REGION[1].OutX = (width_sec * 15); + FISHEYE_REGION[1].OutY = (height_sec * 0); + + FISHEYE_REGION[2].RegionValid = 1; + FISHEYE_REGION[2].MeshVer = 8; + FISHEYE_REGION[2].MeshHor = 8; + FISHEYE_REGION[2].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[2].ThetaX = M_PI / 4; + FISHEYE_REGION[2].ThetaZ = M_PI; + FISHEYE_REGION[2].ThetaY = 0; + FISHEYE_REGION[2].ZoomH = 2048; + FISHEYE_REGION[2].ZoomV = 2048; + FISHEYE_REGION[2].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[2].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[2].OutW = (width_sec * 15); + FISHEYE_REGION[2].OutH = (height_sec * 20); + FISHEYE_REGION[2].OutX = (width_sec * 0); + FISHEYE_REGION[2].OutY = (height_sec * 20); + + FISHEYE_REGION[3].RegionValid = 1; + FISHEYE_REGION[3].MeshVer = 8; + FISHEYE_REGION[3].MeshHor = 8; + FISHEYE_REGION[3].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[3].ThetaX = M_PI / 4; + FISHEYE_REGION[3].ThetaZ = 3 * M_PI / 2; + FISHEYE_REGION[3].ThetaY = 0; + FISHEYE_REGION[3].ZoomH = 2048; + FISHEYE_REGION[3].ZoomV = 2048; + FISHEYE_REGION[3].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[3].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[3].OutW = (width_sec * 15); + FISHEYE_REGION[3].OutH = (height_sec * 20); + FISHEYE_REGION[3].OutX = (width_sec * 15); + FISHEYE_REGION[3].OutY = (height_sec * 20); + + FISHEYE_REGION[4].RegionValid = 0; + } + else if (FISHEYE_CONFIG->UsageMode == MODE_03_4R) + { + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 16; + FISHEYE_REGION[0].MeshHor = 16; + FISHEYE_REGION[0].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[0].ThetaX = 0.4*M_PI; + FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ThetaY = 0; + FISHEYE_REGION[0].ZoomH = 2048; // zooming factor for horizontal: 0 ~ 4095 to control view + FISHEYE_REGION[0].ZoomV = 2048; // zooming factor for vertical: 0 ~ 4095 to control view + FISHEYE_REGION[0].Pan = UI_CTRL_VALUE_CENTER; // center = 180, value = 0 ~ 360 => value = +- 180 degrees + FISHEYE_REGION[0].Tilt = UI_CTRL_VALUE_CENTER; // center = 180, value = 0 ~ 360 => value = +-30 degrees + FISHEYE_REGION[0].OutW = (width_sec * 20); + FISHEYE_REGION[0].OutH = (height_sec * 20); + FISHEYE_REGION[0].OutX = 0;//(width_sec * 2); + FISHEYE_REGION[0].OutY = 0;//(height_sec * 2); + + FISHEYE_REGION[1].RegionValid = 1; + FISHEYE_REGION[1].MeshVer = 16; + FISHEYE_REGION[1].MeshHor = 16; + FISHEYE_REGION[1].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[1].ThetaX = 0.4 * M_PI; + FISHEYE_REGION[1].ThetaZ = M_PI / 2; + FISHEYE_REGION[1].ThetaY = 0; + FISHEYE_REGION[1].ZoomH = 2048; + FISHEYE_REGION[1].ZoomV = 2048; + FISHEYE_REGION[1].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[1].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[1].OutW = (width_sec * 20); + FISHEYE_REGION[1].OutH = (height_sec * 20); + FISHEYE_REGION[1].OutX = (width_sec * 20); + FISHEYE_REGION[1].OutY = (height_sec * 0); + + FISHEYE_REGION[2].RegionValid = 1; + FISHEYE_REGION[2].MeshVer = 16; + FISHEYE_REGION[2].MeshHor = 16; + FISHEYE_REGION[2].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[2].ThetaX = 0.4 * M_PI; + FISHEYE_REGION[2].ThetaZ = M_PI; + FISHEYE_REGION[2].ThetaY = 0; + FISHEYE_REGION[2].ZoomH = 2048; + FISHEYE_REGION[2].ZoomV = 2048; + FISHEYE_REGION[2].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[2].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[2].OutW = (width_sec * 20); + FISHEYE_REGION[2].OutH = (height_sec * 20); + FISHEYE_REGION[2].OutX = (width_sec * 0); + FISHEYE_REGION[2].OutY = (height_sec * 20); + + FISHEYE_REGION[3].RegionValid = 1; + FISHEYE_REGION[3].MeshVer = 16; + FISHEYE_REGION[3].MeshHor = 16; + FISHEYE_REGION[3].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[3].ThetaX = 0.4 * M_PI; + FISHEYE_REGION[3].ThetaZ = 3 * M_PI / 2; + FISHEYE_REGION[3].ThetaY = 0; + FISHEYE_REGION[3].ZoomH = 2048; + FISHEYE_REGION[3].ZoomV = 2048; + FISHEYE_REGION[3].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[3].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[3].OutW = (width_sec * 20); + FISHEYE_REGION[3].OutH = (height_sec * 20); + FISHEYE_REGION[3].OutX = (width_sec * 20); + FISHEYE_REGION[3].OutY = (height_sec * 20); + + FISHEYE_REGION[4].RegionValid = 0; + } + else if (FISHEYE_CONFIG->UsageMode == MODE_04_1P2R) + { + // Region #1 => Panorama 180 + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 16; + FISHEYE_REGION[0].MeshHor = 16; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_180; + //FISHEYE_REGION[0].ThetaX = 0; + //FISHEYE_REGION[0].ThetaY = 0; + //FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ZoomH = 4096; // value = 0 ~ 4095, symmeterically control horizontal View Range, ex: value = 4095 => hor view angle = -90 ~ + 90 + FISHEYE_REGION[0].ZoomV = 1920; // value = 0 ~ 4095, symmetrically control vertical view range. ex: value = 4096, ver view angle = -90 ~ + 90 + FISHEYE_REGION[0].Pan = UI_CTRL_VALUE_CENTER; // value range = 0 ~ 360, => -180 ~ 0 ~ +180 + FISHEYE_REGION[0].Tilt = UI_CTRL_VALUE_CENTER; // value = 0 ~ 360, center = 180 ( original ) => -180 ~ 0 ~ + 180 + FISHEYE_REGION[0].OutW = (width_sec * 40); + FISHEYE_REGION[0].OutH = (height_sec * 22); + FISHEYE_REGION[0].OutX = 0; //(width_sec * 1); + FISHEYE_REGION[0].OutY = 0; //height_sec * 1); + //FISHEYE_REGION[0].InRadius = 50; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].OutRadius = 450; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].PanEnd = 180; + + FISHEYE_REGION[1].RegionValid = 1; + FISHEYE_REGION[1].MeshVer = 8; + FISHEYE_REGION[1].MeshHor = 8; + FISHEYE_REGION[1].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[1].ThetaX = M_PI / 4; + FISHEYE_REGION[1].ThetaZ = M_PI / 2; + FISHEYE_REGION[1].ThetaY = 0; + FISHEYE_REGION[1].ZoomH = 2048; + FISHEYE_REGION[1].ZoomV = 2048; + FISHEYE_REGION[1].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[1].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[1].OutW = (width_sec * 20); + FISHEYE_REGION[1].OutH = (height_sec * 18); + FISHEYE_REGION[1].OutX = (width_sec * 0); + FISHEYE_REGION[1].OutY = (height_sec * 22); + + FISHEYE_REGION[2].RegionValid = 1; + FISHEYE_REGION[2].MeshVer = 8; + FISHEYE_REGION[2].MeshHor = 8; + FISHEYE_REGION[2].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[2].ThetaX = M_PI / 4; + FISHEYE_REGION[2].ThetaZ = M_PI; + FISHEYE_REGION[2].ThetaY = 0; + FISHEYE_REGION[2].ZoomH = 2048; + FISHEYE_REGION[2].ZoomV = 2048; + FISHEYE_REGION[2].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[2].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[2].OutW = (width_sec * 20); + FISHEYE_REGION[2].OutH = (height_sec * 18); + FISHEYE_REGION[2].OutX = (width_sec * 20); + FISHEYE_REGION[2].OutY = (height_sec * 22); + + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + } + else if (FISHEYE_CONFIG->UsageMode == MODE_05_1P2R) + { + // Region #1 => Panorama 180 + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 16; + FISHEYE_REGION[0].MeshHor = 16; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_180; + //FISHEYE_REGION[0].ThetaX = 0; + //FISHEYE_REGION[0].ThetaY = 0; + //FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ZoomH = 3000; // value = 0 ~ 4095, symmeterically control horizontal View Range, ex: value = 4095 => hor view angle = -90 ~ + 90 + FISHEYE_REGION[0].ZoomV = 2048; // value = 0 ~ 4095, symmetrically control vertical view range. ex: value = 4096, ver view angle = -90 ~ + 90 + FISHEYE_REGION[0].Pan = UI_CTRL_VALUE_CENTER; // value range = 0 ~ 360, => -180 ~ 0 ~ +180 + FISHEYE_REGION[0].Tilt = UI_CTRL_VALUE_CENTER; // value = 0 ~ 360, center = 180 ( original ) => -180 ~ 0 ~ + 180 + FISHEYE_REGION[0].OutW = (width_sec * 27 ); + FISHEYE_REGION[0].OutH = (height_sec * 40); + FISHEYE_REGION[0].OutX = 0; //(width_sec * 1); + FISHEYE_REGION[0].OutY = 0; //height_sec * 1); + //FISHEYE_REGION[0].InRadius = 50; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].OutRadius = 450; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].PanEnd = 180; + + FISHEYE_REGION[1].RegionValid = 1; + FISHEYE_REGION[1].MeshVer = 8; + FISHEYE_REGION[1].MeshHor = 8; + FISHEYE_REGION[1].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[1].ThetaX = M_PI / 4; + FISHEYE_REGION[1].ThetaZ = M_PI / 2; + FISHEYE_REGION[1].ThetaY = 0; + FISHEYE_REGION[1].ZoomH = 2048; + FISHEYE_REGION[1].ZoomV = 2048; + FISHEYE_REGION[1].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[1].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[1].OutW = (width_sec * 13); + FISHEYE_REGION[1].OutH = (height_sec * 20); + FISHEYE_REGION[1].OutX = (width_sec * 27); + FISHEYE_REGION[1].OutY = (height_sec * 0); + + FISHEYE_REGION[2].RegionValid = 1; + FISHEYE_REGION[2].MeshVer = 8; + FISHEYE_REGION[2].MeshHor = 8; + FISHEYE_REGION[2].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[2].ThetaX = M_PI / 4; + FISHEYE_REGION[2].ThetaZ = M_PI; + FISHEYE_REGION[2].ThetaY = 0; + FISHEYE_REGION[2].ZoomH = 2048; + FISHEYE_REGION[2].ZoomV = 2048; + FISHEYE_REGION[2].Pan = UI_CTRL_VALUE_CENTER; // theta-X + FISHEYE_REGION[2].Tilt = UI_CTRL_VALUE_CENTER; // theta-Z + FISHEYE_REGION[2].OutW = (width_sec * 13); + FISHEYE_REGION[2].OutH = (height_sec * 20); + FISHEYE_REGION[2].OutX = (width_sec * 27); + FISHEYE_REGION[2].OutY = (height_sec * 20); + + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + + + } + else if (FISHEYE_CONFIG->UsageMode == MODE_06_1P) + { + // Region #1 => Panorama 180 + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 30; + FISHEYE_REGION[0].MeshHor = 30; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_180; + //FISHEYE_REGION[0].ThetaX = 0; + //FISHEYE_REGION[0].ThetaY = 0; + //FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ZoomH = 4096; // value = 0 ~ 4095, symmeterically control horizontal View Range, ex: value = 4095 => hor view angle = -90 ~ + 90 + FISHEYE_REGION[0].ZoomV = 2800; // value = 0 ~ 4095, symmetrically control vertical view range. ex: value = 4096, ver view angle = -90 ~ + 90 + FISHEYE_REGION[0].Pan = UI_CTRL_VALUE_CENTER; // value range = 0 ~ 360, => -180 ~ 0 ~ +180 + FISHEYE_REGION[0].Tilt = UI_CTRL_VALUE_CENTER; // value = 0 ~ 360, center = 180 ( original ) => -180 ~ 0 ~ + 180 + FISHEYE_REGION[0].OutW = (width_sec * 40 ); + FISHEYE_REGION[0].OutH = (height_sec * 40); + FISHEYE_REGION[0].OutX = 0; //(width_sec * 1); + FISHEYE_REGION[0].OutY = 0; //height_sec * 1); + //FISHEYE_REGION[0].InRadius = 50; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].OutRadius = 450; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].PanEnd = 180; + + FISHEYE_REGION[1].RegionValid = 0; + FISHEYE_REGION[2].RegionValid = 0; + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + } else if (FISHEYE_CONFIG->UsageMode == MODE_07_2P ) { + //_Panorama360View2; + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 16; + FISHEYE_REGION[0].MeshHor = 16; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_360; + FISHEYE_REGION[0].ThetaX = M_PI / 4; + FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ThetaY = 0; + //FISHEYE_REGION[0].ZoomH = 4095; // Not Used in Panorama 360 Mode. + FISHEYE_REGION[0].ZoomV = 4095; // To ZoomIn OutRadius + FISHEYE_REGION[0].Pan = 0; // for panorama 360 => Pan is the label start position angle ( in degrees + FISHEYE_REGION[0].Tilt = 300; // to add shift offset vertical angle. + FISHEYE_REGION[0].OutW = (width_sec * 40); + FISHEYE_REGION[0].OutH = (height_sec * 20); + FISHEYE_REGION[0].OutX = (width_sec * 0); + FISHEYE_REGION[0].OutY = (height_sec * 0); + FISHEYE_REGION[0].InRadius = 300; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + FISHEYE_REGION[0].OutRadius = 500; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + FISHEYE_REGION[0].PanEnd = 180; + + FISHEYE_REGION[1].RegionValid = 1; + FISHEYE_REGION[1].MeshVer = 16; + FISHEYE_REGION[1].MeshHor = 16; + FISHEYE_REGION[1].ViewMode = PROJECTION_PANORAMA_360; + FISHEYE_REGION[1].ThetaX = M_PI / 4; + FISHEYE_REGION[1].ThetaZ = 0; + FISHEYE_REGION[1].ThetaY = 0; + //FISHEYE_REGION[1].ZoomH = 4095; // Not Used in Panorama 360 Mode. + FISHEYE_REGION[1].ZoomV = 4095; // To ZoomIn OutRadius + FISHEYE_REGION[1].Pan = 240; // for panorama 360 => Pan is the label start position angle ( in degrees + FISHEYE_REGION[1].Tilt = 200; // to add shift offset vertical angle. + FISHEYE_REGION[1].OutW = (width_sec * 40); + FISHEYE_REGION[1].OutH = (height_sec * 20); + FISHEYE_REGION[1].OutX = (width_sec * 0); + FISHEYE_REGION[1].OutY = (height_sec * 20); + FISHEYE_REGION[1].InRadius = 0; // a ratio to represent OutRadius length. 1 = full origina redius. value/512 is the value. + FISHEYE_REGION[1].OutRadius = 512; // a ratio to represent OutRadius length. 1 = full origina redius. value/512 is the value. + FISHEYE_REGION[1].PanEnd = 60; // + + FISHEYE_REGION[2].RegionValid = 0; + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + } else if (FISHEYE_CONFIG->UsageMode == MODE_PANORAMA_180) { + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 16; + FISHEYE_REGION[0].MeshHor = 16; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_180; + //FISHEYE_REGION[0].ThetaX = M_PI / 4; + //FISHEYE_REGION[0].ThetaZ = 0; + //FISHEYE_REGION[0].ThetaY = 0; + FISHEYE_REGION[0].ZoomH = 4096; // Not Used in Panorama 360 Mode. + FISHEYE_REGION[0].ZoomV = 4096; // To ZoomIn OutRadius + FISHEYE_REGION[0].Pan = 180; // for panorama 360 => Pan is the label start position angle ( in degrees + FISHEYE_REGION[0].Tilt = 180; // to add shift offset vertical angle. + FISHEYE_REGION[0].OutW = (width_sec * 40); + FISHEYE_REGION[0].OutH = (height_sec * 40); + FISHEYE_REGION[0].OutX = 0; //(width_sec * 1); + FISHEYE_REGION[0].OutY = 0; //height_sec * 1); + //FISHEYE_REGION[0].InRadius = 50; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].OutRadius = 450; // a ratio to represent OutRadius length. 1 => full origina redius. value/512 is the value. + //FISHEYE_REGION[0].PanEnd = 180; + + FISHEYE_REGION[1].RegionValid = 0; + FISHEYE_REGION[2].RegionValid = 0; + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + } else if (FISHEYE_CONFIG->UsageMode == MODE_PANORAMA_360) { + SIZE_S in, out; + RECT_S rect; + + in.u32Width = 2 * M_PI * FISHEYE_CONFIG->InRadius; + in.u32Height = FISHEYE_CONFIG->InRadius; + out.u32Width = (width_sec * 40); + out.u32Height = (height_sec * 40); + rect = aspect_ratio_resize(in, out); + + //_Panorama360View2; + FISHEYE_REGION[0].RegionValid = 1; + FISHEYE_REGION[0].MeshVer = 64; + FISHEYE_REGION[0].MeshHor = 64; + FISHEYE_REGION[0].ViewMode = PROJECTION_PANORAMA_360; + FISHEYE_REGION[0].ThetaX = M_PI / 4; + FISHEYE_REGION[0].ThetaZ = 0; + FISHEYE_REGION[0].ThetaY = 0; + //FISHEYE_REGION[0].ZoomH = 4095; // Not Used in Panorama 360 Mode. + FISHEYE_REGION[0].ZoomV = 4095; // To ZoomIn OutRadius + FISHEYE_REGION[0].Pan = 0; // for panorama 360 => Pan is the label start position angle ( in degrees + FISHEYE_REGION[0].Tilt = 180; // to add shift offset vertical angle. + FISHEYE_REGION[0].OutW = rect.u32Width; + FISHEYE_REGION[0].OutH = rect.u32Height; + FISHEYE_REGION[0].OutX = rect.s32X; //(width_sec * 1); + FISHEYE_REGION[0].OutY = rect.s32Y; //(height_sec * 1); + FISHEYE_REGION[0].InRadius = 0; // a ratio to represent OutRadius length. 1 => full origina redius. value = 0 ~ 4095, + FISHEYE_REGION[0].OutRadius = 4095; // a ratio to represent OutRadius length. 1 => full origina redius. value = 0 ~ 4095 + FISHEYE_REGION[0].PanEnd = 359; + + FISHEYE_REGION[1].RegionValid = 0; + FISHEYE_REGION[2].RegionValid = 0; + FISHEYE_REGION[3].RegionValid = 0; + FISHEYE_REGION[4].RegionValid = 0; + } else { + printf("Not done yet. !!!"); + //system("pause"); + } +} + +void _LOAD_FRAME_CONFIG(FISHEYE_ATTR* FISHEYE_CONFIG) +{ + switch (FISHEYE_CONFIG->UsageMode) + { + case MODE_PANORAMA_360: + FISHEYE_CONFIG->RgnNum = 1; + break; + case MODE_PANORAMA_180: + FISHEYE_CONFIG->RgnNum = 1; + break; + case MODE_01_1O: + FISHEYE_CONFIG->RgnNum = 1; + break; + case MODE_02_1O4R: + FISHEYE_CONFIG->RgnNum = 4; // 1O should be handled in scaler block. + break; + case MODE_03_4R: + FISHEYE_CONFIG->RgnNum = 4; + break; + case MODE_04_1P2R: + FISHEYE_CONFIG->RgnNum = 3; + break; + case MODE_05_1P2R: + FISHEYE_CONFIG->RgnNum = 3; + break; + case MODE_06_1P: + FISHEYE_CONFIG->RgnNum = 1; + break; + case MODE_07_2P: + FISHEYE_CONFIG->RgnNum = 2;// + break; + default: + printf("UsageMode Error!!!"); + //system("pause"); + break; + } +} + +/** + * generate_mesh_on_fisheye: generate mesh for fisheye + * + * @param param: mesh parameters. + * @param faces: the nodes describe the faces + */ +static int generate_mesh_on_fisheye(FISHEYE_ATTR* FISHEYE_CONFIG, FISHEYE_REGION_ATTR* FISHEYE_REGION + , int X_TILE_NUMBER, int Y_TILE_NUMBER + , uint16_t *reorder_mesh_id_list, int **reorder_mesh_tbl, uint64_t mesh_tbl_phy_addr) +{ + int mesh_tbl_num; // get number of meshes + double x0, y0, r; // infos of src_img, (x0,y0) = center of image, r = radius of image. + + struct timespec start, end; + + clock_gettime(CLOCK_MONOTONIC, &start); + + x0 = FISHEYE_CONFIG->InCenterX; + y0 = FISHEYE_CONFIG->InCenterY; + r = FISHEYE_CONFIG->InRadius; + // In Each Mode, for Every Region: + for (int rgn_idx = 0; rgn_idx < FISHEYE_CONFIG->RgnNum; rgn_idx++) { + // check region valid first + if (!FISHEYE_REGION[rgn_idx].RegionValid) + return -1; + + // get & store region mesh info. + _get_region_dst_mesh_list(FISHEYE_REGION, rgn_idx); + + // Get Source Mesh-Info Projected from Destination by Differet ViewModw. + _get_region_src_mesh_list(FISHEYE_CONFIG->MntMode, FISHEYE_REGION, rgn_idx, x0, y0, r); + } + //combine all region meshs - mesh projection done. + _get_frame_mesh_list(FISHEYE_CONFIG, FISHEYE_REGION); + + mesh_tbl_num = FISHEYE_CONFIG->TotalMeshNum; + float src_x_mesh_tbl[mesh_tbl_num][4]; + float src_y_mesh_tbl[mesh_tbl_num][4]; + float dst_x_mesh_tbl[mesh_tbl_num][4]; + float dst_y_mesh_tbl[mesh_tbl_num][4]; + for (int mesh_idx = 0; mesh_idx < FISHEYE_CONFIG->TotalMeshNum; mesh_idx++) { + for (int knotidx = 0; knotidx < 4; knotidx++) { + src_x_mesh_tbl[mesh_idx][knotidx] = FISHEYE_CONFIG->SrcRgnMeshInfo[mesh_idx].knot[knotidx].xcor; + src_y_mesh_tbl[mesh_idx][knotidx] = FISHEYE_CONFIG->SrcRgnMeshInfo[mesh_idx].knot[knotidx].ycor; + dst_x_mesh_tbl[mesh_idx][knotidx] = FISHEYE_CONFIG->DstRgnMeshInfo[mesh_idx].knot[knotidx].xcor; + dst_y_mesh_tbl[mesh_idx][knotidx] = FISHEYE_CONFIG->DstRgnMeshInfo[mesh_idx].knot[knotidx].ycor; + } + } + + int dst_height, dst_width; + if (FISHEYE_CONFIG->rotate_index == 1 || FISHEYE_CONFIG->rotate_index == 3) { + dst_height = FISHEYE_CONFIG->OutW_disp; + dst_width = FISHEYE_CONFIG->OutH_disp; + } else { + dst_height = FISHEYE_CONFIG->OutH_disp; + dst_width = FISHEYE_CONFIG->OutW_disp; + } + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh_tbl_num = %d\n", mesh_tbl_num); + + ///////////////////////////////////////////////////////////////////////////////////// + // mesh scan order preprocessing + ///////////////////////////////////////////////////////////////////////////////////// + int Y_SUBTILE_NUMBER = ceil((float)dst_height / (float)NUMBER_Y_LINE_A_SUBTILE); + int MAX_MESH_NUM_A_TILE = ((64 * 2) / X_TILE_NUMBER) * (1 + ceil((4*128)/(float)dst_height)); // (maximum horizontal meshes number x 2)/horizontal tiles number + uint16_t mesh_scan_tile_mesh_id_list[MAX_MESH_NUM_A_TILE * Y_SUBTILE_NUMBER * X_TILE_NUMBER]; + + int mesh_id_list_entry_num = + mesh_scan_preproc_3(dst_width, dst_height, + dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, mesh_scan_tile_mesh_id_list, + X_TILE_NUMBER, NUMBER_Y_LINE_A_SUBTILE, + Y_TILE_NUMBER, MAX_MESH_NUM_A_TILE); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_list_entry_num = %d\n", mesh_id_list_entry_num); + + int isrc_x_mesh_tbl[mesh_tbl_num][4]; + int isrc_y_mesh_tbl[mesh_tbl_num][4]; + int idst_x_mesh_tbl[mesh_tbl_num][4]; + int idst_y_mesh_tbl[mesh_tbl_num][4]; + + mesh_coordinate_float2fixed(src_x_mesh_tbl, src_y_mesh_tbl, dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, + isrc_x_mesh_tbl, isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl); + + int reorder_mesh_tbl_entry_num, reorder_mesh_id_list_entry_num; + + mesh_tbl_reorder_and_parse_3(mesh_scan_tile_mesh_id_list, mesh_id_list_entry_num, + isrc_x_mesh_tbl, isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl, + X_TILE_NUMBER, Y_TILE_NUMBER, Y_SUBTILE_NUMBER, reorder_mesh_tbl, + &reorder_mesh_tbl_entry_num, reorder_mesh_id_list, + &reorder_mesh_id_list_entry_num, mesh_tbl_phy_addr); + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh table size (bytes) = %d\n", (reorder_mesh_tbl_entry_num * 4)); + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh id list size (bytes) = %d\n", (reorder_mesh_id_list_entry_num * 2)); + + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_INFO, "time consumed: %fms\n", + (CVI_FLOAT)get_diff_in_us(start, end) / 1000); + return 0; +} + +void _fisheye_attr_map(const FISHEYE_ATTR_S *pstFisheyeAttr, SIZE_S out_size, FISHEYE_ATTR *FISHEYE_CONFIG + , FISHEYE_REGION_ATTR *FISHEYE_REGION) +{ + FISHEYE_CONFIG->MntMode = pstFisheyeAttr->enMountMode; + FISHEYE_CONFIG->OutW_disp = out_size.u32Width; + FISHEYE_CONFIG->OutH_disp = out_size.u32Height; + FISHEYE_CONFIG->InCenterX = pstFisheyeAttr->s32HorOffset; + FISHEYE_CONFIG->InCenterY = pstFisheyeAttr->s32VerOffset; + // TODO: how to handl radius + FISHEYE_CONFIG->InRadius = MIN2(FISHEYE_CONFIG->InCenterX, FISHEYE_CONFIG->InCenterY); + FISHEYE_CONFIG->FStrength = pstFisheyeAttr->s32FanStrength; + FISHEYE_CONFIG->TCoef = pstFisheyeAttr->u32TrapezoidCoef; + + FISHEYE_CONFIG->RgnNum = pstFisheyeAttr->u32RegionNum; + + CVI_TRACE_GDC(CVI_DBG_INFO, "OutW_disp(%d) OutH_disp(%d)\n" + , FISHEYE_CONFIG->OutW_disp, FISHEYE_CONFIG->OutH_disp); + CVI_TRACE_GDC(CVI_DBG_INFO, "InCenterX(%d) InCenterY(%d)\n" + , FISHEYE_CONFIG->InCenterX, FISHEYE_CONFIG->InCenterY); + CVI_TRACE_GDC(CVI_DBG_INFO, "FStrength(%lf) TCoef(%lf) RgnNum(%d)\n" + , FISHEYE_CONFIG->FStrength, FISHEYE_CONFIG->TCoef, FISHEYE_CONFIG->RgnNum); + + for (int i = 0; i < MAX_REGION_NUM; ++i) + FISHEYE_REGION[i].RegionValid = 0; + + for (int i = 0; i < FISHEYE_CONFIG->RgnNum; ++i) { + FISHEYE_REGION[i].RegionValid = 1; + + FISHEYE_REGION[i].ZoomH = pstFisheyeAttr->astFishEyeRegionAttr[i].u32HorZoom; + FISHEYE_REGION[i].ZoomV = pstFisheyeAttr->astFishEyeRegionAttr[i].u32VerZoom; + FISHEYE_REGION[i].Pan = pstFisheyeAttr->astFishEyeRegionAttr[i].u32Pan; + FISHEYE_REGION[i].Tilt = pstFisheyeAttr->astFishEyeRegionAttr[i].u32Tilt; + FISHEYE_REGION[i].OutW = pstFisheyeAttr->astFishEyeRegionAttr[i].stOutRect.u32Width; + FISHEYE_REGION[i].OutH = pstFisheyeAttr->astFishEyeRegionAttr[i].stOutRect.u32Height; + FISHEYE_REGION[i].OutX = pstFisheyeAttr->astFishEyeRegionAttr[i].stOutRect.s32X; + FISHEYE_REGION[i].OutY = pstFisheyeAttr->astFishEyeRegionAttr[i].stOutRect.s32Y; + FISHEYE_REGION[i].InRadius = pstFisheyeAttr->astFishEyeRegionAttr[i].u32InRadius; + FISHEYE_REGION[i].OutRadius = pstFisheyeAttr->astFishEyeRegionAttr[i].u32OutRadius; + if (pstFisheyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_NORMAL) { + FISHEYE_REGION[i].MeshVer = 16; + FISHEYE_REGION[i].MeshHor = 16; + FISHEYE_REGION[i].ViewMode = PROJECTION_REGION; + FISHEYE_REGION[i].ThetaX = 0.4*M_PI; + FISHEYE_REGION[i].ThetaZ = 0; + FISHEYE_REGION[i].ThetaY = 0; + } else if (pstFisheyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA) { + FISHEYE_REGION[i].MeshVer = 32; + FISHEYE_REGION[i].MeshHor = 32; + FISHEYE_REGION[i].ViewMode = PROJECTION_PANORAMA_180; + } else if (pstFisheyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_360_PANORAMA) { + FISHEYE_REGION[i].MeshVer = (FISHEYE_CONFIG->RgnNum == 1) ? 64 : 32; + FISHEYE_REGION[i].MeshHor = (FISHEYE_CONFIG->RgnNum == 1) ? 64 : 32; + FISHEYE_REGION[i].ViewMode = PROJECTION_PANORAMA_360; + FISHEYE_REGION[i].ThetaX = M_PI / 4; + FISHEYE_REGION[i].ThetaZ = 0; + FISHEYE_REGION[i].ThetaY = 0; + FISHEYE_REGION[i].PanEnd = FISHEYE_REGION[i].Pan + + 360 * pstFisheyeAttr->astFishEyeRegionAttr[i].u32HorZoom / 4096; + } + CVI_TRACE_GDC(CVI_DBG_INFO, "Region(%d) ViewMode(%d) MeshVer(%d) MeshHor(%d)\n" + , i, FISHEYE_REGION[i].ViewMode, FISHEYE_REGION[i].MeshVer, FISHEYE_REGION[i].MeshHor); + CVI_TRACE_GDC(CVI_DBG_INFO, "ZoomH(%lf) ZoomV(%lf) Pan(%d) Tilt(%d) PanEnd(%d)\n" + , FISHEYE_REGION[i].ZoomH, FISHEYE_REGION[i].ZoomV + , FISHEYE_REGION[i].Pan, FISHEYE_REGION[i].Tilt, FISHEYE_REGION[i].PanEnd); + CVI_TRACE_GDC(CVI_DBG_INFO, "InRadius(%lf) OutRadius(%lf) Rect(%d %d %d %d)\n" + , FISHEYE_REGION[i].InRadius, FISHEYE_REGION[i].OutRadius + , FISHEYE_REGION[i].OutX, FISHEYE_REGION[i].OutY + , FISHEYE_REGION[i].OutW, FISHEYE_REGION[i].OutH); + } +} + +void mesh_gen_fisheye(SIZE_S in_size, SIZE_S out_size, const FISHEYE_ATTR_S *pstFisheyeAttr + , uint64_t mesh_phy_addr, void *mesh_vir_addr, ROTATION_E rot) +{ + FISHEYE_ATTR *FISHEYE_CONFIG; + FISHEYE_REGION_ATTR *FISHEYE_REGION; + + FISHEYE_CONFIG = (FISHEYE_ATTR *)calloc(1, sizeof(*FISHEYE_CONFIG)); + if (!FISHEYE_CONFIG) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye config\n"); + return; + } + FISHEYE_REGION = (FISHEYE_REGION_ATTR *)calloc(1, sizeof(*FISHEYE_REGION) * MAX_REGION_NUM); + if (!FISHEYE_REGION) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye region config\n"); + return; + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "in_size(%d %d) out_size(%d %d)\n" + , in_size.u32Width, in_size.u32Height + , out_size.u32Width, out_size.u32Height); + + if (pstFisheyeAttr->enUseMode > 0) { + double x0, y0, r; // infos of src_img, (x0,y0) = center of image, r = radius of image. + x0 = pstFisheyeAttr->s32HorOffset; + y0 = pstFisheyeAttr->s32VerOffset; + r = MIN2(x0, y0); + + FISHEYE_CONFIG->Enable = true; + FISHEYE_CONFIG->BgEnable = true; + FISHEYE_CONFIG->MntMode = pstFisheyeAttr->enMountMode; + FISHEYE_CONFIG->UsageMode = pstFisheyeAttr->enUseMode; + FISHEYE_CONFIG->OutW_disp = out_size.u32Width; + FISHEYE_CONFIG->OutH_disp = out_size.u32Height; + FISHEYE_CONFIG->BgColor.R = 0; + FISHEYE_CONFIG->BgColor.G = 0; + FISHEYE_CONFIG->BgColor.B = 0; + FISHEYE_CONFIG->InCenterX = x0; // front-end set. + FISHEYE_CONFIG->InCenterY = y0; // front-end set. + FISHEYE_CONFIG->InRadius = r; // front-end set. + FISHEYE_CONFIG->FStrength = pstFisheyeAttr->s32FanStrength; + + _LOAD_FRAME_CONFIG(FISHEYE_CONFIG); + _LOAD_REGION_CONFIG(FISHEYE_CONFIG, FISHEYE_REGION); + } else + _fisheye_attr_map(pstFisheyeAttr, out_size, FISHEYE_CONFIG, FISHEYE_REGION); + + FISHEYE_CONFIG->rotate_index = rot; + + int X_TILE_NUMBER, Y_TILE_NUMBER; + CVI_U32 mesh_id_size, mesh_tbl_size; + CVI_U64 mesh_id_phy_addr, mesh_tbl_phy_addr; + CVI_BOOL is_4K = (in_size.u32Width > 2048) && (out_size.u32Width > 2048); + + X_TILE_NUMBER = is_4K ? 4 : 1; + Y_TILE_NUMBER = is_4K ? 4 : 1; + + // calculate mesh_id/mesh_tbl's size in bytes. + mesh_tbl_size = 0x60000; + mesh_id_size = 0x30000; + + // Decide the position of mesh in memory. + mesh_id_phy_addr = mesh_phy_addr; + mesh_tbl_phy_addr = ALIGN(mesh_phy_addr + mesh_id_size, 0x1000); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "phy-addr of mesh id(%#"PRIx64") mesh_tbl(%#"PRIx64")\n" + , mesh_id_phy_addr, mesh_tbl_phy_addr); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_size(%d) mesh_tbl_size(%d)\n", mesh_id_size, mesh_tbl_size); + + int *reorder_mesh_tbl[X_TILE_NUMBER * Y_TILE_NUMBER]; + + // Provide virtual address to write mesh. + reorder_mesh_tbl[0] = mesh_vir_addr + (mesh_tbl_phy_addr - mesh_id_phy_addr); + generate_mesh_on_fisheye(FISHEYE_CONFIG, FISHEYE_REGION, X_TILE_NUMBER, Y_TILE_NUMBER + , (uint16_t *)mesh_vir_addr + , reorder_mesh_tbl, mesh_tbl_phy_addr); + free(FISHEYE_CONFIG); + free(FISHEYE_REGION); +} + +void _ldc_attr_map(const LDC_ATTR_S *pstLDCAttr, SIZE_S out_size, FISHEYE_ATTR *FISHEYE_CONFIG + , FISHEYE_REGION_ATTR *FISHEYE_REGION) +{ + FISHEYE_CONFIG->MntMode = 0; + FISHEYE_CONFIG->OutW_disp = out_size.u32Width; + FISHEYE_CONFIG->OutH_disp = out_size.u32Height; + FISHEYE_CONFIG->InCenterX = out_size.u32Width >> 1; + FISHEYE_CONFIG->InCenterY = out_size.u32Height >> 1; + // TODO: how to handl radius + FISHEYE_CONFIG->InRadius = MIN2(FISHEYE_CONFIG->InCenterX, FISHEYE_CONFIG->InCenterY); + FISHEYE_CONFIG->FStrength = 0; + FISHEYE_CONFIG->TCoef = 0; + + FISHEYE_CONFIG->RgnNum = 1; + + CVI_TRACE_GDC(CVI_DBG_INFO, "OutW_disp(%d) OutH_disp(%d)\n" + , FISHEYE_CONFIG->OutW_disp, FISHEYE_CONFIG->OutH_disp); + + for (int i = 0; i < MAX_REGION_NUM; ++i) + FISHEYE_REGION[i].RegionValid = 0; + + for (int i = 0; i < FISHEYE_CONFIG->RgnNum; ++i) { + FISHEYE_REGION[i].RegionValid = 1; + + //FISHEYE_REGION[i].ZoomH = pstLDCAttr->bAspect; + FISHEYE_REGION[i].ZoomV = pstLDCAttr->bAspect; + FISHEYE_REGION[i].Pan = pstLDCAttr->s32XYRatio; + FISHEYE_REGION[i].PanEnd = pstLDCAttr->s32DistortionRatio; + FISHEYE_REGION[i].Tilt = 180; + FISHEYE_REGION[i].OutW = FISHEYE_CONFIG->OutW_disp; + FISHEYE_REGION[i].OutH = FISHEYE_CONFIG->OutH_disp; + FISHEYE_REGION[i].OutX = 0; + FISHEYE_REGION[i].OutY = 0; + FISHEYE_REGION[i].InRadius = pstLDCAttr->s32CenterXOffset; + FISHEYE_REGION[i].OutRadius = pstLDCAttr->s32CenterYOffset; + FISHEYE_REGION[i].MeshVer = 16; + FISHEYE_REGION[i].MeshHor = 16; + FISHEYE_REGION[i].ViewMode = PROJECTION_LDC; + FISHEYE_REGION[i].ThetaX = pstLDCAttr->s32XRatio; + FISHEYE_REGION[i].ThetaZ = pstLDCAttr->s32YRatio; + FISHEYE_REGION[i].ThetaY = 0; + + CVI_TRACE_GDC(CVI_DBG_INFO, "Region(%d) ViewMode(%d) MeshVer(%d) MeshHor(%d)\n" + , i, FISHEYE_REGION[i].ViewMode, FISHEYE_REGION[i].MeshVer, FISHEYE_REGION[i].MeshHor); + CVI_TRACE_GDC(CVI_DBG_INFO, "bAspect(%d) XYRatio(%d) DistortionRatio(%d)\n" + , (bool)FISHEYE_REGION[i].ZoomV, FISHEYE_REGION[i].Pan, FISHEYE_REGION[i].PanEnd); + CVI_TRACE_GDC(CVI_DBG_INFO, "XRatio(%d) XYRatio(%d)\n" + , (int)FISHEYE_REGION[i].ThetaX, (int)FISHEYE_REGION[i].ThetaZ); + CVI_TRACE_GDC(CVI_DBG_INFO, "CenterXOffset(%lf) CenterYOffset(%lf) Rect(%d %d %d %d)\n" + , FISHEYE_REGION[i].InRadius, FISHEYE_REGION[i].OutRadius + , FISHEYE_REGION[i].OutX, FISHEYE_REGION[i].OutY + , FISHEYE_REGION[i].OutW, FISHEYE_REGION[i].OutH); + } +} + +int set_mesh_size(int mesh_hor, int mesh_ver) +{ + if (mesh_hor <= 0 || mesh_ver <= 0) { + CVI_TRACE_GDC(CVI_DBG_ERR, "bad param , mesh_hor:(%d), mesh_ver:(%d)\n", mesh_hor, mesh_ver); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + if (mesh_hor * mesh_ver > MESH_MAX_SIZE) { + CVI_TRACE_GDC(CVI_DBG_ERR, "mesh size is too large, max mesh size is (%d).\n", MESH_MAX_SIZE); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + meshHor = mesh_hor; + meshVer = mesh_ver; + + return CVI_SUCCESS; +} + +int get_mesh_size(int *p_mesh_hor, int *p_mesh_ver) +{ + MOD_CHECK_NULL_PTR(CVI_ID_GDC, p_mesh_hor); + MOD_CHECK_NULL_PTR(CVI_ID_GDC, p_mesh_ver); + *p_mesh_hor = meshHor; + *p_mesh_ver = meshVer; + + return CVI_SUCCESS; +} + +void mesh_gen_rotation(SIZE_S in_size, SIZE_S out_size, ROTATION_E rot + , uint64_t mesh_phy_addr, void *mesh_vir_addr) +{ + FISHEYE_ATTR *FISHEYE_CONFIG; + LDC_ATTR_S stLDCAttr = { .bAspect = true, .s32XYRatio = 100, + .s32CenterXOffset = 0, .s32CenterYOffset = 0, .s32DistortionRatio = 0 }; + FISHEYE_REGION_ATTR *FISHEYE_REGION; + int nMeshhor, nMeshVer; + + FISHEYE_CONFIG = (FISHEYE_ATTR *)calloc(1, sizeof(*FISHEYE_CONFIG)); + if (!FISHEYE_CONFIG) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye config\n"); + return; + } + FISHEYE_REGION = (FISHEYE_REGION_ATTR *)calloc(1, sizeof(*FISHEYE_REGION) * MAX_REGION_NUM); + if (!FISHEYE_REGION) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye region config\n"); + return; + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "in_size(%d %d) out_size(%d %d)\n" + , in_size.u32Width, in_size.u32Height + , out_size.u32Width, out_size.u32Height); + + _ldc_attr_map(&stLDCAttr, in_size, FISHEYE_CONFIG, FISHEYE_REGION); + get_mesh_size(&nMeshhor, &nMeshVer); + FISHEYE_REGION[0].MeshHor = nMeshhor; + FISHEYE_REGION[0].MeshVer = nMeshVer; + + FISHEYE_CONFIG->rotate_index = rot; + + int X_TILE_NUMBER, Y_TILE_NUMBER; + CVI_U32 mesh_id_size, mesh_tbl_size; + CVI_U64 mesh_id_phy_addr, mesh_tbl_phy_addr; + + X_TILE_NUMBER = DIV_UP(in_size.u32Width, 122); + Y_TILE_NUMBER = 8; + + // calculate mesh_id/mesh_tbl's size in bytes. + mesh_tbl_size = 0x20000; + mesh_id_size = 0x40000; + + // Decide the position of mesh in memory. + mesh_id_phy_addr = mesh_phy_addr; + mesh_tbl_phy_addr = ALIGN(mesh_phy_addr + mesh_id_size, 0x1000); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "phy-addr of mesh id(%#"PRIx64") mesh_tbl(%#"PRIx64")\n" + , mesh_id_phy_addr, mesh_tbl_phy_addr); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_size(%d) mesh_tbl_size(%d)\n", mesh_id_size, mesh_tbl_size); + + int *reorder_mesh_tbl[X_TILE_NUMBER * Y_TILE_NUMBER]; + + // Provide virtual address to write mesh. + reorder_mesh_tbl[0] = mesh_vir_addr + (mesh_tbl_phy_addr - mesh_id_phy_addr); + generate_mesh_on_fisheye(FISHEYE_CONFIG, FISHEYE_REGION, X_TILE_NUMBER, Y_TILE_NUMBER + , (uint16_t *)mesh_vir_addr + , reorder_mesh_tbl, mesh_tbl_phy_addr); + free(FISHEYE_CONFIG); + free(FISHEYE_REGION); +} + +CVI_S32 mesh_gen_ldc(SIZE_S in_size, SIZE_S out_size, const LDC_ATTR_S *pstLDCAttr, + uint64_t mesh_phy_addr, void *mesh_vir_addr, ROTATION_E rot) +{ + FISHEYE_ATTR *FISHEYE_CONFIG; + FISHEYE_REGION_ATTR *FISHEYE_REGION; + + FISHEYE_CONFIG = (FISHEYE_ATTR *)calloc(1, sizeof(*FISHEYE_CONFIG)); + if (!FISHEYE_CONFIG) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye config\n"); + return CVI_ERR_GDC_NOMEM; + } + FISHEYE_REGION = (FISHEYE_REGION_ATTR *)calloc(1, sizeof(*FISHEYE_REGION) * MAX_REGION_NUM); + if (!FISHEYE_REGION) { + CVI_TRACE_GDC(CVI_DBG_ERR, "memory insufficient for fisheye region config\n"); + return CVI_ERR_GDC_NOMEM; + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "in_size(%d %d) out_size(%d %d)\n" + , in_size.u32Width, in_size.u32Height + , out_size.u32Width, out_size.u32Height); + + _ldc_attr_map(pstLDCAttr, out_size, FISHEYE_CONFIG, FISHEYE_REGION); + FISHEYE_CONFIG->rotate_index = rot; + + int X_TILE_NUMBER, Y_TILE_NUMBER; + CVI_U32 mesh_id_size, mesh_tbl_size; + CVI_U64 mesh_id_phy_addr, mesh_tbl_phy_addr; + + X_TILE_NUMBER = DIV_UP(in_size.u32Width, 122); + Y_TILE_NUMBER = 8; + + // calculate mesh_id/mesh_tbl's size in bytes. + mesh_tbl_size = 0x60000; + mesh_id_size = 0x50000; + + // Decide the position of mesh in memory. + mesh_id_phy_addr = mesh_phy_addr; + mesh_tbl_phy_addr = ALIGN(mesh_phy_addr + mesh_id_size, 0x1000); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "phy-addr of mesh id(%#"PRIx64") mesh_tbl(%#"PRIx64")\n" + , mesh_id_phy_addr, mesh_tbl_phy_addr); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_size(%d) mesh_tbl_size(%d)\n", mesh_id_size, mesh_tbl_size); + + int *reorder_mesh_tbl[X_TILE_NUMBER * Y_TILE_NUMBER]; + + // Provide virtual address to write mesh. + reorder_mesh_tbl[0] = mesh_vir_addr + (mesh_tbl_phy_addr - mesh_id_phy_addr); + generate_mesh_on_fisheye(FISHEYE_CONFIG, FISHEYE_REGION, X_TILE_NUMBER, Y_TILE_NUMBER + , (uint16_t *)mesh_vir_addr + , reorder_mesh_tbl, mesh_tbl_phy_addr); + free(FISHEYE_CONFIG); + free(FISHEYE_REGION); + + return CVI_SUCCESS; +} + +int CNV_MESH_EDGE[4][2] = { { 0, 1 }, { 1, 3 }, { 2, 0 }, { 3, 2 } }; + +int cnv_mesh_coordinate_float2fixed(float src_x_mesh_tbl[][4], float src_y_mesh_tbl[][4], float dst_x_mesh_tbl[][4], + float dst_y_mesh_tbl[][4], int mesh_tbl_num, int isrc_x_mesh_tbl[][4], + int isrc_y_mesh_tbl[][4], int idst_x_mesh_tbl[][4], int idst_y_mesh_tbl[][4]) +{ + int64_t MAX_VAL; + int64_t MIN_VAL; + double tmp_val; + int64_t val; + + MAX_VAL = 1; + MAX_VAL <<= (DEWARP_COORD_MBITS + DEWARP_COORD_NBITS); + MAX_VAL -= 1; + MIN_VAL = -1 * MAX_VAL; + + for (int i = 0; i < mesh_tbl_num; i++) { + for (int j = 0; j < 4; j++) { + tmp_val = (src_x_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + isrc_x_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (src_y_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + isrc_y_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (dst_x_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + idst_x_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + + tmp_val = (dst_y_mesh_tbl[i][j] * (double)(1 << DEWARP_COORD_NBITS)); + val = (tmp_val >= 0) ? (int64_t)(tmp_val + 0.5) : (int64_t)(tmp_val - 0.5); + idst_y_mesh_tbl[i][j] = (int)CLIP(val, MIN_VAL, MAX_VAL); + } + } + + return 0; +} + +int cnv_mesh_tbl_reorder_and_parse_3(uint16_t *mesh_scan_tile_mesh_id_list, int mesh_id_list_entry_num, + int isrc_x_mesh_tbl[][4], int isrc_y_mesh_tbl[][4], int idst_x_mesh_tbl[][4], + int idst_y_mesh_tbl[][4], int X_TILE_NUMBER, int Y_TILE_NUMBER, + int Y_SUBTILE_NUMBER, int **reorder_mesh_tbl, int *reorder_mesh_tbl_entry_num, + uint16_t *reorder_mesh_id_list, int *reorder_mesh_id_list_entry_num, + uint64_t mesh_tbl_phy_addr) +{ + int mesh = -1; + int reorder_mesh; + int mesh_id_idx = 0; + int mesh_idx = 0; + int *reorder_id_map = (int *)malloc(sizeof(int) * 128 * 128); + + int *reorder_mesh_slice_tbl = reorder_mesh_tbl[0]; // initial mesh_tbl to + + int i = 0; + // int ext_mem_addr_alignment = 32; + + (void) mesh_id_list_entry_num; + (void)Y_SUBTILE_NUMBER; + + // frame start ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + + for (int k = 0; k < Y_TILE_NUMBER; k++) { + for (int j = 0; j < X_TILE_NUMBER; j++) { + reorder_mesh_tbl[j + k * X_TILE_NUMBER] = reorder_mesh_slice_tbl + mesh_idx; + + reorder_mesh = 0; +#if 1 // (JAMMY) clear to -1 + for (int l = 0; l < 128 * 128; l++) { + reorder_id_map[l] = -1; + } +#else + memset(reorder_id_map, 0xff, sizeof(sizeof(int) * 128 * 128)); +#endif + + // slice start ID + mesh = mesh_scan_tile_mesh_id_list[i++]; + reorder_mesh_id_list[mesh_id_idx++] = mesh; + +// (JAMMY) replace with phy-addr later. +// reorder mesh table address -> reorder mesh id list header +#if 0 + uintptr_t addr = (uintptr_t)reorder_mesh_tbl[j + k * X_TILE_NUMBER]; + + reorder_mesh_id_list[mesh_id_idx++] = addr & 0x0000000fff; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0000fff000) >> 12; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0fff000000) >> 24; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0xf000000000) >> 36; +#else + CVI_U64 addr = mesh_tbl_phy_addr + ((uintptr_t)reorder_mesh_tbl[j + k * X_TILE_NUMBER] - + (uintptr_t)reorder_mesh_tbl[0]); + + reorder_mesh_id_list[mesh_id_idx++] = addr & 0x0000000fff; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0000fff000) >> 12; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0x0fff000000) >> 24; + reorder_mesh_id_list[mesh_id_idx++] = (addr & 0xf000000000) >> 36; +#endif + + // slice src and width -> reorder mesh id list header + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile x src + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile width + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile y src + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; // tile height + + while (mesh_scan_tile_mesh_id_list[i] != MESH_ID_FSE) { + mesh = mesh_scan_tile_mesh_id_list[i++]; + if (mesh == MESH_ID_FST || mesh == MESH_ID_FSS) { + continue; + } else if (mesh == MESH_ID_FSP || + /* mesh == MESH_ID_FED */ mesh == MESH_ID_FTE) { + reorder_mesh_id_list[mesh_id_idx++] = mesh; // meta-data header + } else /* if (mesh != MESH_ID_FED) */ { + if (reorder_id_map[mesh] == -1) { + reorder_id_map[mesh] = reorder_mesh; + reorder_mesh++; + + for (int l = 0; l < 4; l++) { + reorder_mesh_slice_tbl[mesh_idx++] = isrc_x_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = isrc_y_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = idst_x_mesh_tbl[mesh][l]; + reorder_mesh_slice_tbl[mesh_idx++] = idst_y_mesh_tbl[mesh][l]; + } + } + + reorder_mesh_id_list[mesh_id_idx++] = reorder_id_map[mesh]; + } + } + + // slice end ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + } + } + + // frame end ID + reorder_mesh_id_list[mesh_id_idx++] = mesh_scan_tile_mesh_id_list[i++]; + + *reorder_mesh_tbl_entry_num = mesh_idx; + *reorder_mesh_id_list_entry_num = mesh_id_idx; + + free(reorder_id_map); + + return 0; +} + +int cnv_position_transfer_rect2dist(double x, double y, double *newx, double *newy, double *param, int mapping, + double scale, int width, int height, int owidth, int oheight) +{ + double coeff_0 = PI * param[0] / 180.0; + double coeff_1 = param[1]; + double coeff_2 = param[2]; + double coeff_3 = param[3]; + double coeff_4 = param[4]; + + double phi, radius2, radius; + double x0, y0, x1, y1; + double m11, m12, m13, m21, m22, m23; + + // normalize + double PID2 = PI / 2; + double norm_r = sqrt((width / 2.0) * (width / 2.0) + (height / 2.0) * (height / 2.0)); + double onorm_r = sqrt((owidth / 2.0) * (owidth / 2.0) + (oheight / 2.0) * (oheight / 2.0)); + + x0 = x - width / 2; + y0 = y - height / 2; + phi = atan2(y0, x0); + y0 = y0 / norm_r; + y0 = y0 * scale; + x0 = x0 / norm_r; + x0 = x0 * scale; + // polarize + radius2 = y0 * y0 + x0 * x0; + radius = sqrt(radius2); + + // 360 finsheye param + double theta_src = param[0] * PI / 180.0; + double theta_tot = param[1] * PI / 180.0; + double radius_in = param[2]; + double radius_out = param[3]; + double lens_center_x = (double)owidth / 2; + double lens_center_y = (double)oheight / 2; + double theta = 0.0; + + switch (mapping) { + case 1: // r <= r^2 + // distortion + radius = radius * radius; + // depolarize + x1 = radius * cos(phi); + y1 = radius * sin(phi); + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 2: // radial distortion +#if 0 + // distortion + icoeff_1 = -1 * coeff_1; + icoeff_2 = 0.f; + icoeff_3 = 3 * coeff_1 * coeff_1 - coeff_3; + icoeff_4 = 0.f; + radius = radius * (1 + radius * (icoeff_1 + radius * + (icoeff_2 + radius * (icoeff_3 + radius * icoeff_4)))); + // depolarize + x1 = radius * cos(phi); + y1 = radius * sin(phi); + // denormalize + *newx = (norm_r * x1) + width / 2; + *newy = (norm_r * y1) + height / 2; +#endif + *newx = x; + *newy = y; + break; + case 3: // rotation + // depolarize + x1 = radius * cos(phi - coeff_0); + y1 = radius * sin(phi - coeff_0); + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 4: // affine transform + coeff_3 /= width; + coeff_4 /= height; + m11 = coeff_1 * cos(coeff_0); + m12 = -1 * coeff_2 * sin(coeff_0); + m13 = coeff_3 * coeff_1 * cos(coeff_0) - coeff_4 * coeff_2 * sin(coeff_0); + m21 = coeff_1 * sin(coeff_0); + m22 = coeff_2 * cos(coeff_0); + m23 = coeff_3 * coeff_1 * sin(coeff_0) + coeff_4 * coeff_2 * cos(coeff_0); + x1 = m11 * x0 + m12 * y0 + m13; + y1 = m21 * x0 + m22 * y0 + m23; + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + + break; + case 5: // arcsin correction + // distortion + radius = sin(radius * PID2); + // depolarize + x1 = radius * cos(phi); + y1 = radius * sin(phi); + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 6: + x1 = x0 + y0 * tan(coeff_0); + y1 = y0; + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 7: + x1 = x0; + y1 = y0 + x0 * tan(coeff_0); + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 8: + x1 = x0; + y1 = y0 + x0 * tan(coeff_0); + // denormalize + *newx = (onorm_r * x1) + owidth / 2; + *newy = (onorm_r * y1) + oheight / 2; + break; + case 9: + theta = -(x / (double)(width - 1)) * theta_tot; + radius = (double)(height - 1 - y) / (double)(height - 1); + radius = (radius * (1.0 - radius_in - radius_out) + radius_in) * (double)oheight / 2; + *newx = radius * sin(theta - theta_src) + lens_center_x; + *newy = radius * cos(theta - theta_src) + lens_center_y; + break; + default: + *newx = x; + *newy = y; + break; + } + return 0; +} + + +// cnv + +int cnv_mesh_scan_preproc_3(int width, int height, int dst_width, int dst_height, float src_x_mesh_tbl[][4], + float src_y_mesh_tbl[][4], float dst_x_mesh_tbl[][4], float dst_y_mesh_tbl[][4], + int mesh_tbl_num, uint16_t *mesh_scan_id_order, int Y_SUBTILE_NUMBER, int X_TILE_NUMBER, + int NUM_Y_LINE_A_SUBTILE, int NUM_X_LINE_A_TILE, int Y_TILE_NUMBER, int NUM_Y_LINE_A_TILE, + int MAX_MESH_NUM_A_TILE) +{ + int tile_idx_x, tile_idx_y; + int current_dst_mesh_y_line_intersection_cnt, mesh_num_cnt = 0; + + int id_idx = 0; + int *tmp_mesh_scan_id_order = (int *)malloc(sizeof(int) * (MAX_MESH_NUM_A_TILE * 16)); + + (void) width; + (void) height; + (void) src_x_mesh_tbl; + (void) src_y_mesh_tbl; + (void) Y_SUBTILE_NUMBER; + + mesh_scan_id_order[id_idx] = MESH_ID_FST; + id_idx++; + + for (tile_idx_y = 0; tile_idx_y < Y_TILE_NUMBER; tile_idx_y++) { + int src_y = CLIP((tile_idx_y * NUM_Y_LINE_A_TILE), 0, dst_height); + int dst_y = CLIP((src_y + NUM_Y_LINE_A_TILE), 0, dst_height); + + for (tile_idx_x = 0; tile_idx_x < X_TILE_NUMBER; tile_idx_x++) { + mesh_scan_id_order[id_idx++] = MESH_ID_FSS; + + int src_x = CLIP((tile_idx_x * NUM_X_LINE_A_TILE), 0, dst_width); + int dst_x = CLIP((src_x + NUM_X_LINE_A_TILE), 0, dst_width); + + mesh_scan_id_order[id_idx++] = src_x; + mesh_scan_id_order[id_idx++] = dst_x - src_x; + mesh_scan_id_order[id_idx++] = src_y; + mesh_scan_id_order[id_idx++] = dst_y - src_y; + + for (int y = src_y; y < dst_y; y++) { + // if first line of a tile, then initialization + if (y % NUM_Y_LINE_A_SUBTILE == 0) { + mesh_num_cnt = 0; + for (int i = 0; i < MAX_MESH_NUM_A_TILE; i++) + tmp_mesh_scan_id_order[i] = -1; + + // frame separator ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FSP; + } + + for (int m = 0; m < mesh_tbl_num; m++) { + current_dst_mesh_y_line_intersection_cnt = 0; + int is_mesh_incorp_yline = 0; + int min_x = MIN(MIN(dst_x_mesh_tbl[m][0], dst_x_mesh_tbl[m][1]), + MIN(dst_x_mesh_tbl[m][2], dst_x_mesh_tbl[m][3])); + int max_x = MAX(MAX(dst_x_mesh_tbl[m][0], dst_x_mesh_tbl[m][1]), + MAX(dst_x_mesh_tbl[m][2], dst_x_mesh_tbl[m][3])); + int min_y = MIN(MIN(dst_y_mesh_tbl[m][0], dst_y_mesh_tbl[m][1]), + MIN(dst_y_mesh_tbl[m][2], dst_y_mesh_tbl[m][3])); + int max_y = MAX(MAX(dst_y_mesh_tbl[m][0], dst_y_mesh_tbl[m][1]), + MAX(dst_y_mesh_tbl[m][2], dst_y_mesh_tbl[m][3])); + if (min_y <= y && y <= max_y && min_x <= src_x && dst_x <= max_x) + is_mesh_incorp_yline = 1; + + if (!is_mesh_incorp_yline) { + for (int k = 0; k < 4; k++) { + float knot_dst_a_y = dst_y_mesh_tbl[m][CNV_MESH_EDGE[k][0]]; + float knot_dst_b_y = dst_y_mesh_tbl[m][CNV_MESH_EDGE[k][1]]; + float knot_dst_a_x = dst_x_mesh_tbl[m][CNV_MESH_EDGE[k][0]]; + float knot_dst_b_x = dst_x_mesh_tbl[m][CNV_MESH_EDGE[k][1]]; + float delta_a_y = (float)y - knot_dst_a_y; + float delta_b_y = (float)y - knot_dst_b_y; + int intersect_x = 0; + + if ((src_x <= knot_dst_a_x) && (knot_dst_a_x <= dst_x)) + intersect_x = 1; + if ((src_x <= knot_dst_b_x) && (knot_dst_b_x <= dst_x)) + intersect_x = 1; + + // check whether if vertex connection + if ((delta_a_y == 0.f) && (intersect_x == 1)) { + current_dst_mesh_y_line_intersection_cnt += 2; + } + // check whether if edge connection + else if ((delta_a_y * delta_b_y < 0) && (intersect_x == 1)) { + current_dst_mesh_y_line_intersection_cnt += 2; + } + // otherwise no connection + } // finish check in a mesh + } + + if ((current_dst_mesh_y_line_intersection_cnt > 0) || + (is_mesh_incorp_yline == 1)) { + // check the mesh in list or not + int isInList = 0; + + for (int i = 0; i < mesh_num_cnt; i++) { + if (m == tmp_mesh_scan_id_order[i]) { + isInList = 1; + continue; + } + } + // not in the list, then add the mesh to list + if (!isInList) { + tmp_mesh_scan_id_order[mesh_num_cnt] = m; + mesh_num_cnt++; + } + } + } + + // x direction reorder + if (((y % NUM_Y_LINE_A_SUBTILE) == (NUM_Y_LINE_A_SUBTILE - 1)) || + (y == dst_height - 1)) { + for (int i = 0; i < mesh_num_cnt - 1; i++) { + for (int j = 0; j < mesh_num_cnt - 1 - i; j++) { + int m0 = tmp_mesh_scan_id_order[j]; + int m1 = tmp_mesh_scan_id_order[j + 1]; + float knot_m0_x0 = dst_x_mesh_tbl[m0][0]; + float knot_m0_x1 = dst_x_mesh_tbl[m0][1]; + float knot_m0_x2 = dst_x_mesh_tbl[m0][2]; + float knot_m0_x3 = dst_x_mesh_tbl[m0][3]; + float knot_m1_x0 = dst_x_mesh_tbl[m1][0]; + float knot_m1_x1 = dst_x_mesh_tbl[m1][1]; + float knot_m1_x2 = dst_x_mesh_tbl[m1][2]; + float knot_m1_x3 = dst_x_mesh_tbl[m1][3]; + + int m0_min_x = MIN(MIN(knot_m0_x0, knot_m0_x1), + MIN(knot_m0_x2, knot_m0_x3)); + int m1_min_x = MIN(MIN(knot_m1_x0, knot_m1_x1), + MIN(knot_m1_x2, knot_m1_x3)); + + if (m0_min_x > m1_min_x) { + int tmp = tmp_mesh_scan_id_order[j]; + + tmp_mesh_scan_id_order[j] = + tmp_mesh_scan_id_order[j + 1]; + tmp_mesh_scan_id_order[j + 1] = tmp; + } + } + } + + // mesh ID insertion + for (int i = 0; i < mesh_num_cnt; i++) { + mesh_scan_id_order[id_idx++] = tmp_mesh_scan_id_order[i]; + } + + // tile end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FTE; + } + } + + // frame slice end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FSE; + } + } + + // frame end ID insertion + mesh_scan_id_order[id_idx++] = MESH_ID_FED; + + int mesh_id_list_entry_num = id_idx; + + free(tmp_mesh_scan_id_order); + + return mesh_id_list_entry_num; +} + +/** + * gen_mesh_f_xy_mesh_tbl: generate mesh from + * src_x_mesh_tbl/src_y_mesh_tbl/dst_x_mesh_tbl/dst_y_mesh_tbl + * + * @param param: mesh parameters. + */ + +static int gen_mesh_m_xy_mesh_tbl(float *mesh_data, int imgw, int imgh, uint16_t *reorder_mesh_id_list, + int **reorder_mesh_tbl, uint64_t mesh_tbl_phy_addr) +{ + int width, height, TotalMeshNum; + int X_TILE_NUMBER, Y_TILE_NUMBER, tbl_w_mesh_num, tbl_h_mesh_num; + // FILE *fpMesh; + // if(mesh_data==NULL) + //{ + // fpMesh = fopen("init_mesh_file.txt", "r"); + // fscanf(fpMesh, "%d %d %d %d %d %d %d", &TotalMeshNum, &X_TILE_NUMBER, &Y_TILE_NUMBER, + //&tbl_w_mesh_num, &tbl_h_mesh_num, &width, &height); }else + { + TotalMeshNum = (int)mesh_data[0]; + X_TILE_NUMBER = (int)mesh_data[1]; + Y_TILE_NUMBER = (int)mesh_data[2]; + tbl_w_mesh_num = (int)mesh_data[3]; + tbl_h_mesh_num = (int)mesh_data[4]; + width = (int)mesh_data[5]; + height = (int)mesh_data[6]; + } + if (imgw != width || imgh != height) { + printf("TotalMeshNum, imgw, imgh, width, height: %d %d %d %d %d", TotalMeshNum, imgw, imgh, width, + height); + return (-1); + } + + int mesh_tbl_num = tbl_w_mesh_num * tbl_h_mesh_num; // get number of meshes + float src_x_mesh_tbl[mesh_tbl_num][4]; + float src_y_mesh_tbl[mesh_tbl_num][4]; + float dst_x_mesh_tbl[mesh_tbl_num][4]; + float dst_y_mesh_tbl[mesh_tbl_num][4]; + + float *ptrtmp = mesh_data + 7; + int cc = 0; + + for (int mesh_idx = 0; mesh_idx < TotalMeshNum; mesh_idx++) { + for (int knotidx = 0; knotidx < 4; knotidx++) { + src_x_mesh_tbl[mesh_idx][knotidx] = ptrtmp[cc]; + cc++; + src_y_mesh_tbl[mesh_idx][knotidx] = ptrtmp[cc]; + cc++; + dst_x_mesh_tbl[mesh_idx][knotidx] = ptrtmp[cc]; + cc++; + dst_y_mesh_tbl[mesh_idx][knotidx] = ptrtmp[cc]; + cc++; + } + } + + mesh_tbl_num = TotalMeshNum; // FISHEYE_CONFIG->TotalMeshNum; + int dst_height = height; // FISHEYE_CONFIG->OutH_disp; + int dst_width = width; // FISHEYE_CONFIG->OutW_disp; + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh_tbl_num = %d\n", mesh_tbl_num); + + ///////////////////////////////////////////////////////////////////////////////////// + // mesh scan order preprocessing + ///////////////////////////////////////////////////////////////////////////////////// + int Y_SUBTILE_NUMBER = ceil((float)dst_height / (float)NUMBER_Y_LINE_A_SUBTILE); + int NUMBER_X_LINE_A_TILE = ceil((float)dst_width / (float)X_TILE_NUMBER / 2.0) * 2; + int NUMBER_Y_LINE_A_TILE = + (int)(ceil(ceil((float)dst_height / (float)Y_TILE_NUMBER) / (float)NUMBER_Y_LINE_A_SUBTILE)) * + NUMBER_Y_LINE_A_SUBTILE; + int MAX_MESH_NUM_A_TILE = + ((128 * 2) / X_TILE_NUMBER) * + (1 + + ceil((4 * 128) / (float)dst_height)); // (maximum horizontal meshes number x 2)/horizontal tiles number + printf("MAX_MESH_NUM_A_TILE: %d, %d, %d\n", MAX_MESH_NUM_A_TILE, Y_SUBTILE_NUMBER, X_TILE_NUMBER); + uint16_t mesh_scan_tile_mesh_id_list[MAX_MESH_NUM_A_TILE * Y_SUBTILE_NUMBER * X_TILE_NUMBER]; + + int mesh_id_list_entry_num = + cnv_mesh_scan_preproc_3(width, height, dst_width, dst_height, src_x_mesh_tbl, src_y_mesh_tbl, + dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, mesh_scan_tile_mesh_id_list, + Y_SUBTILE_NUMBER, X_TILE_NUMBER, NUMBER_Y_LINE_A_SUBTILE, NUMBER_X_LINE_A_TILE, + Y_TILE_NUMBER, NUMBER_Y_LINE_A_TILE, MAX_MESH_NUM_A_TILE); + + printf("MAX_MESH_NUM_A_TILE: %d, %d, %d; mesh_id_list_entry_num: %d\n", MAX_MESH_NUM_A_TILE, Y_SUBTILE_NUMBER, + X_TILE_NUMBER, mesh_id_list_entry_num); + + int isrc_x_mesh_tbl[mesh_tbl_num][4]; + int isrc_y_mesh_tbl[mesh_tbl_num][4]; + int idst_x_mesh_tbl[mesh_tbl_num][4]; + int idst_y_mesh_tbl[mesh_tbl_num][4]; + + cnv_mesh_coordinate_float2fixed(src_x_mesh_tbl, src_y_mesh_tbl, dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, + isrc_x_mesh_tbl, isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl); + + int reorder_mesh_tbl_entry_num, reorder_mesh_id_list_entry_num; + + cnv_mesh_tbl_reorder_and_parse_3(mesh_scan_tile_mesh_id_list, mesh_id_list_entry_num, isrc_x_mesh_tbl, + isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl, X_TILE_NUMBER, + Y_TILE_NUMBER, Y_SUBTILE_NUMBER, reorder_mesh_tbl, &reorder_mesh_tbl_entry_num, + reorder_mesh_id_list, &reorder_mesh_id_list_entry_num, mesh_tbl_phy_addr); + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh table size (bytes) = %d\n", (reorder_mesh_tbl_entry_num * 4)); + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh id list size (bytes) = %d\n", (reorder_mesh_id_list_entry_num * 2)); + printf("mesh table size (bytes) = %d\n", (reorder_mesh_tbl_entry_num * 4)); + + return 0; +} + +#if 1 +////int x_tile_nbr, int y_tile_nbr, int tbl_mesh_nbr_w, int tbl_mesh_nbr_h, +static int gen_mesh_f_xy_mesh_tbl(char *init_mesh_file, int imgw, int imgh, uint16_t *reorder_mesh_id_list, + int **reorder_mesh_tbl, uint64_t mesh_tbl_phy_addr) +{ + int width, height, TotalMeshNum; + int X_TILE_NUMBER, Y_TILE_NUMBER, tbl_w_mesh_num, tbl_h_mesh_num; + FILE *fpMesh; + + fpMesh = fopen(init_mesh_file, "r"); + fscanf(fpMesh, "%d %d %d %d %d %d %d", &TotalMeshNum, &X_TILE_NUMBER, &Y_TILE_NUMBER, &tbl_w_mesh_num, + &tbl_h_mesh_num, &width, &height); + if (imgw != width || imgh != height) { + printf("TotalMeshNum, imgw, imgh, width, height: %d %d %d %d %d", TotalMeshNum, imgw, imgh, width, + height); + return (-1); + } + + int mesh_tbl_num = tbl_w_mesh_num * tbl_h_mesh_num; // get number of meshes + float src_x_mesh_tbl[mesh_tbl_num][4]; + float src_y_mesh_tbl[mesh_tbl_num][4]; + float dst_x_mesh_tbl[mesh_tbl_num][4]; + float dst_y_mesh_tbl[mesh_tbl_num][4]; + + for (int mesh_idx = 0; mesh_idx < TotalMeshNum; mesh_idx++) { + for (int knotidx = 0; knotidx < 4; knotidx++) { + fscanf(fpMesh, "%f %f %f %f", &src_x_mesh_tbl[mesh_idx][knotidx], + &src_y_mesh_tbl[mesh_idx][knotidx], &dst_x_mesh_tbl[mesh_idx][knotidx], + &dst_y_mesh_tbl[mesh_idx][knotidx]); + + // src_x_mesh_tbl[mesh_idx][knotidx] = + //FISHEYE_CONFIG->SrcRgnMeshInfo[mesh_idx].knot[knotidx].xcor; + // src_y_mesh_tbl[mesh_idx][knotidx] = + //FISHEYE_CONFIG->SrcRgnMeshInfo[mesh_idx].knot[knotidx].ycor; + // dst_x_mesh_tbl[mesh_idx][knotidx] = + //FISHEYE_CONFIG->DstRgnMeshInfo[mesh_idx].knot[knotidx].xcor; + // dst_y_mesh_tbl[mesh_idx][knotidx] = + //FISHEYE_CONFIG->DstRgnMeshInfo[mesh_idx].knot[knotidx].ycor; + } + } + + fclose(fpMesh); + + mesh_tbl_num = TotalMeshNum; // FISHEYE_CONFIG->TotalMeshNum; + int dst_height = height; // FISHEYE_CONFIG->OutH_disp; + int dst_width = width; // FISHEYE_CONFIG->OutW_disp; + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh_tbl_num = %d\n", mesh_tbl_num); + + ///////////////////////////////////////////////////////////////////////////////////// + // mesh scan order preprocessing + ///////////////////////////////////////////////////////////////////////////////////// + int Y_SUBTILE_NUMBER = ceil((float)dst_height / (float)NUMBER_Y_LINE_A_SUBTILE); + int NUMBER_X_LINE_A_TILE = ceil((float)dst_width / (float)X_TILE_NUMBER / 2.0) * 2; + int NUMBER_Y_LINE_A_TILE = + (int)(ceil(ceil((float)dst_height / (float)Y_TILE_NUMBER) / (float)NUMBER_Y_LINE_A_SUBTILE)) * + NUMBER_Y_LINE_A_SUBTILE; + int MAX_MESH_NUM_A_TILE = + ((128 * 2) / X_TILE_NUMBER) * + (1 + + ceil((4 * 128) / (float)dst_height)); // (maximum horizontal meshes number x 2)/horizontal tiles number + uint16_t mesh_scan_tile_mesh_id_list[MAX_MESH_NUM_A_TILE * Y_SUBTILE_NUMBER * X_TILE_NUMBER]; + + int mesh_id_list_entry_num = + cnv_mesh_scan_preproc_3(width, height, dst_width, dst_height, src_x_mesh_tbl, src_y_mesh_tbl, + dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, mesh_scan_tile_mesh_id_list, + Y_SUBTILE_NUMBER, X_TILE_NUMBER, NUMBER_Y_LINE_A_SUBTILE, NUMBER_X_LINE_A_TILE, + Y_TILE_NUMBER, NUMBER_Y_LINE_A_TILE, MAX_MESH_NUM_A_TILE); + + int isrc_x_mesh_tbl[mesh_tbl_num][4]; + int isrc_y_mesh_tbl[mesh_tbl_num][4]; + int idst_x_mesh_tbl[mesh_tbl_num][4]; + int idst_y_mesh_tbl[mesh_tbl_num][4]; + + cnv_mesh_coordinate_float2fixed(src_x_mesh_tbl, src_y_mesh_tbl, dst_x_mesh_tbl, dst_y_mesh_tbl, mesh_tbl_num, + isrc_x_mesh_tbl, isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl); + + int reorder_mesh_tbl_entry_num, reorder_mesh_id_list_entry_num; + + cnv_mesh_tbl_reorder_and_parse_3(mesh_scan_tile_mesh_id_list, mesh_id_list_entry_num, isrc_x_mesh_tbl, + isrc_y_mesh_tbl, idst_x_mesh_tbl, idst_y_mesh_tbl, X_TILE_NUMBER, + Y_TILE_NUMBER, Y_SUBTILE_NUMBER, reorder_mesh_tbl, &reorder_mesh_tbl_entry_num, + reorder_mesh_id_list, &reorder_mesh_id_list_entry_num, mesh_tbl_phy_addr); + + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh table size (bytes) = %d\n", (reorder_mesh_tbl_entry_num * 4)); + CVI_TRACE_GDC(CVI_DBG_INFO, "mesh id list size (bytes) = %d\n", (reorder_mesh_id_list_entry_num * 2)); + + printf("mesh table size (bytes) = %d\n", (reorder_mesh_tbl_entry_num * 4)); + printf("mesh id list size (bytes) = %d\n", (reorder_mesh_id_list_entry_num * 2)); + + return 0; +} +#endif + +void mesh_gen_cnv(const float *pfmesh_data, SIZE_S in_size, SIZE_S out_size, const FISHEYE_ATTR_S *pstFisheyeAttr, + uint64_t mesh_phy_addr, void *mesh_vir_addr) +{ + // FISHEYE_ATTR FISHEYE_CONFIG; + // FISHEYE_REGION_ATTR FISHEYE_REGION[MAX_REGION_NUM]; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "in_size(%d %d) out_size(%d %d)\n", in_size.u32Width, in_size.u32Height, + out_size.u32Width, out_size.u32Height); + + int TotalMeshNum, tw, th; + int tbl_w_mesh_num, tbl_h_mesh_num; + int X_TILE_NUMBER, Y_TILE_NUMBER; + CVI_U32 mesh_id_size, mesh_tbl_size; + CVI_U64 mesh_id_phy_addr, mesh_tbl_phy_addr; + + (void) pstFisheyeAttr; + + // tbl_w_mesh_num = 64; + // tbl_h_mesh_num = 64; + X_TILE_NUMBER = 1; + Y_TILE_NUMBER = 1; + if (pfmesh_data == NULL) { + FILE *fpMesh = fopen("init_mesh_file.txt", "r"); + + fscanf(fpMesh, "%d %d %d %d %d %d %d", &TotalMeshNum, &X_TILE_NUMBER, &Y_TILE_NUMBER, &tbl_w_mesh_num, + &tbl_h_mesh_num, &tw, &th); + fclose(fpMesh); + } else { + // TotalMeshNum = (int) pfmesh_data[0]; + X_TILE_NUMBER = (int)pfmesh_data[1]; + Y_TILE_NUMBER = (int)pfmesh_data[2]; + } + + // calculate mesh_id/mesh_tbl's size in bytes. + mesh_tbl_size = 0x40000; + mesh_id_size = 0x8000; + + // Decide the position of mesh in memory. + mesh_id_phy_addr = mesh_phy_addr; + mesh_tbl_phy_addr = ALIGN(mesh_phy_addr + mesh_id_size, 0x1000); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "phy-addr of mesh id(%#" PRIx64 ") mesh_tbl(%#" PRIx64 ")\n", mesh_id_phy_addr, + mesh_tbl_phy_addr); + CVI_TRACE_GDC(CVI_DBG_DEBUG, "mesh_id_size(%d) mesh_tbl_size(%d)\n", mesh_id_size, mesh_tbl_size); + + int *reorder_mesh_tbl[X_TILE_NUMBER * Y_TILE_NUMBER]; + + // Provide virtual address to write mesh. + reorder_mesh_tbl[0] = mesh_vir_addr + (mesh_tbl_phy_addr - mesh_id_phy_addr); + + if (pfmesh_data == NULL) { + gen_mesh_f_xy_mesh_tbl("init_mesh_file.txt", in_size.u32Width, in_size.u32Height, + (uint16_t *)mesh_vir_addr, reorder_mesh_tbl, mesh_tbl_phy_addr); + } else { + gen_mesh_m_xy_mesh_tbl((float *)pfmesh_data, in_size.u32Width, in_size.u32Height, + (uint16_t *)mesh_vir_addr, reorder_mesh_tbl, mesh_tbl_phy_addr); + } +} + +void mesh_gen_get_size(SIZE_S in_size, SIZE_S out_size, CVI_U32 *mesh_id_size, CVI_U32 *mesh_tbl_size) +{ + if (!mesh_id_size || !mesh_tbl_size) + return; + + (void)in_size; + (void)out_size; + + // CVI_GDC_MESH_SIZE_FISHEYE + *mesh_tbl_size = 0x60000; + *mesh_id_size = 0x50000; +} diff --git a/middleware/v2/modules/vpu/src/gdc_mesh_1822.c b/middleware/v2/modules/vpu/src/gdc_mesh_1822.c new file mode 100644 index 000000000..766ef01de --- /dev/null +++ b/middleware/v2/modules/vpu/src/gdc_mesh_1822.c @@ -0,0 +1,1562 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#if !(defined(__SOC_MARS__) || defined(__SOC_PHOBOS__)) +#include "cvi_common.h" +#include "cvi_math.h" +#include "cvi_comm_video.h" +#endif + +#include "cvi_base.h" +#include "cvi_vpss.h" +#include "cvi_sys.h" +#include "cvi_gdc.h" +#include "gdc_mesh.h" + +#define TILESIZE 64 // HW: data Tile Size +#define HW_MESH_SIZE 8 + +#define MESH_NUM_ATILE (TILESIZE / HW_MESH_SIZE) // how many mesh in A TILE + +#define QFORMAT_M 10 // mesh coordinate's floating precision bit number. +#define PHASEBIT 8 // pixel interpolation phase +#define TILESIZE 64 // HW: data Tile Size +#define HW_MESH_SIZE 8 + +// HW: +#define MAX_WIDTH_MESH_NUM 16 // offline calibration mesh number +#define MAX_HEIGHT_MESH_NUM 16 // offline calibration mesh number. +#define MESH_NUM_ATILE (TILESIZE / HW_MESH_SIZE) // how many mesh in A TILE +#define MAX_FRAME_MESH_NUM (MAX_WIDTH_MESH_NUM * MAX_HEIGHT_MESH_NUM) + +// Fixed CONFIGURATION +#define TWOS_COMPLEMENT 1 // ifndef: sign bit representation: +#define MAX_REGION_NUM 1 + +#define minmax(a, b, c) (((a) < (b)) ? (b):((a) > (c)) ? (c) : (a)) + +// #define SAVE_MESH_TBL_FILE +// #define ENABLE_PROFILE + +typedef struct { + int dwa_en; + + int stage2_rotate_type; // 0: +90, 1: -90 + int bg_color_y_r; + int bg_color_u_g; + int bg_color_v_b; + + int dst_x0; + int dst_y0; + + int src_xstr_s1; + int src_xend_s1; + int src_xstr_s2; + int src_xend_s2; +} _reg_dwa; + +typedef struct COORD2D { + double xcor; + double ycor; +} COORD2D; + +typedef struct COORD2D_INT { + int xcor; + int ycor; +} COORD2D_INT; + +typedef struct COORD2D_INT_HW { + CVI_U8 xcor[3]; // s13.10, 24bit +} __attribute__((packed)) COORD2D_INT_HW; + +typedef struct MESH_STRUCT { + COORD2D knot[4]; + int idx; +} MESH_STRUCT; + +typedef struct LDC_ATTR { + int Enable; // dewarp engine on/off + + int RgnNum; // dewarp Region Number. + int TotalMeshNum; // total mesh numbers + int OutW_disp; // output display frame width + int OutH_disp; // output display frame height + int InCenterX; // input fisheye center position X + int InCenterY; // input fisheye center position Y + int InRadius; // input fisheye radius in pixels. + + // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT DstRgnMeshInfo[MAX_FRAME_MESH_NUM]; + + // frame-based src mesh info. + MESH_STRUCT SrcRgnMeshInfo[MAX_FRAME_MESH_NUM]; + + // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT DstRgnMeshInfoExt[9 * MAX_FRAME_MESH_NUM]; + + // frame-based src mesh info. + MESH_STRUCT SrcRgnMeshInfoExt[9 * MAX_FRAME_MESH_NUM]; + + // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT DstRgnMeshInfoExt2ND[9 * MAX_FRAME_MESH_NUM]; + + // frame-based src mesh info. + MESH_STRUCT SrcRgnMeshInfoExt2ND[9 * MAX_FRAME_MESH_NUM]; + + // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT DstRgnMeshInfo_1st[MAX_FRAME_MESH_NUM]; + + // frame-based src mesh info. + MESH_STRUCT SrcRgnMeshInfo_1st[MAX_FRAME_MESH_NUM]; + + // frame-based dst mesh info. maximum num=128*28 = 16384 meshes. + MESH_STRUCT DstRgnMeshInfo_2nd[MAX_FRAME_MESH_NUM]; + + // frame-based src mesh info. + MESH_STRUCT SrcRgnMeshInfo_2nd[MAX_FRAME_MESH_NUM]; + + // How many tile is sliced in a frame horizontally. + int SliceX_Num; + + // How many tile is sliced in a frame vertically. + int SliceY_Num; +} LDC_ATTR; + +typedef struct LDC_RGN_ATTR { + int RgnIndex; // region index + int InRadius; // For Panorama.360 mode, inner radius. + int OutRadius; // For Panorama.360 mode, outer radius. + int Pan; // Region PTZ-Pan. + int HorZoom; // adjust horizontal zoom in Region PTZ. + int VerZoom; // adjust vertical zoom in Region PTZ. + int OutX; // region initial position x on display frame. + int OutY; // region initial position y on display frame. + int OutW; // region width. + int OutH; // region height. + int MeshHor; // mesh counts horizontal + int MeshVer; // mesh counts vertical + + // to give region default view center + // User set rotation angle around X-axis, create angle between + // vector to Z-axis. (start position @ [0,0,1]) + int ThetaX; + + int ThetaZ; // User set rotation angle around Z-axis + + int ZoomV; // User Set for Region + int PanEnd; // For Panorama Case Only + int RegionValid; // label valid/ invalid for each region + + // initial buffer to store destination mesh info. max: 32*32 + MESH_STRUCT DstRgnMeshInfo[MAX_FRAME_MESH_NUM]; + + // extend to 3x3 range. + MESH_STRUCT DstRgnMeshInfoExt[9 * MAX_FRAME_MESH_NUM]; + + // initial buffer to store source mesh info + MESH_STRUCT SrcRgnMeshInfo[MAX_FRAME_MESH_NUM]; + + // extend to 3x3 range. + MESH_STRUCT SrcRgnMeshInfoExt[9 * MAX_FRAME_MESH_NUM]; +} LDC_RGN_ATTR; + +typedef struct Vector2D { + double x; + double y; +} Vector2D; + +static int _chk_in_mesh(int x, int y, MESH_STRUCT cur_sw_mesh); +static COORD2D _find_knot_map2src(COORD2D_INT cur_dst_mesh, LDC_ATTR *cfg, + int swmesh_hit_index, int stageID); + +static int _double2Int_s13_10(double value); + +void mesh_gen_get_1st_size(SIZE_S in_size, CVI_U32 *mesh_1st_size) +{ + if (!mesh_1st_size) + return; + + CVI_U32 ori_src_width = in_size.u32Width; + CVI_U32 ori_src_height = in_size.u32Height; + + // In LDC Processing, width & height aligned to TILESIZE ** + CVI_U32 src_width_s1 = + ((ori_src_width + TILESIZE - 1) / TILESIZE) * TILESIZE; + CVI_U32 src_height_s1 = + ((ori_src_height + TILESIZE - 1) / TILESIZE) * TILESIZE; + + // modify frame size + CVI_U32 dst_height_s1 = src_height_s1; + CVI_U32 dst_width_s1 = src_width_s1; + CVI_U32 num_tilex_s1 = dst_width_s1 / TILESIZE; + CVI_U32 num_tiley_s1 = dst_height_s1 / TILESIZE; + + *mesh_1st_size = sizeof(struct COORD2D_INT_HW) * MESH_NUM_ATILE * + MESH_NUM_ATILE * num_tilex_s1 * + num_tiley_s1 * 4; // 4 = 4 knots in a mesh +} + +void mesh_gen_get_2nd_size(SIZE_S in_size, CVI_U32 *mesh_2nd_size) +{ + if (!mesh_2nd_size) + return; + + CVI_U32 ori_src_width = in_size.u32Width; + CVI_U32 ori_src_height = in_size.u32Height; + + // In LDC Processing, width & height aligned to TILESIZE + CVI_U32 src_width_s1 = + ((ori_src_width + TILESIZE - 1) / TILESIZE) * TILESIZE; + CVI_U32 src_height_s1 = + ((ori_src_height + TILESIZE - 1) / TILESIZE) * TILESIZE; + + // modify frame size + CVI_U32 dst_height_s1 = src_height_s1; + CVI_U32 dst_width_s1 = src_width_s1; + CVI_U32 src_height_s2 = dst_width_s1; + CVI_U32 src_width_s2 = dst_height_s1; + CVI_U32 dst_height_s2 = src_height_s2; + CVI_U32 dst_width_s2 = src_width_s2; + CVI_U32 num_tilex_s2 = dst_width_s2 / TILESIZE; + CVI_U32 num_tiley_s2 = dst_height_s2 / TILESIZE; + + *mesh_2nd_size = sizeof(struct COORD2D_INT_HW) * MESH_NUM_ATILE * + MESH_NUM_ATILE * num_tilex_s2 * + num_tiley_s2 * 4; // 4 = 4 knots in a mesh +} + +void mesh_gen_get_size(SIZE_S in_size, SIZE_S out_size, + CVI_U32 *mesh_1st_size, + CVI_U32 *mesh_2nd_size) +{ + if (!mesh_1st_size || !mesh_2nd_size) + return; + + (void)out_size; + + mesh_gen_get_1st_size(in_size, mesh_1st_size); + mesh_gen_get_2nd_size(in_size, mesh_2nd_size); +} + +#ifdef SAVE_MESH_TBL_FILE +static void _save_1st_src_mdxy(int num_tilex_s1, COORD2D_INT_HW *src_1st_list, + int tidx, int tidy, FILE *fp1x) +{ + int midx, midy, xidx, yidx; + uint32_t idx; + + for (midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (midx = 0; midx < MESH_NUM_ATILE; midx++) { + xidx = tidx * MESH_NUM_ATILE + midx; + yidx = tidy * MESH_NUM_ATILE + midy; + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 0; + + fprintf(fp1x, "%02x%02x%02x ", + src_1st_list[idx].xcor[2], + src_1st_list[idx].xcor[1], + src_1st_list[idx].xcor[0]); + + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 1; + fprintf(fp1x, "%02x%02x%02x ", + src_1st_list[idx].xcor[2], + src_1st_list[idx].xcor[1], + src_1st_list[idx].xcor[0]); + } + } + + if (midy == MESH_NUM_ATILE - 1) { + for (midx = 0; midx < MESH_NUM_ATILE; midx++) { + xidx = tidx * MESH_NUM_ATILE + midx; + yidx = tidy * MESH_NUM_ATILE + midy; + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 3; + fprintf(fp1x, "%02x%02x%02x ", + src_1st_list[idx].xcor[2], + src_1st_list[idx].xcor[1], + src_1st_list[idx].xcor[0]); + + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 2; + fprintf(fp1x, + "%02x%02x%02x ", + src_1st_list[idx].xcor[2], + src_1st_list[idx].xcor[1], + src_1st_list[idx].xcor[0]); + } + } + } + } + fprintf(fp1x, "\n"); +} + +static void save_1st_src_mesh_table(int num_tiley_s1, int num_tilex_s1, + COORD2D_INT_HW *src_1st_list) +{ + // packed data in dram for HW + FILE *fp1x = fopen("srcx_1st_mesh.txt", "w"); + + if (!fp1x) + return; + + for (int tidy = 0; tidy < num_tiley_s1; tidy++) { + for (int tidx = 0; tidx < num_tilex_s1; tidx++) + _save_1st_src_mdxy(num_tilex_s1, src_1st_list, tidx, tidy, fp1x); + } + fclose(fp1x); +} + +static void _save_2nd_src_mdxy(int num_tilex_s2, COORD2D_INT_HW *src_2nd_list, + int tidx, int tidy, FILE *fp2x) +{ + int midx, midy, xidx, yidx; + uint32_t idx; + + for (midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (midx = 0; midx < MESH_NUM_ATILE; midx++) { + xidx = tidx * MESH_NUM_ATILE + midx; + yidx = tidy * MESH_NUM_ATILE + midy; + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 0; + + fprintf(fp2x, "%02x%02x%02x ", + src_2nd_list[idx].xcor[2], + src_2nd_list[idx].xcor[1], + src_2nd_list[idx].xcor[0]); + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 1; + + fprintf(fp2x, "%02x%02x%02x ", + src_2nd_list[idx].xcor[2], + src_2nd_list[idx].xcor[1], + src_2nd_list[idx].xcor[0]); + } + } + + if (midy == MESH_NUM_ATILE - 1) { + for (midx = 0; midx < MESH_NUM_ATILE; midx++) { + xidx = tidx * MESH_NUM_ATILE + midx; + yidx = tidy * MESH_NUM_ATILE + midy; + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 3; + + fprintf(fp2x, "%02x%02x%02x ", + src_2nd_list[idx].xcor[2], + src_2nd_list[idx].xcor[1], + src_2nd_list[idx].xcor[0]); + + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 2; + fprintf(fp2x, + "%02x%02x%02x ", + src_2nd_list[idx].xcor[2], + src_2nd_list[idx].xcor[1], + src_2nd_list[idx].xcor[0]); + } + } + } + } + fprintf(fp2x, "\n"); +} + +static void save_2nd_src_mesh_table(int num_tiley_s2, int num_tilex_s2, + COORD2D_INT_HW *src_2nd_list, + CVI_U32 mesh_2nd_size) +{ + // packed data in dram for HW + FILE *fp2x_bin = fopen("srcx_2nd_mesh.bin", "wb"); + + if (fp2x_bin) { + size_t wr_size = fwrite(src_2nd_list, mesh_2nd_size, 1, fp2x_bin); + + if (wr_size != mesh_2nd_size) + CVI_TRACE_GDC(CVI_DBG_ERR, + "2nd src mesh, fwrite %d, only %d succeed\n", + mesh_2nd_size, wr_size); + fclose(fp2x_bin); + } + + FILE *fp2x = fopen("srcx_2nd_mesh.txt", "w"); + + if (fp2x) { + for (int tidy = 0; tidy < num_tiley_s2; tidy++) { + for (int tidx = 0; tidx < num_tilex_s2; tidx++) + _save_2nd_src_mdxy(num_tilex_s2, src_2nd_list, tidx, tidy, fp2x); + } + fclose(fp2x); + } +} + +static void save_mesh_info(LDC_ATTR *cfg) +{ + FILE *fpsrc = fopen("mesh_frm_src.txt", "w"); + FILE *fpdst = fopen("mesh_frm_dst.txt", "w"); + + for (int meshidx = 0; meshidx < 9 * MAX_FRAME_MESH_NUM; meshidx++) { + fprintf(fpsrc, "meshidx = %d\n", meshidx); + fprintf(fpdst, "meshidx = %d\n", meshidx); + + for (int knotidx = 0; knotidx < 4; knotidx++) { + fprintf(fpsrc, "[%d]( %f, %f)\n", knotidx, + cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].xcor, + cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + fprintf(fpdst, "[%d]( %f, %f)\n", knotidx, + cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].xcor, + cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + } + + fprintf(fpsrc, "\n"); + fprintf(fpdst, "\n"); + } + fclose(fpsrc); + fclose(fpdst); +} +#endif // SAVE_MESH_TBL_FILE + +static CVI_S32 _convert_1st_src_midxy(int num_tilex_s1, CVI_U32 mesh_1st_size, + COORD2D_INT_HW *src_1st_list, int tidx, int tidy, uint8_t *ptr, + uint32_t *offset_p) +{ + uint32_t offset = *offset_p; + CVI_U32 idx; + + for (int midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + + if (offset >= (mesh_1st_size - 2)) + return CVI_ERR_GDC_ILLEGAL_PARAM; + + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 0; + ptr[offset++] = src_1st_list[idx].xcor[0]; + ptr[offset++] = src_1st_list[idx].xcor[1]; + ptr[offset++] = src_1st_list[idx].xcor[2]; + + if (midx == MESH_NUM_ATILE - 1) { + if (offset >= (mesh_1st_size - 2)) + return CVI_ERR_GDC_ILLEGAL_PARAM; + + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 1; + ptr[offset++] = src_1st_list[idx].xcor[0]; + ptr[offset++] = src_1st_list[idx].xcor[1]; + ptr[offset++] = src_1st_list[idx].xcor[2]; + } + } + + if (midy == MESH_NUM_ATILE - 1) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + + if (offset >= (mesh_1st_size - 2)) + return CVI_ERR_GDC_ILLEGAL_PARAM; + + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 3; + ptr[offset++] = src_1st_list[idx].xcor[0]; + ptr[offset++] = src_1st_list[idx].xcor[1]; + ptr[offset++] = src_1st_list[idx].xcor[2]; + + if (midx == MESH_NUM_ATILE - 1) { + if (offset >= (mesh_1st_size - 2)) { + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + idx = (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + 2; + ptr[offset++] = src_1st_list[idx].xcor[0]; + ptr[offset++] = src_1st_list[idx].xcor[1]; + ptr[offset++] = src_1st_list[idx].xcor[2]; + } + } + } + } + + *offset_p = offset; + + return CVI_SUCCESS; +} + +static CVI_S32 convert_1st_src_mesh_table(int num_tiley_s1, int num_tilex_s1, + COORD2D_INT_HW *src_1st_list, COORD2D_INT_HW *src_1st_list_1d, + CVI_U32 mesh_1st_size) +{ + // packed data in dram for HW + uint8_t *ptr = (uint8_t *)src_1st_list_1d; + uint32_t offset = 0; + CVI_S32 ret; + + for (int tidy = 0; tidy < num_tiley_s1; tidy++) { + for (int tidx = 0; tidx < num_tilex_s1; tidx++) { + ret = _convert_1st_src_midxy(num_tilex_s1, mesh_1st_size, + src_1st_list, tidx, tidy, ptr, + &offset); + if (ret != CVI_SUCCESS) + return ret; + + // # 256 bytes per tile + for (uint32_t i = 0; i < 13; i++) + ptr[offset++] = 0xab; + + } + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " offset=%d, mesh_1st_size=%d\n", + offset, mesh_1st_size); + +#ifdef SAVE_MESH_TBL_FILE + FILE *fp1x_bin = fopen("srcx_1st_mesh.bin", "wb"); + + if (fp1x_bin) { + size_t wr_size = fwrite(src_1st_list_1d, mesh_1st_size, 1, fp1x_bin); + + if (wr_size != mesh_1st_size) + CVI_TRACE_GDC(CVI_DBG_DEBUG, + "1st src mesh, fwrite %d, only %d succeed\n", + mesh_1st_size, wr_size); + fclose(fp1x_bin); + } +#endif + + return CVI_SUCCESS; +} + +static CVI_S32 _get_1st_src_midxy(int num_tilex_s1, + LDC_ATTR *cfg, COORD2D_INT_HW *src_1st_list, int tidx, int tidy) +{ + CVI_U32 max_mesh_num = 9 * (MAX_HEIGHT_MESH_NUM * MAX_WIDTH_MESH_NUM); + + // go check all meshes inside. + for (int midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + // each grid mesh from destination + // find the mapping coordinate onto the source. + COORD2D_INT cur_dst_mesh[4]; + + memset(cur_dst_mesh, 0, sizeof(cur_dst_mesh)); + + cur_dst_mesh[0].xcor = (tidx * TILESIZE) + (midx + 0) * HW_MESH_SIZE; + cur_dst_mesh[1].xcor = (tidx * TILESIZE) + (midx + 1) * HW_MESH_SIZE; + cur_dst_mesh[2].xcor = (tidx * TILESIZE) + (midx + 1) * HW_MESH_SIZE; + cur_dst_mesh[3].xcor = (tidx * TILESIZE) + (midx + 0) * HW_MESH_SIZE; + + cur_dst_mesh[0].ycor = (tidy * TILESIZE) + (midy + 0) * HW_MESH_SIZE; + cur_dst_mesh[1].ycor = (tidy * TILESIZE) + (midy + 0) * HW_MESH_SIZE; + cur_dst_mesh[2].ycor = (tidy * TILESIZE) + (midy + 1) * HW_MESH_SIZE; + cur_dst_mesh[3].ycor = (tidy * TILESIZE) + (midy + 1) * HW_MESH_SIZE; + + // for each knot of grid cur_dst_mesh, check all sw mesh + // "on source" to estimate approximation. + // swmesh_hit_index[N] is to record which sw-mesh index + // cur knot-N hit. + uint32_t swmesh_hit_index[4]; + + for (int i = 0; i < 4; i++) + swmesh_hit_index[i] = 0xFFFFFFFF; + + // go through al hwmesh knots + for (int knotidx = 0; knotidx < 4; knotidx++) { + for (uint32_t meshidx = 0; meshidx < max_mesh_num; meshidx++) { + MESH_STRUCT cur_sw_mesh; + MESH_STRUCT *dst = &cfg->DstRgnMeshInfoExt[meshidx]; + MESH_STRUCT *src = &cfg->SrcRgnMeshInfoExt[meshidx]; + + // load cur_sw_mesh to check if hwmesh's knot is in it? + for (int swknotidx = 0; swknotidx < 4; swknotidx++) { + // 1st stage, SW destination( x, y ) = ( int ,float ) + // 1st stage, SW source( x,y ) = ( float, float ) + cur_sw_mesh.knot[swknotidx].xcor = + dst->knot[swknotidx].xcor; + cur_sw_mesh.knot[swknotidx].ycor = + src->knot[swknotidx].ycor; + } + + // check if cur-pixel in this mesh + int sw_mesh_hit = _chk_in_mesh(cur_dst_mesh[knotidx].xcor, + cur_dst_mesh[knotidx].ycor, cur_sw_mesh); + if (sw_mesh_hit) { + swmesh_hit_index[knotidx] = meshidx; + break; + } + } + + // each knot has been + // assigned a swmesh index + // to estimate approximation. + // do estimation here: + COORD2D map_src_knot; + + memset(&map_src_knot, 0, sizeof(map_src_knot)); + + if (swmesh_hit_index[knotidx] == 0xFFFFFFFF) { + CVI_TRACE_GDC(CVI_DBG_ERR, + " knotidx = %d tidx = %d tidy = %d,\n", + knotidx, tidx, tidy); + CVI_TRACE_GDC(CVI_DBG_ERR, " midx = %d, midy = %d,\n", midx, + midy); + CVI_TRACE_GDC(CVI_DBG_ERR, + " cur_dst_mesh[%d] = (%d, %d)\n", knotidx, + cur_dst_mesh[knotidx].xcor, + cur_dst_mesh[knotidx].ycor); + CVI_TRACE_GDC(CVI_DBG_ERR, " DEBUG STASRT!!\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + map_src_knot = _find_knot_map2src(cur_dst_mesh[knotidx], cfg, + swmesh_hit_index[knotidx], 0); //0 = 1st stage + + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + uint32_t xcor = (uint32_t)_double2Int_s13_10(map_src_knot.xcor); + uint32_t offset = + (yidx * (num_tilex_s1 * MESH_NUM_ATILE) + xidx) * 4 + + knotidx; + + src_1st_list[offset].xcor[0] = xcor & 0xff; + src_1st_list[offset].xcor[1] = (xcor >> 8) & 0xff; + src_1st_list[offset].xcor[2] = (xcor >> 16) & 0xff; + } + } + } + + return CVI_SUCCESS; +} + +static CVI_S32 _offline_get_1st_src_mesh_table(int num_tiley_s1, + int num_tilex_s1, + LDC_ATTR *cfg, + COORD2D_INT_HW *src_1st_list) +{ + CVI_S32 ret; + + // 1st stage buffer data. + for (int tidy = 0; tidy < num_tiley_s1; tidy++) { + for (int tidx = 0; tidx < num_tilex_s1; tidx++) { + ret = _get_1st_src_midxy(num_tilex_s1, cfg, + src_1st_list, tidx, tidy); + if (ret != CVI_SUCCESS) + return ret; + } + CVI_TRACE_GDC(CVI_DBG_DEBUG, " OFFLINE tidy = %d\n", tidy); + } + +#ifdef SAVE_MESH_TBL_FILE + save_1st_src_mesh_table(num_tiley_s1, num_tilex_s1, src_1st_list); +#endif + + return CVI_SUCCESS; +} + +static void _convert_2nd_src_midxy(int num_tilex_s2, + COORD2D_INT_HW *src_2nd_list, int tidx, int tidy, uint8_t *ptr, + uint32_t *offset_ptr) +{ + uint32_t offset = *offset_ptr; + CVI_U32 idx; + + for (int midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 0; + ptr[offset++] = src_2nd_list[idx].xcor[0]; + ptr[offset++] = src_2nd_list[idx].xcor[1]; + ptr[offset++] = src_2nd_list[idx].xcor[2]; + + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 1; + ptr[offset++] = src_2nd_list[idx].xcor[0]; + ptr[offset++] = src_2nd_list[idx].xcor[1]; + ptr[offset++] = src_2nd_list[idx].xcor[2]; + } + } + + if (midy == MESH_NUM_ATILE - 1) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 3; + ptr[offset++] = src_2nd_list[idx].xcor[0]; + ptr[offset++] = src_2nd_list[idx].xcor[1]; + ptr[offset++] = src_2nd_list[idx].xcor[2]; + + if (midx == MESH_NUM_ATILE - 1) { + idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + 2; + ptr[offset++] = src_2nd_list[idx].xcor[0]; + ptr[offset++] = src_2nd_list[idx].xcor[1]; + ptr[offset++] = src_2nd_list[idx].xcor[2]; + } + } + } + } + + *offset_ptr = offset; +} + +static void convert_2nd_src_mesh_table(int num_tiley_s2, int num_tilex_s2, + COORD2D_INT_HW *src_2nd_list, + COORD2D_INT_HW *src_2nd_list_1d, + CVI_U32 mesh_2nd_size) +{ + // packed data in dram for HW + uint8_t *ptr = (uint8_t *)src_2nd_list_1d; + uint32_t offset = 0; + uint32_t map_file_size = num_tiley_s2 * num_tilex_s2 * 256; + + if (mesh_2nd_size < map_file_size) { + CVI_TRACE_GDC(CVI_DBG_ERR, + "error, mesh_2nd_size(%d) < map_file_size(%d)\n", + mesh_2nd_size, map_file_size); + return; + } + + for (int tidy = 0; tidy < num_tiley_s2; tidy++) { + for (int tidx = 0; tidx < num_tilex_s2; tidx++) { + _convert_2nd_src_midxy(num_tilex_s2, src_2nd_list, tidx, + tidy, ptr, &offset); + + // # 256 bytes per tile + // fout.write(bytearray([0xab]*13)) + for (uint32_t i = 0; i < 13; i++) + ptr[offset++] = 0xab; + } + } + +#ifdef SAVE_MESH_TBL_FILE + FILE *fp2x_bin = fopen("srcx_2nd_mesh.bin", "wb"); + size_t wr_size = fwrite(src_2nd_list_1d, mesh_2nd_size, 1, fp2x_bin); + + if (wr_size != mesh_2nd_size) + CVI_TRACE_GDC(CVI_DBG_DEBUG, + "2nd src mesh, fwrite %d, only %d succeed\n", + mesh_2nd_size, wr_size); + fclose(fp2x_bin); +#endif +} + +static CVI_S32 _fill_src_2nd_list(int num_tilex_s2, LDC_ATTR *cfg, + COORD2D_INT_HW *src_2nd_list, int tidx, int tidy, int midx, int midy, + MESH_STRUCT *dstMesh, COORD2D_INT *cur_dst_mesh, + uint32_t *swmesh_hit_index) +{ + CVI_U32 max_mesh_num = 9 * (MAX_HEIGHT_MESH_NUM * MAX_WIDTH_MESH_NUM); + + // go through all hwmesh knots + for (int knotidx = 0; knotidx < 4; knotidx++) { + for (CVI_U32 meshidx = 0; meshidx < max_mesh_num; meshidx++) { + MESH_STRUCT cur_sw_mesh; + + // load cur_sw_mesh to check if hwmesh's knot is in it? + for (int swknotidx = 0; swknotidx < 4; swknotidx++) { + // 1st stage, SW destination( x, y ) = ( int ,float ) + // 1st stage, SW source( x,y ) = ( float, float ) + cur_sw_mesh.knot[swknotidx].xcor = + dstMesh[meshidx].knot[swknotidx].xcor; + cur_sw_mesh.knot[swknotidx].ycor = + dstMesh[meshidx].knot[swknotidx].ycor; + } + + // check if cur-pixel in this mesh + int sw_mesh_hit = _chk_in_mesh(cur_dst_mesh[knotidx].xcor, + cur_dst_mesh[knotidx].ycor, cur_sw_mesh); + + if (sw_mesh_hit) { + swmesh_hit_index[knotidx] = meshidx; + continue; + } + } + + // each knot has been assigned a swmesh index to estimate approximation. + // do estimation here: + // int knotMissingFlag = 0; + COORD2D map_src_knot; + + memset(&map_src_knot, 0, sizeof(map_src_knot)); + //COORD2D_INT map_src_knot_32bit; + if (swmesh_hit_index[knotidx] == 0xFFFFFFFF) { + CVI_TRACE_GDC(CVI_DBG_ERR, " !!!! 2ndSTAG----ERROR !!!\n"); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + map_src_knot = _find_knot_map2src(cur_dst_mesh[knotidx], cfg, + swmesh_hit_index[knotidx], 1); // 1: 2nd stage + + // update to buffer order should align to interpolation index: + int xidx = tidx * MESH_NUM_ATILE + midx; + int yidx = tidy * MESH_NUM_ATILE + midy; + + uint32_t xcor = (uint32_t)_double2Int_s13_10(map_src_knot.xcor); + uint32_t idx = (yidx * (num_tilex_s2 * MESH_NUM_ATILE) + xidx) * 4 + + knotidx; + + src_2nd_list[idx].xcor[0] = xcor & 0xff; + src_2nd_list[idx].xcor[1] = (xcor >> 8) & 0xff; + src_2nd_list[idx].xcor[2] = (xcor >> 16) & 0xff; + } + + return CVI_SUCCESS; +} + +static CVI_S32 _offline_get_2nd_src_mesh_table(int stage2_rotate_type, + int num_tiley_s2, int num_tilex_s2, LDC_ATTR *cfg, + COORD2D_INT_HW *src_2nd_list, int src_width_s1, int src_height_s1, + CVI_U32 mesh_2nd_size) +{ + // stage2_rotate_type = 0: +90 degrees + // stage2_rotate_type = 1: -90 degrees + + CVI_U32 max_mesh_num = 9 * (MAX_HEIGHT_MESH_NUM * MAX_WIDTH_MESH_NUM); + + int RMATRIX[2][2]; + MESH_STRUCT *dstMesh = cfg->DstRgnMeshInfoExt2ND; + MESH_STRUCT *srcMesh = cfg->SrcRgnMeshInfoExt2ND; + + CVI_S32 ret; + + if (stage2_rotate_type) { + //-90 degrees + RMATRIX[0][0] = 0; + RMATRIX[0][1] = -1; + RMATRIX[1][0] = 1; + RMATRIX[1][1] = 0; + } else { + // + 90 degrees + RMATRIX[0][0] = 0; + RMATRIX[0][1] = 1; + RMATRIX[1][0] = -1; + RMATRIX[1][1] = 0; + } + + for (CVI_U32 meshidx = 0; meshidx < max_mesh_num; meshidx++) { + for (int knotidx = 0; knotidx < 4; knotidx++) { + dstMesh[meshidx].knot[knotidx].xcor = + RMATRIX[0][0] * (cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].xcor) + + RMATRIX[0][1] * (cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + + dstMesh[meshidx].knot[knotidx].ycor = + RMATRIX[1][0] * (cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].xcor) + + RMATRIX[1][1] * (cfg->DstRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + + srcMesh[meshidx].knot[knotidx].xcor = + RMATRIX[0][0] * (cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].xcor) + + RMATRIX[0][1] * (cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + + srcMesh[meshidx].knot[knotidx].ycor = + RMATRIX[1][0] * (cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].xcor) + + RMATRIX[1][1] * (cfg->SrcRgnMeshInfoExt[meshidx].knot[knotidx].ycor); + + if (RMATRIX[0][1] == 1) { + dstMesh[meshidx].knot[knotidx].xcor += 0; + dstMesh[meshidx].knot[knotidx].ycor += (src_width_s1 - 1); + srcMesh[meshidx].knot[knotidx].xcor += 0; + srcMesh[meshidx].knot[knotidx].ycor += (src_width_s1 - 1); + } else { + // +90 + dstMesh[meshidx].knot[knotidx].xcor += (src_height_s1 - 1); + dstMesh[meshidx].knot[knotidx].ycor += 0; + srcMesh[meshidx].knot[knotidx].xcor += (src_height_s1 - 1); + srcMesh[meshidx].knot[knotidx].ycor += 0; + } + } + } + CVI_TRACE_GDC(CVI_DBG_DEBUG, " rotate mesh table by 90 degree done!!\n"); + + // 1st stage buffer data. + for (int tidy = 0; tidy < num_tiley_s2; tidy++) { + for (int tidx = 0; tidx < num_tilex_s2; tidx++) { + // tmp buffer for dump data + // for each tile + // go check all meshes inside. + for (int midy = 0; midy < MESH_NUM_ATILE; midy++) { + for (int midx = 0; midx < MESH_NUM_ATILE; midx++) { + // each grid mesh from destination + // find the mapping coordinate onto the source. + COORD2D_INT cur_dst_mesh[4]; + + memset(cur_dst_mesh, 0, sizeof(cur_dst_mesh)); + + cur_dst_mesh[0].xcor = (tidx * TILESIZE) + (midx + 0) * HW_MESH_SIZE; + cur_dst_mesh[1].xcor = (tidx * TILESIZE) + (midx + 1) * HW_MESH_SIZE; + cur_dst_mesh[2].xcor = (tidx * TILESIZE) + (midx + 1) * HW_MESH_SIZE; + cur_dst_mesh[3].xcor = (tidx * TILESIZE) + (midx + 0) * HW_MESH_SIZE; + + cur_dst_mesh[0].ycor = (tidy * TILESIZE) + (midy + 0) * HW_MESH_SIZE; + cur_dst_mesh[1].ycor = (tidy * TILESIZE) + (midy + 0) * HW_MESH_SIZE; + cur_dst_mesh[2].ycor = (tidy * TILESIZE) + (midy + 1) * HW_MESH_SIZE; + cur_dst_mesh[3].ycor = (tidy * TILESIZE) + (midy + 1) * HW_MESH_SIZE; + + // for each knot of grid cur_dst_mesh, check all sw mesh "on source" to + // estimate approximation. + // swmesh_hit_index[N] is to record which sw-mesh index cur knot-N hit. + uint32_t swmesh_hit_index[4]; + + for (int i = 0; i < 4; i++) + swmesh_hit_index[i] = 0xFFFFFFFF; + + ret = _fill_src_2nd_list(num_tilex_s2, cfg, src_2nd_list, + tidx, tidy, midx, midy, + dstMesh, cur_dst_mesh, swmesh_hit_index); + if (ret != CVI_SUCCESS) + return ret; + } + } + } + CVI_TRACE_GDC(CVI_DBG_DEBUG, " 2nd Stage OFFLINE tidy = %d\n", tidy); + } + +#ifdef SAVE_MESH_TBL_FILE + save_2nd_src_mesh_table(num_tiley_s2, num_tilex_s2, src_2nd_list, mesh_2nd_size); +#else + (void)mesh_2nd_size; +#endif + + return CVI_SUCCESS; +} + +static void _ldc_attr_map_cv182x(const LDC_ATTR_S *pstLDCAttr, LDC_ATTR *cfg, + LDC_RGN_ATTR *rgn_attr, double x0, + double y0, double r) +{ + // Global Initialization + cfg->Enable = 1; + cfg->OutW_disp = (int)x0 * 2; // -200; + cfg->OutH_disp = (int)y0 * 2; // -200; + cfg->InCenterX = (int)x0; // front-end set. + cfg->InCenterY = (int)y0; // front-end set. + cfg->InRadius = (int)r; // front-end set. + + cfg->SliceX_Num = 2; + cfg->SliceY_Num = 2; + + cfg->RgnNum = 1; + rgn_attr[0].RegionValid = 1; + rgn_attr[0].ZoomV = pstLDCAttr->bAspect; + rgn_attr[0].Pan = pstLDCAttr->s32XYRatio; + rgn_attr[0].PanEnd = pstLDCAttr->s32DistortionRatio; + rgn_attr[0].OutW = cfg->OutW_disp; + rgn_attr[0].OutH = cfg->OutH_disp; + rgn_attr[0].OutX = 0; + rgn_attr[0].OutY = 0; + rgn_attr[0].InRadius = pstLDCAttr->s32CenterXOffset; + rgn_attr[0].OutRadius = pstLDCAttr->s32CenterYOffset; + rgn_attr[0].MeshVer = 16; + rgn_attr[0].MeshHor = 16; + rgn_attr[0].ThetaX = pstLDCAttr->s32XRatio; + rgn_attr[0].ThetaZ = pstLDCAttr->s32YRatio; +} + +static CVI_S32 _get_region_dst_mesh_list(LDC_RGN_ATTR *rgn_attr, int view_w, + int view_h, int mesh_horcnt, int mesh_vercnt, int rgn_idx) +{ + if (rgn_attr[rgn_idx].RegionValid != 1) + return CVI_ERR_GDC_ILLEGAL_PARAM; + + // 1st loop: to find mesh infos. on source ( backward projection ) + // hit index for buffer + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " view_h = %d,\n", view_h); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " view_w = %d,\n", view_w); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " mesh_horcnt = %d,\n", mesh_horcnt); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " mesh_vercnt = %d,\n", mesh_vercnt); + + int mesh_xstep = ((1 << PHASEBIT) * (view_w) / mesh_horcnt); //.2 + int mesh_ystep = ((1 << PHASEBIT) * (view_h) / mesh_vercnt); //.2 + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " mesh_xstep = %d,\n", mesh_xstep); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " mesh_ystep = %d,\n", mesh_ystep); + + // give 3 types + // 1. normal grid mesh geeration. + // 2. center high resoution. + // 3. boundary high resolution. + // To extend to 3x size to cover miss hit area. + + for (int j = 0; j < mesh_vercnt; j++) { + for (int i = 0; i < mesh_horcnt; i++) { + int meshidx = j * mesh_horcnt + i; + + if (meshidx >= MAX_FRAME_MESH_NUM) { + CVI_TRACE_GDC(CVI_DBG_WARN, " [%d][%d] meshidx = %d >= MAX_FRAME_MESH_NUM(%d)\n", + j, i, meshidx, MAX_FRAME_MESH_NUM); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + + int xcor = (mesh_xstep * (i + 0)) >> PHASEBIT; + int xcor_r = (mesh_xstep * (i + 1)) >> PHASEBIT; + int ycor = (mesh_ystep * (j + 0)) >> PHASEBIT; + int ycor_d = (mesh_ystep * (j + 1)) >> PHASEBIT; + + xcor_r = MIN(view_w - 1, xcor_r); + ycor_d = MIN(view_h - 1, ycor_d); + + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].xcor = xcor; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[0].ycor = ycor; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].xcor = xcor_r; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[1].ycor = ycor; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].xcor = xcor_r; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[2].ycor = ycor_d; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].xcor = xcor; + rgn_attr[rgn_idx].DstRgnMeshInfo[meshidx].knot[3].ycor = ycor_d; + } + + if (j && + 0 != (rgn_attr[rgn_idx].DstRgnMeshInfo[j * mesh_horcnt].knot[0].ycor - + rgn_attr[rgn_idx].DstRgnMeshInfo[(j - 1) * mesh_horcnt].knot[3].ycor)) { + CVI_TRACE_GDC(CVI_DBG_WARN, + " WARNING!!!!!!! Mesh are not tightly connected to each other!!!\n"); + CVI_TRACE_GDC(CVI_DBG_WARN, " Check The Position: "); + CVI_TRACE_GDC(CVI_DBG_WARN, " [%d] DstRgnMeshInfo[%d * %d].knot[0].ycor = %10f\n", + rgn_idx, j, mesh_horcnt, + rgn_attr[rgn_idx].DstRgnMeshInfo[j * mesh_horcnt].knot[0].ycor); + CVI_TRACE_GDC(CVI_DBG_WARN, " [%d] DstRgnMeshInfo[(%d - 1) * %d].knot[3] = %10f\n", + rgn_idx, j, mesh_horcnt, + rgn_attr[rgn_idx].DstRgnMeshInfo[j * mesh_horcnt].knot[3].ycor); + return CVI_ERR_GDC_ILLEGAL_PARAM; + } + } + + // Third part ---------------------------------------------------------- + // Extend Destination Mesh Grid to 3x3 large. + // extend destination mesh here, off line work!! + // Why need extend ? + // 1st stage de-warp of pincushion case: + // our mapping is grid mesh from final destination to source. + // distorion of vertical area has no mesh covered on it. + // we need to create mesh mapping for these area, so to extend 3x3 + // final destination meshes. + // --------------------------------------------------------------------- + for (int reorder_meshidx = 0; reorder_meshidx < 9 * (mesh_horcnt * mesh_vercnt); reorder_meshidx++) { + int mesh_horcntExt = (mesh_horcnt * 3); + + int reorder_idy = (reorder_meshidx / mesh_horcntExt); + int reorder_idx = reorder_meshidx - (reorder_idy * mesh_horcntExt); + + int ori_idx = reorder_idx % mesh_horcnt; + int ori_idy = reorder_idy % mesh_vercnt; + + int ext_idx = (reorder_idx / mesh_horcnt) - 1; // -1, 0, +1 + int ext_idy = (reorder_idy / mesh_vercnt) - 1; // -1, 0, +1 + + for (int knotidx = 0; knotidx < 4; knotidx++) { + // view "-1": ex: ori: 1079, upside = 179 - 1079 = 0 + rgn_attr[0].DstRgnMeshInfoExt[reorder_meshidx].knot[knotidx].xcor = + rgn_attr[0].DstRgnMeshInfo[ori_idy * mesh_horcnt + + ori_idx].knot[knotidx].xcor + ext_idx * (view_w - 1); + + rgn_attr[0].DstRgnMeshInfoExt[reorder_meshidx].knot[knotidx].ycor = + rgn_attr[0].DstRgnMeshInfo[ori_idy * mesh_horcnt + + ori_idx].knot[knotidx].ycor + ext_idy * (view_h - 1); + } + } + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " PASS2!!!!\n\r"); + return CVI_SUCCESS; +} + +static COORD2D _find_knot_map2src(COORD2D_INT cur_dst_mesh, LDC_ATTR *cfg, + int swmesh_hit_index, int stageID) +{ + COORD2D knot_source; + MESH_STRUCT cur_dst_sw_mesh; + MESH_STRUCT cur_src_sw_mesh; + MESH_STRUCT *dstMesh = cfg->DstRgnMeshInfoExt; + MESH_STRUCT *srcMesh = cfg->SrcRgnMeshInfoExt; + MESH_STRUCT *dstMesh2ND = cfg->DstRgnMeshInfoExt2ND; + MESH_STRUCT *srcMesh2ND = cfg->SrcRgnMeshInfoExt2ND; + + //====================================================================== + // input current destination grid mesh + // input cur_dst_mesh hit stage-destination mesh index + // load cur stage-destination mesh by given mesh index + // calculate vector coefficients a & b + // By coefficients a & b, mapping onto the cooridnate on source frame + //====================================================================== + + // check which triangle cur-pxl locates in, + for (int knotidx = 0; knotidx < 4; knotidx++) { + if (stageID == 0) { + cur_dst_sw_mesh.knot[knotidx].xcor = dstMesh[swmesh_hit_index].knot[knotidx].xcor; + cur_dst_sw_mesh.knot[knotidx].ycor = srcMesh[swmesh_hit_index].knot[knotidx].ycor; + + cur_src_sw_mesh.knot[knotidx].xcor = srcMesh[swmesh_hit_index].knot[knotidx].xcor; + cur_src_sw_mesh.knot[knotidx].ycor = srcMesh[swmesh_hit_index].knot[knotidx].ycor; + } else { + cur_dst_sw_mesh.knot[knotidx].xcor = dstMesh2ND[swmesh_hit_index].knot[knotidx].xcor; + cur_dst_sw_mesh.knot[knotidx].ycor = dstMesh2ND[swmesh_hit_index].knot[knotidx].ycor; + + cur_src_sw_mesh.knot[knotidx].xcor = srcMesh2ND[swmesh_hit_index].knot[knotidx].xcor; + cur_src_sw_mesh.knot[knotidx].ycor = dstMesh2ND[swmesh_hit_index].knot[knotidx].ycor; + } + } + + // fixed in side 01 & side 23 + double x01_a = (double)cur_dst_mesh.xcor - cur_dst_sw_mesh.knot[(0 + stageID) % 4].xcor; + double x01_b = cur_dst_sw_mesh.knot[(1 + stageID) % 4].xcor - (double)cur_dst_mesh.xcor; + + COORD2D INTER_01, INTER_32; + + INTER_01.xcor = cur_dst_sw_mesh.knot[(0 + stageID) % 4].xcor + + (cur_dst_sw_mesh.knot[(1 + stageID) % 4].xcor - + cur_dst_sw_mesh.knot[(0 + stageID) % 4].xcor) * (x01_a) / (x01_a + x01_b); + INTER_01.ycor = cur_dst_sw_mesh.knot[(0 + stageID) % 4].ycor + + (cur_dst_sw_mesh.knot[(1 + stageID) % 4].ycor - + cur_dst_sw_mesh.knot[(0 + stageID) % 4].ycor) * (x01_a) / (x01_a + x01_b); + INTER_32.xcor = cur_dst_sw_mesh.knot[(3 + stageID) % 4].xcor + + (cur_dst_sw_mesh.knot[(2 + stageID) % 4].xcor - + cur_dst_sw_mesh.knot[(3 + stageID) % 4].xcor) * (x01_a) / (x01_a + x01_b); + INTER_32.ycor = cur_dst_sw_mesh.knot[(3 + stageID) % 4].ycor + + (cur_dst_sw_mesh.knot[(2 + stageID) % 4].ycor - + cur_dst_sw_mesh.knot[(3 + stageID) % 4].ycor) * (x01_a) / (x01_a + x01_b); + + double y01_a = (double)cur_dst_mesh.ycor - INTER_01.ycor; + double y01_b = INTER_32.ycor - (double)cur_dst_mesh.ycor; + + COORD2D INTER_01_SRC, INTER_32_SRC; + + INTER_01_SRC.xcor = cur_src_sw_mesh.knot[(0 + stageID) % 4].xcor + + (cur_src_sw_mesh.knot[(1 + stageID) % 4].xcor - + cur_src_sw_mesh.knot[(0 + stageID) % 4].xcor) * (x01_a) / (x01_a + x01_b); + INTER_32_SRC.xcor = cur_src_sw_mesh.knot[(3 + stageID) % 4].xcor + + (cur_src_sw_mesh.knot[(2 + stageID) % 4].xcor - + cur_src_sw_mesh.knot[(3 + stageID) % 4].xcor) * (x01_a) / (x01_a + x01_b); + + knot_source.ycor = (double)cur_dst_mesh.ycor; + knot_source.xcor = INTER_01_SRC.xcor + (INTER_32_SRC.xcor - INTER_01_SRC.xcor) * (y01_a) / (y01_a + y01_b); + + return knot_source; +} + +static void _get_frame_mesh_list(LDC_ATTR *cfg, LDC_RGN_ATTR *rgn_attr) +{ + // pack all regions' mesh info, including src & dst. + int rgnNum = cfg->RgnNum; + int meshNumRgn[MAX_REGION_NUM]; + int frameMeshIdx = 0; + + for (int i = 0; i < rgnNum; i++) { + if (rgn_attr[i].RegionValid == 1) { + meshNumRgn[i] = (rgn_attr[i].MeshHor * rgn_attr[i].MeshVer); + + // go through each region loop + for (int meshidx = 0; meshidx < 9 * meshNumRgn[i]; meshidx++) { + // each mesh has 4 knots + for (int knotidx = 0; knotidx < 4; knotidx++) { + cfg->DstRgnMeshInfoExt[frameMeshIdx].knot[knotidx].xcor = + rgn_attr[i].DstRgnMeshInfoExt[meshidx].knot[knotidx].xcor; + cfg->DstRgnMeshInfoExt[frameMeshIdx].knot[knotidx].ycor = + rgn_attr[i].DstRgnMeshInfoExt[meshidx].knot[knotidx].ycor; + + cfg->SrcRgnMeshInfoExt[frameMeshIdx].knot[knotidx].xcor = + rgn_attr[i].SrcRgnMeshInfoExt[meshidx].knot[knotidx].xcor; + cfg->SrcRgnMeshInfoExt[frameMeshIdx].knot[knotidx].ycor = + rgn_attr[i].SrcRgnMeshInfoExt[meshidx].knot[knotidx].ycor; + } + frameMeshIdx += 1; + } + } + } + + // update mesh index number + cfg->TotalMeshNum = frameMeshIdx; + +#ifdef SAVE_MESH_TBL_FILE + save_mesh_info(cfg); +#endif +} + +static void _get_region_src_mesh_list(LDC_RGN_ATTR *rgn_attr, int rgn_idx, + double x0, double y0) +{ + int view_w = rgn_attr[rgn_idx].OutW; + int view_h = rgn_attr[rgn_idx].OutH; + int mesh_horcnt = rgn_attr[rgn_idx].MeshHor; + int mesh_vercnt = rgn_attr[rgn_idx].MeshVer; + + // register: + bool bAspect = (bool)rgn_attr[0].ZoomV; + int XYRatio = minmax(rgn_attr[0].Pan, 0, 100); + int XRatio = minmax(rgn_attr[0].ThetaX, 0, 100); + int YRatio = minmax(rgn_attr[0].ThetaZ, 0, 100); + int CenterXOffset = minmax(rgn_attr[0].InRadius, -511, 511); + int CenterYOffset = minmax(rgn_attr[0].OutRadius, -511, 511); + int DistortionRatio = minmax(rgn_attr[0].PanEnd, -300, 500); + + double norm = sqrt((view_w / 2) * (view_w / 2) + (view_h / 2) * (view_h / 2)); + + // internal link to register: + double k = (double)DistortionRatio / 1000.0; + double ud_gain = (1 + k * (((double)view_h / 2) * (double)view_h / 2) / norm / norm); + double lr_gain = (1 + k * (((double)view_w / 2) * (double)view_w / 2) / norm / norm); + + double Aspect_gainX = MAX(ud_gain, lr_gain); + double Aspect_gainY = MAX(ud_gain, lr_gain); + Vector2D dist2d; + + for (int i = 0; i < 9*(mesh_horcnt * mesh_vercnt); i++) { + // Do LDC mapping in Center Mesh Grid only + for (int knotidx = 0; knotidx < 4; knotidx++) { + double x = rgn_attr[rgn_idx].DstRgnMeshInfoExt[i].knot[knotidx].xcor - + rgn_attr[rgn_idx].OutX - rgn_attr[rgn_idx].OutW / 2; + double y = rgn_attr[rgn_idx].DstRgnMeshInfoExt[i].knot[knotidx].ycor - + rgn_attr[rgn_idx].OutY - rgn_attr[rgn_idx].OutH / 2; + + x = x - CenterXOffset; // -view_w / 2 + 1, view_w / 2 - 1); + y = y - CenterYOffset; // -view_h / 2 + 1, view_h / 2 - 1); + + x = x / Aspect_gainX; + y = y / Aspect_gainY; + + if (bAspect == true) { + x = x * (1 - 0.333 * (100 - XYRatio) / 100); + y = y * (1 - 0.333 * (100 - XYRatio) / 100); + } else { + x = x * (1 - 0.333 * (100 - XRatio) / 100); + y = y * (1 - 0.333 * (100 - YRatio) / 100); + } + + double rd = MIN(norm, sqrt(x * x + y * y)); + + dist2d.x = x * (1 + k * ((rd / norm) * (rd / norm))); + dist2d.y = y * (1 + k * ((rd / norm) * (rd / norm))); + + // update source mesh-info here + rgn_attr[rgn_idx].SrcRgnMeshInfoExt[i].knot[knotidx].xcor = dist2d.x + x0 + CenterXOffset; + rgn_attr[rgn_idx].SrcRgnMeshInfoExt[i].knot[knotidx].ycor = dist2d.y + y0 + CenterYOffset; + } + } +} + +static int _chk_location_to_line(COORD2D *meshcorA, COORD2D *meshcorB, int x, + int y, int inc_zero) +{ + int onright = 0; + + // along vector from A -> B + // A(x1, y1) to B(x2, y2), P(x0�Ay0) outsize the line + // determine which side the point resides + // a = (x2 - x1, y2 - y1) + // b = (x0 - x1, y0 - y1) + + double x1 = meshcorA->xcor; + double y1 = meshcorA->ycor; + double x2 = meshcorB->xcor; + double y2 = meshcorB->ycor; + + double tmp = (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1); + + // has optional inclusion of zero as in mesh. + onright = inc_zero ? (tmp >= 0) : (tmp > 0); + + return onright; +} + +static int _double2Int_s13_10(double value) +{ +#ifdef TWOS_COMPLEMENT + //double abs_value = abs(value); + //double dtmp2cpl = abs_value * 1024; + int tmp2cpl = (int)(abs((int)(value * (1 << QFORMAT_M)))); + + // get 24 bit + tmp2cpl = tmp2cpl & 0xFFFFFF; + + int rtn_value = tmp2cpl; + + if (value < 0) + rtn_value = (~tmp2cpl) + 1; + else + rtn_value = rtn_value; + + rtn_value = rtn_value & 0xFFFFFF; + +#else + int sbit = (value < 0) ? 1 : 0; + int tmp2cpl = (int)(abs(value) * (1 << QFORMAT_M)); + int rtn_value = sbit << (13 + QFORMAT_M) | tmp2cpl; // s13.QFORMAT_M +#endif + return rtn_value; +} + +static int _chk_in_mesh(int x, int y, MESH_STRUCT cur_sw_mesh) +{ + int inthismesh_hit = 0; + int onright_01 = _chk_location_to_line(&cur_sw_mesh.knot[0], &cur_sw_mesh.knot[1], x, y, 1); + int onright_12 = _chk_location_to_line(&cur_sw_mesh.knot[1], &cur_sw_mesh.knot[2], x, y, 0); + int onright_23 = _chk_location_to_line(&cur_sw_mesh.knot[2], &cur_sw_mesh.knot[3], x, y, 0); + int onright_30 = _chk_location_to_line(&cur_sw_mesh.knot[3], &cur_sw_mesh.knot[0], x, y, 1); + + // in mesh case: clockwise: 0 -> 1 -> 2 -> 3 + // & counter clockwise: 3 -> 2 -> 1 -> 0 + // onright_01, onright_12, onright_23, onright_30, = ( 1, 1, 1, 1 ) + // onright_01, onright_12, onright_23, onright_30, = ( 0, 0, 0, 0 ) + + // inside the mesh + if ((onright_01 == onright_12) && (onright_12 == onright_23) && (onright_23 == onright_30)) { + inthismesh_hit = 1; + } else { + inthismesh_hit = 0; + } + return inthismesh_hit; +} + +void mesh_gen_rotation(SIZE_S in_size, SIZE_S out_size, ROTATION_E rot, + uint64_t mesh_phy_addr, void *mesh_vir_addr) +{ + (void)in_size; + (void)out_size; + (void)rot; + (void)mesh_phy_addr; + (void)mesh_vir_addr; + + // No need to generate mesh +} + +void mesh_gen_fisheye(SIZE_S in_size, SIZE_S out_size, + const FISHEYE_ATTR_S *pstFisheyeAttr, + uint64_t mesh_phy_addr, void *mesh_vir_addr, + ROTATION_E rot) +{ + (void)in_size; + (void)out_size; + (void)pstFisheyeAttr; + (void)mesh_phy_addr; + (void)mesh_vir_addr; + (void)rot; +} + +CVI_S32 mesh_gen_ldc(SIZE_S in_size, SIZE_S out_size, + const LDC_ATTR_S *pstLDCAttr, uint64_t mesh_phy_addr, + void *mesh_vir_addr, ROTATION_E rot) +{ + CVI_S32 ret = CVI_SUCCESS; + _reg_dwa reg; + COORD2D_INT_HW *src_1st_list_1d = NULL, *src_2nd_list_1d = NULL; + COORD2D_INT_HW *src_1st_list = NULL, *src_2nd_list = NULL; + LDC_ATTR *cfg = NULL; + LDC_RGN_ATTR *rgn_attr = NULL; +#ifdef ENABLE_PROFILE + struct timespec start, end; +#endif + + (void)mesh_phy_addr; + (void)rot; + + CVI_U32 mesh_1st_size = 0, mesh_2nd_size = 0; + + mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size); + src_1st_list_1d = (COORD2D_INT_HW *)mesh_vir_addr; + src_2nd_list_1d = (COORD2D_INT_HW *)(mesh_vir_addr + mesh_1st_size); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " 1st src_1st_list=%p(%d), src_2nd_list=%p(%d)\n", + src_1st_list_1d, mesh_1st_size, src_2nd_list_1d, mesh_2nd_size); + + src_1st_list = (COORD2D_INT_HW *)malloc(mesh_1st_size); + src_2nd_list = (COORD2D_INT_HW *)malloc(mesh_2nd_size); + cfg = (LDC_ATTR *)calloc(1, sizeof(*cfg)); + rgn_attr = (LDC_RGN_ATTR *)calloc(1, sizeof(*rgn_attr) * MAX_REGION_NUM); + if (!src_1st_list || !src_2nd_list || !cfg || !rgn_attr) { + free(src_1st_list); + free(src_2nd_list); + free(cfg); + free(rgn_attr); + + CVI_TRACE_GDC(CVI_DBG_ERR, " fail to alloc mesh\n"); + return CVI_ERR_GDC_NOMEM; + } + + // al registers + reg.dwa_en = 1; + reg.stage2_rotate_type = 0; + + int bgc_pack = 0x00217E; + + reg.bg_color_y_r = (bgc_pack & 0xFF0000) >> 16; + reg.bg_color_u_g = (bgc_pack & 0x00FF00) >> 8; + reg.bg_color_v_b = (bgc_pack & 0x0000FF) >> 0; + + int ori_src_width = in_size.u32Width; + int ori_src_height = in_size.u32Height; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " ori_src_width = %d,\n", ori_src_width); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " ori_src_height = %d,\n", ori_src_height); + + // In LDC Processing, width & height aligned to TILESIZE ** + int src_width_s1 = ((ori_src_width + TILESIZE - 1) / TILESIZE) * TILESIZE; + int src_height_s1 = ((ori_src_height + TILESIZE - 1) / TILESIZE) * TILESIZE; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " src_width_s1 = %d,\n", src_width_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " src_height_s1 = %d,\n", src_height_s1); + + // auto assign correct range: + reg.src_xstr_s1 = 0; + reg.src_xend_s1 = ori_src_width - 1; + reg.src_xstr_s2 = reg.stage2_rotate_type ? (src_height_s1 - ori_src_height) : 0; + reg.src_xend_s2 = reg.stage2_rotate_type ? (src_height_s1 - 1) : (ori_src_height - 1); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.stage2_rotate_type = %d,\n", reg.stage2_rotate_type); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.bg_color_y_r = %d,\n", reg.bg_color_y_r); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.bg_color_u_g = %d,\n", reg.bg_color_u_g); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.bg_color_v_b = %d,\n", reg.bg_color_v_b); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.src_xstart_s1 = %d,\n", reg.src_xstr_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.src_xend_s1 = %d,\n", reg.src_xend_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.src_xstart_s2 = %d,\n", reg.src_xstr_s2); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " reg.src_xend_s2 = %d,\n", reg.src_xend_s2); + + int x0, y0, r; + + x0 = ori_src_width / 2; + y0 = ori_src_height / 2; + r = MIN(x0, y0); + + CVI_TRACE_GDC(CVI_DBG_DEBUG, "cfg size %d\n", (int)sizeof(LDC_ATTR)); + + // update parameters + _ldc_attr_map_cv182x(pstLDCAttr, cfg, rgn_attr, x0, y0, r); + + // In Each Mode, for Every Region: + for (int rgn_idx = 0; rgn_idx < cfg->RgnNum; rgn_idx++) { + // check region valid first + if (!rgn_attr[rgn_idx].RegionValid) + return CVI_ERR_GDC_ILLEGAL_PARAM; + + // Destination Mesh-Info Allocation + int view_w = rgn_attr[rgn_idx].OutW; + int view_h = rgn_attr[rgn_idx].OutH; + int mesh_horcnt = rgn_attr[rgn_idx].MeshHor; + int mesh_vercnt = rgn_attr[rgn_idx].MeshVer; + + // get & store region mesh info. +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + ret |= _get_region_dst_mesh_list(rgn_attr, view_w, view_h, mesh_horcnt, mesh_vercnt, rgn_idx); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " _get_region_dst_mesh_list: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + + // Get Source Mesh-Info Projected from Destination by Differet ViewModw. +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + _get_region_src_mesh_list(rgn_attr, rgn_idx, x0, y0); //, mat0); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " _get_region_src_mesh_list: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + + // debug msg + CVI_TRACE_GDC(CVI_DBG_DEBUG, " REGION %d done.\n", rgn_idx); + } + + //combine all region meshs - mesh projection done. +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + _get_frame_mesh_list(cfg, rgn_attr); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " _get_frame_mesh_list: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + + // modify frame size + int dst_height_s1 = src_height_s1; + int dst_width_s1 = src_width_s1; + int src_height_s2 = dst_width_s1; + int src_width_s2 = dst_height_s1; + int dst_height_s2 = src_height_s2; + int dst_width_s2 = src_width_s2; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " dst_height_s1 = %d,\n", dst_height_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " dst_width_s1 = %d,\n", dst_width_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " src_height_s2 = %d,\n", src_height_s2); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " src_width_s2 = %d,\n", src_width_s2); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " dst_height_s2 = %d,\n", dst_height_s2); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " dst_width_s2 = %d,\n", dst_width_s2); + + // 1st-stage, in(1984, 1088 ) -> out(1984, 1088) + // 2nd-stage, in(1088, 1984 ) -> out(1088, 1984) + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " 1st-stage, in(%d, %d ) -> out(%d, %d)\n", + src_width_s1, src_height_s1, dst_width_s1, dst_height_s1); + CVI_TRACE_GDC(CVI_DBG_DEBUG, " 2nd-stage, in(%d, %d ) -> out(%d, %d)\n", + src_width_s2, src_height_s2, dst_width_s2, dst_height_s2); + + // tileNum: 1st stage =( 31 X 17 ) 2nd stage = ( 17 X 31 ) + + int num_tilex_s1 = dst_width_s1 / TILESIZE; + int num_tiley_s1 = dst_height_s1 / TILESIZE; + int num_tilex_s2 = dst_width_s2 / TILESIZE; + int num_tiley_s2 = dst_height_s2 / TILESIZE; + + CVI_TRACE_GDC(CVI_DBG_DEBUG, " tileNum: 1st stage =( %d X %d ) 2nd stage = ( %d X %d )\n", + num_tilex_s1, num_tiley_s1, num_tilex_s2, num_tiley_s2); + + // to calculate each stage source mesh x-data. +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + ret |= _offline_get_1st_src_mesh_table(num_tiley_s1, num_tilex_s1, cfg, src_1st_list); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " _offline_get_1st_src_mesh_table: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + ret |= _offline_get_2nd_src_mesh_table(reg.stage2_rotate_type, num_tiley_s2, num_tilex_s2, cfg, + src_2nd_list, src_width_s1, src_height_s1, mesh_2nd_size); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " _offline_get_2nd_src_mesh_table: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + convert_1st_src_mesh_table(num_tiley_s1, num_tilex_s1, src_1st_list, src_1st_list_1d, mesh_1st_size); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " convert_1st_src_mesh_table: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &start); +#endif + convert_2nd_src_mesh_table(num_tiley_s2, num_tilex_s2, src_2nd_list, src_2nd_list_1d, mesh_2nd_size); +#ifdef ENABLE_PROFILE + clock_gettime(CLOCK_MONOTONIC, &end); + CVI_TRACE_GDC(CVI_DBG_ERR, " convert_2nd_src_mesh_table: %ldms\n", + get_diff_in_us(start, end) / 1000); +#endif + + free(src_1st_list); + free(src_2nd_list); + free(cfg); + free(rgn_attr); + + return ret; +} + +void mesh_gen_cnv(const float *pfmesh_data, SIZE_S in_size, SIZE_S out_size, + const FISHEYE_ATTR_S *pstFisheyeAttr, uint64_t mesh_phy_addr, + void *mesh_vir_addr) +{ + (void)pfmesh_data; + (void)in_size; + (void)out_size; + (void)pstFisheyeAttr; + (void)mesh_phy_addr; + (void)mesh_vir_addr; +} diff --git a/middleware/v2/modules/vpu/src/rgn_ioctl.c b/middleware/v2/modules/vpu/src/rgn_ioctl.c new file mode 100644 index 000000000..20f26f48a --- /dev/null +++ b/middleware/v2/modules/vpu/src/rgn_ioctl.c @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include +#include "rgn_ioctl.h" + +#include + +static inline CVI_S32 S_CTRL_PTR(int _fd, void *_cfg, int _ioctl, CVI_U32 _handle) +{ + struct rgn_ext_control ec1; + + memset(&ec1, 0, sizeof(ec1)); + ec1.id = _ioctl; + ec1.handle = _handle; + ec1.ptr1 = (void *) _cfg; + + if (ioctl(_fd, RGN_IOC_S_CTRL, &ec1) < 0) { + fprintf(stderr, "RGN_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno)); + return -1; + } + return 0; +} + +static inline CVI_S32 SDK_CTRL_GET_CFG(int _fd, void *_cfg1, void *_cfg2, int _ioctl, CVI_U32 _handle) +{ + struct rgn_ext_control ec1; + + memset(&ec1, 0, sizeof(ec1)); + ec1.id = RGN_IOCTL_SDK_CTRL; + ec1.sdk_id = _ioctl; + ec1.handle = _handle; + ec1.ptr1 = _cfg1; + ec1.ptr2 = _cfg2; + + if (ioctl(_fd, RGN_IOC_G_CTRL, &ec1) < 0) { + fprintf(stderr, "RGN_SDK_IOC_G_CTRL(%d-%d) - %s NG, %s\n", + ec1.id, ec1.sdk_id, __func__, strerror(errno)); + return -1; + } + return 0; +} + +static inline CVI_S32 SDK_CTRL_SET_CFG(int _fd, void *_cfg1, void *_cfg2, int _ioctl, CVI_U32 _handle) +{ + struct rgn_ext_control ec1; + + memset(&ec1, 0, sizeof(ec1)); + ec1.id = RGN_IOCTL_SDK_CTRL; + ec1.sdk_id = _ioctl; + ec1.handle = _handle; + ec1.ptr1 = _cfg1; + ec1.ptr2 = _cfg2; + + if (ioctl(_fd, RGN_IOC_S_CTRL, &ec1) < 0) { + fprintf(stderr, "RGN_SDK_IOC_S_CTRL(%d-%d) - %s NG, %s\n", + ec1.id, ec1.sdk_id, __func__, strerror(errno)); + return -1; + } + return 0; +} + +int rgn_create(int fd, int Handle, const RGN_ATTR_S *pstRegion) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_CREATE, Handle); +} + +int rgn_destroy(int fd, int Handle) +{ + return SDK_CTRL_SET_CFG(fd, NULL, NULL, RGN_SDK_DESTORY, Handle); +} + +int rgn_get_attr(int fd, int Handle, RGN_ATTR_S *pstRegion) +{ + return SDK_CTRL_GET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_GET_ATTR, Handle); +} + +int rgn_set_attr(int fd, int Handle, const RGN_ATTR_S *pstRegion) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_SET_ATTR, Handle); +} + +int rgn_set_bit_map(int fd, int Handle, const BITMAP_S *pstBitmap) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstBitmap, NULL, RGN_SDK_SET_BIT_MAP, Handle); +} + +int rgn_attach_to_chn(int fd, int Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstChnAttr, RGN_SDK_ATTACH_TO_CHN, Handle); +} + +int rgn_detach_from_chn(int fd, int Handle, const MMF_CHN_S *pstChn) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstChn, NULL, RGN_SDK_DETACH_FROM_CHN, Handle); +} + +int rgn_set_display_attr(int fd, int Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstChnAttr, RGN_SDK_SET_DISPLAY_ATTR, Handle); +} + +int rgn_get_display_attr(int fd, int Handle, const MMF_CHN_S *pstChn, RGN_CHN_ATTR_S *pstChnAttr) +{ + return SDK_CTRL_GET_CFG(fd, (void *)pstChn, pstChnAttr, RGN_SDK_GET_DISPLAY_ATTR, Handle); +} + +int rgn_get_canvas_info(int fd, int Handle, RGN_CANVAS_INFO_S *pstCanvasInfo) +{ + return SDK_CTRL_GET_CFG(fd, (void *)pstCanvasInfo, NULL, RGN_SDK_GET_CANVAS_INFO, Handle); +} + +int rgn_update_canvas(int fd, int Handle) +{ + return SDK_CTRL_SET_CFG(fd, NULL, NULL, RGN_SDK_UPDATE_CANVAS, Handle); +} + +int rgn_invert_color(int fd, int Handle, MMF_CHN_S *pstChn, void *pu32Color) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstChn, pu32Color, RGN_SDK_INVERT_COLOR, Handle); +} + +int rgn_set_chn_palette(int fd, int Handle, const MMF_CHN_S *pstChn, RGN_PALETTE_S *pstPalette) +{ + return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstPalette, RGN_SDK_SET_CHN_PALETTE, Handle); +} diff --git a/middleware/v2/modules/vpu/src/vi_ioctl.c b/middleware/v2/modules/vpu/src/vi_ioctl.c new file mode 100644 index 000000000..5d6599995 --- /dev/null +++ b/middleware/v2/modules/vpu/src/vi_ioctl.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include +#include +#include "vi_ioctl.h" + +#include + +#define S_CTRL_VALUE(_fd, _cfg, _ioctl)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = _cfg;\ + if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define S_CTRL_VALUE64(_fd, _cfg, _ioctl)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value64 = _cfg;\ + if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define S_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define G_CTRL_VALUE(_fd, _out, _ioctl)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = 0;\ + if (ioctl(_fd, VI_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + *_out = ec1.value;\ + return 0;\ + } while (0) + +#define G_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, VI_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define SDK_CTRL_SET_CFG(_fd, _cfg, _ioctl, _dev, _pipe, _chn, _val)\ + do {\ + struct vi_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = VI_IOCTL_SDK_CTRL;\ + ec1.sdk_id = _ioctl;\ + ec1.sdk_cfg.dev = _dev;\ + ec1.sdk_cfg.pipe = _pipe;\ + ec1.sdk_cfg.chn = _chn;\ + ec1.sdk_cfg.val = _val;\ + ec1.sdk_cfg.ptr = (void *)_cfg;\ + if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VI_SDK_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +int vi_enable_usr_pic(int fd, bool enable) +{ + S_CTRL_VALUE(fd, enable, VI_IOCTL_USR_PIC_ONOFF); +} + +int vi_set_usr_pic(int fd, struct cvi_isp_usr_pic_cfg *cfg) +{ + S_CTRL_PTR(fd, cfg, VI_IOCTL_USR_PIC_CFG); +} + +int vi_put_usr_pic(int fd, CVI_U64 phyAddr) +{ + S_CTRL_VALUE64(fd, phyAddr, VI_IOCTL_USR_PIC_PUT); +} + +int vi_set_usr_pic_timing(int fd, CVI_U32 fps) +{ + S_CTRL_VALUE(fd, fps, VI_IOCTL_USR_PIC_TIMING); +} + +int vi_set_be_online(int fd, CVI_BOOL online) +{ + S_CTRL_VALUE(fd, online, VI_IOCTL_BE_ONLINE); +} + +int vi_set_online(int fd, CVI_BOOL online) +{ + S_CTRL_VALUE(fd, online, VI_IOCTL_ONLINE); +} + +int vi_set_hdr(int fd, CVI_BOOL is_hdr_on) +{ + S_CTRL_VALUE(fd, is_hdr_on, VI_IOCTL_HDR); +} + +int vi_set_3dnr(int fd, CVI_BOOL is_3dnr_on) +{ + S_CTRL_VALUE(fd, is_3dnr_on, VI_IOCTL_3DNR); +} + +int vi_get_pipe_dump(int fd, struct cvi_vip_isp_raw_blk *raw_dump) +{ + G_CTRL_PTR(fd, raw_dump, VI_IOCTL_GET_PIPE_DUMP); +} + +int vi_put_pipe_dump(int fd, CVI_U32 dev_num) +{ + S_CTRL_VALUE(fd, dev_num, VI_IOCTL_PUT_PIPE_DUMP); +} + +int vi_set_yuv_bypass_path(int fd, struct cvi_vip_isp_yuv_param *param) +{ + S_CTRL_PTR(fd, param, VI_IOCTL_YUV_BYPASS_PATH); +} + +int vi_set_compress_mode(int fd, CVI_BOOL is_compress_on) +{ + S_CTRL_VALUE(fd, is_compress_on, VI_IOCTL_COMPRESS_EN); +} + +int vi_set_lvds_flow(int fd, CVI_BOOL is_lvds_flow_on) +{ + S_CTRL_VALUE(fd, is_lvds_flow_on, VI_IOCTL_SUBLVDS_PATH); +} + +int vi_set_clk(int fd, CVI_BOOL clk_on) +{ + S_CTRL_VALUE(fd, clk_on, VI_IOCTL_CLK_CTRL); +} + +#ifdef ARCH_CV182X +int vi_set_rgbir(int fd, CVI_BOOL is_rgbir) +{ + S_CTRL_VALUE(fd, is_rgbir, VI_IOCTL_RGBIR); +} +#endif + +int vi_get_ip_dump_list(int fd, struct ip_info *ip_info_list) +{ + G_CTRL_PTR(fd, ip_info_list, VI_IOCTL_GET_IP_INFO); +} + +int vi_set_trig_preraw(int fd, CVI_U32 dev_num) +{ + S_CTRL_VALUE(fd, dev_num, VI_IOCTL_TRIG_PRERAW); +} + +int vi_set_online2sc(int fd, struct cvi_isp_sc_online *online) +{ + S_CTRL_PTR(fd, online, VI_IOCTL_SC_ONLINE); +} + +int vi_get_tun_addr(int fd, struct isp_tuning_cfg *tun_buf_info) +{ + G_CTRL_PTR(fd, tun_buf_info, VI_IOCTL_GET_TUN_ADDR); +} + +int vi_get_rgbmap_le_buf(int fd, struct cvi_vip_memblock *buf) +{ + G_CTRL_PTR(fd, buf, VI_IOCTL_GET_RGBMAP_LE_PHY_BUF); +} + +int vi_get_rgbmap_se_buf(int fd, struct cvi_vip_memblock *buf) +{ + G_CTRL_PTR(fd, buf, VI_IOCTL_GET_RGBMAP_SE_PHY_BUF); +} + +int vi_get_dma_size(int fd, CVI_U32 *size) +{ + G_CTRL_VALUE(fd, size, VI_IOCTL_GET_BUF_SIZE); +} + +int vi_set_dma_buf_info(int fd, struct cvi_vi_dma_buf_info *param) +{ + S_CTRL_PTR(fd, param, VI_IOCTL_SET_DMA_BUF_INFO); +} + +int vi_set_enq_buf(int fd, struct vi_buffer *buf) +{ + S_CTRL_PTR(fd, buf, VI_IOCTL_ENQ_BUF); +} + +int vi_set_start_streaming(int fd) +{ + S_CTRL_VALUE(fd, 1, VI_IOCTL_START_STREAMING); +} + +int vi_set_stop_streaming(int fd) +{ + S_CTRL_VALUE(fd, 1, VI_IOCTL_STOP_STREAMING); +} + +int vi_sdk_set_dev_attr(int fd, int dev, VI_DEV_ATTR_S *pstDevAttr) +{ + SDK_CTRL_SET_CFG(fd, pstDevAttr, VI_SDK_SET_DEV_ATTR, dev, -1, -1, -1); +} + +int vi_sdk_get_dev_attr(int fd, int dev, VI_DEV_ATTR_S *pstDevAttr) +{ + SDK_CTRL_SET_CFG(fd, pstDevAttr, VI_SDK_GET_DEV_ATTR, dev, -1, -1, -1); +} + +int vi_sdk_enable_dev(int fd, int dev) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_DEV, dev, -1, -1, -1); +} + +int vi_sdk_create_pipe(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr) +{ + SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_CREATE_PIPE, -1, pipe, -1, -1); +} + +int vi_sdk_start_pipe(int fd, int pipe) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_START_PIPE, -1, pipe, -1, -1); +} + +int vi_sdk_get_chn_attr(int fd, int pipe, int chn, VI_CHN_ATTR_S *pstChnAttr) +{ + SDK_CTRL_SET_CFG(fd, pstChnAttr, VI_SDK_GET_CHN_ATTR, -1, pipe, chn, -1); +} + +int vi_sdk_set_chn_attr(int fd, int pipe, int chn, VI_CHN_ATTR_S *pstChnAttr) +{ + SDK_CTRL_SET_CFG(fd, pstChnAttr, VI_SDK_SET_CHN_ATTR, -1, pipe, chn, -1); +} + +int vi_sdk_enable_chn(int fd, int pipe, int chn) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_CHN, -1, pipe, chn, -1); +} + +int vi_sdk_disable_chn(int fd, int pipe, int chn) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_DISABLE_CHN, -1, pipe, chn, -1); +} + +int vi_sdk_set_motion_lv(int fd, struct mlv_info_s *pmlv_i) +{ + SDK_CTRL_SET_CFG(fd, pmlv_i, VI_SDK_SET_MOTION_LV, -1, -1, -1, -1); +} + +int vi_sdk_enable_dis(int fd, int pipe) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_DIS, -1, pipe, -1, -1); +} + +int vi_sdk_disable_dis(int fd, int pipe) +{ + SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_DISABLE_DIS, -1, pipe, -1, -1); +} + +int vi_sdk_set_dis_info(int fd, struct dis_info_s *pdis_i) +{ + SDK_CTRL_SET_CFG(fd, pdis_i, VI_SDK_SET_DIS_INFO, -1, -1, -1, -1); +} + +int vi_sdk_set_dev_timing_attr(int fd, int dev, VI_DEV_TIMING_ATTR_S *pstDevTimingAttr) +{ + SDK_CTRL_SET_CFG(fd, pstDevTimingAttr, VI_SDK_SET_DEV_TIMING_ATTR, dev, -1, -1, -1); +} + +int vi_sdk_set_pipe_frm_src(int fd, int pipe, VI_PIPE_FRAME_SOURCE_E *source) +{ + SDK_CTRL_SET_CFG(fd, source, VI_SDK_SET_PIPE_FRM_SRC, -1, pipe, -1, -1); +} + +int vi_sdk_send_pipe_raw(int fd, int pipe, VIDEO_FRAME_INFO_S *sVideoFrm) +{ + SDK_CTRL_SET_CFG(fd, sVideoFrm, VI_SDK_SEND_PIPE_RAW, -1, pipe, -1, -1); +} + +int vi_sdk_get_chn_frame(int fd, int pipe, int chn, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_CHN_FRAME, -1, pipe, chn, s32MilliSec); +} + +int vi_sdk_release_chn_frame(int fd, int pipe, int chn, VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_RELEASE_CHN_FRAME, -1, pipe, chn, -1); +} + +int vi_sdk_set_chn_crop(int fd, int pipe, int chn, VI_CROP_INFO_S *pstCropInfo) +{ + SDK_CTRL_SET_CFG(fd, pstCropInfo, VI_SDK_SET_CHN_CROP, -1, pipe, chn, -1); +} + +int vi_sdk_get_chn_crop(int fd, int pipe, int chn, VI_CROP_INFO_S *pstCropInfo) +{ + SDK_CTRL_SET_CFG(fd, pstCropInfo, VI_SDK_GET_CHN_CROP, -1, pipe, chn, -1); +} + +int vi_sdk_get_pipe_attr(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr) +{ + SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_GET_PIPE_ATTR, -1, pipe, -1, -1); +} + +int vi_sdk_set_pipe_attr(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr) +{ + SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_SET_PIPE_ATTR, -1, pipe, -1, -1); +} + +int vi_sdk_get_pipe_dump_attr(int fd, int pipe, VI_DUMP_ATTR_S *pstDumpAttr) +{ + SDK_CTRL_SET_CFG(fd, pstDumpAttr, VI_SDK_GET_PIPE_DUMP_ATTR, -1, pipe, -1, -1); +} + +int vi_sdk_set_pipe_dump_attr(int fd, int pipe, VI_DUMP_ATTR_S *pstDumpAttr) +{ + SDK_CTRL_SET_CFG(fd, pstDumpAttr, VI_SDK_SET_PIPE_DUMP_ATTR, -1, pipe, -1, -1); +} + +int vi_sdk_get_pipe_frame(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_PIPE_FRAME, -1, pipe, -1, s32MilliSec); +} + +int vi_sdk_release_pipe_frame(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_RELEASE_PIPE_FRAME, -1, pipe, -1, -1); +} + +int vi_sdk_start_smooth_rawdump(int fd, int pipe, struct cvi_vip_isp_smooth_raw_param *smooth_raw_param) +{ + SDK_CTRL_SET_CFG(fd, smooth_raw_param, VI_SDK_START_SMOOTH_RAWDUMP, -1, pipe, -1, -1); +} + +int vi_sdk_stop_smooth_rawdump(int fd, int pipe, struct cvi_vip_isp_smooth_raw_param *smooth_raw_param) +{ + SDK_CTRL_SET_CFG(fd, smooth_raw_param, VI_SDK_STOP_SMOOTH_RAWDUMP, -1, pipe, -1, -1); +} + +int vi_sdk_get_smooth_rawdump(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_SMOOTH_RAWDUMP, -1, pipe, -1, s32MilliSec); +} + +int vi_sdk_put_smooth_rawdump(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo) +{ + SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_PUT_SMOOTH_RAWDUMP, -1, pipe, -1, -1); +} + +int vi_sdk_set_chn_rotation(int fd, const struct vi_chn_rot_cfg *cfg) +{ + SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_SET_CHN_ROTATION, -1, -1, cfg->ViChn, -1); +} + +int vi_sdk_set_chn_ldc(int fd, const struct vi_chn_ldc_cfg *cfg) +{ + SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_SET_CHN_LDC, -1, -1, cfg->ViChn, -1); +} + +int vi_sdk_attach_vbpool(int fd, const struct vi_vb_pool_cfg *cfg) +{ + SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_ATTACH_VB_POOL, -1, -1, cfg->ViChn, -1); +} + +int vi_sdk_detach_vbpool(int fd, const struct vi_vb_pool_cfg *cfg) +{ + SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_DETACH_VB_POOL, -1, -1, cfg->ViChn, -1); +} diff --git a/middleware/v2/modules/vpu/src/vo_ioctl.c b/middleware/v2/modules/vpu/src/vo_ioctl.c new file mode 100644 index 000000000..1125a1eb8 --- /dev/null +++ b/middleware/v2/modules/vpu/src/vo_ioctl.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include + +#include +#include +#include +#include "vo_ioctl.h" + +#define VO_S_CTRL_VALUE(_fd, _cfg, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = _cfg;\ + if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define VO_S_CTRL_VALUE64(_fd, _cfg, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value64 = _cfg;\ + if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define VO_SDK_CTRL_PTR(_fd, _cfg, _ioctl, _sdk_id)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.sdk_id = _sdk_id;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define VO_S_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_S_CTRL - %s NG,%s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define VO_G_CTRL_VALUE(_fd, _out, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.value = 0;\ + if (ioctl(_fd, VO_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + *_out = ec1.value;\ + return 0;\ + } while (0) + +#define VO_G_CTRL_PTR(_fd, _cfg, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + if (ioctl(_fd, VO_IOC_G_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +#define VO_S_CTRL_ARR(_fd, _cfg, _size, _ioctl)\ + do {\ + struct vo_ext_control ec1;\ + memset(&ec1, 0, sizeof(ec1));\ + ec1.id = _ioctl;\ + ec1.ptr = (void *)_cfg;\ + ec1.size = _size;\ + if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\ + fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\ + return -1;\ + } \ + return 0;\ + } while (0) + +int vo_set_pattern(int fd, enum cvi_vip_pattern pattern) +{ + VO_S_CTRL_VALUE(fd, pattern, VO_IOCTL_PATTERN); +} + +int vo_set_mode(int fd, int mode) +{ + VO_S_CTRL_VALUE(fd, mode, VO_IOCTL_ONLINE); +} + +int vo_set_frame_bgcolor(int fd, void *rgb) +{ + VO_S_CTRL_PTR(fd, rgb, VO_IOCTL_FRAME_BGCOLOR); +} + +int vo_set_window_bgcolor(int fd, void *rgb) +{ + VO_S_CTRL_PTR(fd, rgb, VO_IOCTL_WINDOW_BGCOLOR); +} + +int vo_set_intf(int fd, struct cvi_disp_intf_cfg *cfg) +{ + VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_INTF); +} + +int vo_enable_window_bgcolor(int fd, int enable) +{ + VO_S_CTRL_VALUE(fd, enable, VO_IOCTL_ENABLE_WIN_BGCOLOR); +} + +int vo_set_align(int fd, int align) +{ + VO_S_CTRL_VALUE(fd, align, VO_IOCTL_SET_ALIGN); +} + +int vo_set_rgn(int fd, struct cvi_rgn_cfg *cfg) +{ + VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_SET_RGN); +} + +int vo_set_csc(int fd, struct cvi_csc_cfg *cfg) +{ + VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_SET_CUSTOM_CSC); +} + +int vo_set_clk(int fd, CVI_U32 clk_freq) +{ + VO_S_CTRL_VALUE(fd, clk_freq, VO_IOCTL_SET_CLK); +} + +int vo_set_i80_sw_mode(int fd, CVI_U32 enable) +{ + VO_S_CTRL_VALUE(fd, enable, VO_IOCTL_I80_SW_MODE); +} + +int vo_send_i80_cmd(int fd, CVI_U32 cmd) +{ + VO_S_CTRL_VALUE(fd, cmd, VO_IOCTL_I80_CMD); +} + +int vo_get_videolayer_size(int fd, SIZE_S *vsize) +{ + VO_S_CTRL_PTR(fd, vsize, VO_IOCTL_GET_VLAYER_SIZE); +} + +int vo_get_intf_type(int fd, CVI_S32 *vo_sel) +{ + VO_G_CTRL_PTR(fd, vo_sel, VO_IOCTL_GET_INTF_TYPE); +} + +int vo_get_panel_status(int fd, CVI_U32 *is_init) +{ + VO_G_CTRL_PTR(fd, is_init, VO_IOCTL_GET_PANEL_STATUS); +} + +int vo_set_gamma_ctrl(int fd, VO_GAMMA_INFO_S *gamma_attr) +{ + VO_S_CTRL_PTR(fd, gamma_attr, VO_IOCTL_GAMMA_LUT_UPDATE); +} + +int vo_get_gamma_ctrl(int fd, VO_GAMMA_INFO_S *gamma_attr) +{ + VO_G_CTRL_PTR(fd, gamma_attr, VO_IOCTL_GAMMA_LUT_READ); +} + +int vo_set_tgt_compose(int fd, struct vo_rect *area) +{ + VO_S_CTRL_PTR(fd, area, VO_IOCTL_SEL_TGT_COMPOSE); +} + +int vo_set_tgt_crop(int fd, struct vo_rect *area) +{ + VO_S_CTRL_PTR(fd, area, VO_IOCTL_SEL_TGT_CROP); +} + +int vo_set_dv_timings(int fd, struct vo_dv_timings *timings) +{ + VO_S_CTRL_PTR(fd, timings, VO_IOCTL_SET_DV_TIMINGS); +} + +int vo_get_dv_timings(int fd, struct vo_dv_timings *timings) +{ + VO_G_CTRL_PTR(fd, timings, VO_IOCTL_GET_DV_TIMINGS); +} + +int vo_set_stop_streaming(int fd) +{ + VO_S_CTRL_VALUE(fd, 1, VO_IOCTL_STOP_STREAMING); +} + +int vo_set_start_streaming(int fd) +{ + VO_S_CTRL_VALUE(fd, 1, VO_IOCTL_START_STREAMING); +} + +int vo_enq_buf(int fd, struct vo_buffer *buf) +{ + VO_S_CTRL_PTR(fd, buf, VO_IOCTL_ENQ_BUF); +} + +//vo sdk API list +int vo_sdk_clearchnbuf(int fd, struct vo_clear_chn_buf_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_CLEAR_CHNBUF); +} + +int vo_sdk_send_frame(int fd, struct vo_snd_frm_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SEND_FRAME); +} + +int vo_sdk_get_panelstatue(int fd, struct vo_panel_status_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_PANELSTATUE); + +} + +int vo_sdk_get_pubattr(int fd, struct vo_pub_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_PUBATTR); +} + +int vo_sdk_set_pubattr(int fd, struct vo_pub_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_PUBATTR); +} + +int vo_sdk_suspend(int fd) +{ + VO_SDK_CTRL_PTR(fd, NULL, VO_IOCTL_SDK_CTRL, VO_SDK_SUSPEND); +} + +int vo_sdk_resume(int fd) +{ + VO_SDK_CTRL_PTR(fd, NULL, VO_IOCTL_SDK_CTRL, VO_SDK_RESUME); +} + +int vo_sdk_get_displaybuflen(int fd, struct vo_display_buflen_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_DISPLAYBUFLEN); +} + +int vo_sdk_set_displaybuflen(int fd, struct vo_display_buflen_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_DISPLAYBUFLEN); +} + +int vo_sdk_set_videolayerattr(int fd, struct vo_video_layer_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_VIDEOLAYERATTR); +} + +int vo_sdk_get_videolayerattr(int fd, struct vo_video_layer_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_VIDEOLAYERATTR); +} + +int vo_sdk_enable_videolayer(int fd, struct vo_video_layer_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE_VIDEOLAYER); +} + +int vo_sdk_disable_videolayer(int fd, struct vo_video_layer_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE_VIDEOLAYER); +} + +int vo_sdk_set_chnattr(int fd, struct vo_chn_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_CHNATTR); +} + +int vo_sdk_get_chnattr(int fd, struct vo_chn_attr_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_CHNATTR); +} + +int vo_sdk_set_chnrotation(int fd, struct vo_chn_rotation_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_CHNROTATION); +} + +int vo_sdk_get_chnrotation(int fd, struct vo_chn_rotation_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_CHNROTATION); +} + +int vo_sdk_enable_chn(int fd, struct vo_chn_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE_CHN); +} + +int vo_sdk_disable_chn(int fd, struct vo_chn_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE_CHN); +} + +int vo_sdk_enable(int fd, struct vo_dev_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE); +} + +int vo_sdk_disable(int fd, struct vo_dev_cfg *cfg) +{ + VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE); +} + diff --git a/middleware/v2/modules/vpu/src/vpss_ioctl.c b/middleware/v2/modules/vpu/src/vpss_ioctl.c new file mode 100644 index 000000000..2416ade4f --- /dev/null +++ b/middleware/v2/modules/vpu/src/vpss_ioctl.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include + +#include "vpss_ioctl.h" + +CVI_S32 vpss_send_frame(CVI_S32 fd, struct vpss_snd_frm_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SEND_FRAME, cfg); +} + +CVI_S32 vpss_send_chn_frame(CVI_S32 fd, struct vpss_chn_frm_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SEND_CHN_FRAME, cfg); +} + +CVI_S32 vpss_release_chn_frame(CVI_S32 fd, const struct vpss_chn_frm_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_RELEASE_CHN_FRAME, cfg); +} + +CVI_S32 vpss_create_grp(CVI_S32 fd, struct vpss_crt_grp_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_CREATE_GROUP, cfg); +} + +CVI_S32 vpss_destroy_grp(CVI_S32 fd, VPSS_GRP VpssGrp) +{ + return ioctl(fd, CVI_VPSS_DESTROY_GROUP, &VpssGrp); +} + +CVI_S32 vpss_get_available_grp(CVI_S32 fd, VPSS_GRP *pVpssGrp) +{ + return ioctl(fd, CVI_VPSS_GET_AVAIL_GROUP, pVpssGrp); +} + +CVI_S32 vpss_start_grp(CVI_S32 fd, struct vpss_str_grp_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_START_GROUP, cfg); +} + +CVI_S32 vpss_stop_grp(CVI_S32 fd, VPSS_GRP VpssGrp) +{ + return ioctl(fd, CVI_VPSS_STOP_GROUP, &VpssGrp); +} + +CVI_S32 vpss_reset_grp(CVI_S32 fd, VPSS_GRP VpssGrp) +{ + return ioctl(fd, CVI_VPSS_RESET_GROUP, &VpssGrp); +} + +CVI_S32 vpss_set_grp_attr(CVI_S32 fd, const struct vpss_grp_attr *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_GRP_ATTR, cfg); +} + +CVI_S32 vpss_get_grp_attr(CVI_S32 fd, struct vpss_grp_attr *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_GRP_ATTR, cfg); +} + +CVI_S32 vpss_set_grp_crop(CVI_S32 fd, const struct vpss_grp_crop_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_GRP_CROP, cfg); +} + +CVI_S32 vpss_get_grp_crop(CVI_S32 fd, struct vpss_grp_crop_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_GRP_CROP, cfg); +} + +CVI_VOID _vpss_pack_fixed_point_norm(VPSS_NORMALIZE_S *pstNormalize) +{ + CVI_U16 sc_frac[3]; + CVI_U8 sub[3]; + CVI_U16 sub_frac[3]; + CVI_DOUBLE sub_int; + VPSS_NORMALIZE_S stNormalize; + struct vpss_int_normalize *int_norm; + + if (!pstNormalize->bEnable) + return; + + memcpy(&stNormalize, pstNormalize, sizeof(stNormalize)); + + for (CVI_U8 i = 0; i < 3; ++i) { + sc_frac[i] = pstNormalize->factor[i] * 8192; + sub_frac[i] + = modf(pstNormalize->mean[i], &sub_int) * 1024; + sub[i] = sub_int; + } + + int_norm = (struct vpss_int_normalize *)pstNormalize; + int_norm->enable = 1; + int_norm->rounding = pstNormalize->rounding; + + for (CVI_U8 i = 0; i < 3; ++i) { + int_norm->sc_frac[i] = sc_frac[i]; + int_norm->sub[i] = sub[i]; + int_norm->sub_frac[i] = sub_frac[i]; + } +} + +CVI_S32 vpss_set_chn_attr(CVI_S32 fd, struct vpss_chn_attr *attr) +{ + if (sizeof(struct vpss_int_normalize) > sizeof(VPSS_NORMALIZE_S)) { + fprintf(stderr, "Kernel cannnot use float\n"); + return CVI_FAILURE; + } + + _vpss_pack_fixed_point_norm(&attr->stChnAttr.stNormalize); + + return ioctl(fd, CVI_VPSS_SET_CHN_ATTR, attr); +} + +CVI_S32 vpss_get_chn_attr(CVI_S32 fd, struct vpss_chn_attr *attr) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_ATTR, attr); +} + +CVI_S32 vpss_show_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SHOW_CHN, cfg); +} + +CVI_S32 vpss_hide_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_HIDE_CHN, cfg); +} + +CVI_S32 vpss_enable_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_ENABLE_CHN, cfg); +} + +CVI_S32 vpss_disable_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_DISABLE_CHN, cfg); +} + +CVI_S32 vpss_get_chn_frame(CVI_S32 fd, struct vpss_chn_frm_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_FRAME, cfg); +} + +CVI_S32 vpss_set_chn_wrap(CVI_S32 fd, const struct vpss_chn_wrap_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_BUF_WRAP, cfg); +} + +CVI_S32 vpss_get_chn_wrap(CVI_S32 fd, struct vpss_chn_wrap_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_BUF_WRAP, cfg); +} + +CVI_S32 vpss_set_chn_rotation(CVI_S32 fd, const struct vpss_chn_rot_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_ROTATION, cfg); +} + +CVI_S32 vpss_get_chn_rotation(CVI_S32 fd, struct vpss_chn_rot_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_ROTATION, cfg); +} + +CVI_S32 vpss_set_chn_align(CVI_S32 fd, const struct vpss_chn_align_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_ALIGN, cfg); +} + +CVI_S32 vpss_get_chn_align(CVI_S32 fd, struct vpss_chn_align_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_ALIGN, cfg); +} + +CVI_S32 vpss_set_chn_ldc(CVI_S32 fd, const struct vpss_chn_ldc_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_LDC, cfg); +} + +CVI_S32 vpss_get_chn_ldc(CVI_S32 fd, struct vpss_chn_ldc_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_LDC, cfg); +} + +CVI_S32 vpss_set_chn_crop(CVI_S32 fd, const struct vpss_chn_crop_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_CROP, cfg); +} + +CVI_S32 vpss_get_chn_crop(CVI_S32 fd, struct vpss_chn_crop_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_CROP, cfg); +} + +CVI_S32 vpss_set_coef_level(CVI_S32 fd, const struct vpss_chn_coef_level_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_SCALE_COEFF_LEVEL, cfg); +} + +CVI_S32 vpss_get_coef_level(CVI_S32 fd, struct vpss_chn_coef_level_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_SCALE_COEFF_LEVEL, cfg); +} + +CVI_S32 vpss_set_chn_yratio(CVI_S32 fd, const struct vpss_chn_yratio_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_CHN_YRATIO, cfg); +} + +CVI_S32 vpss_get_chn_yratio(CVI_S32 fd, struct vpss_chn_yratio_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_CHN_YRATIO, cfg); +} + +CVI_S32 vpss_set_grp_csc(CVI_S32 fd, const struct vpss_grp_csc_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_SET_GRP_CSC_CFG, cfg); +} + +CVI_S32 vpss_attach_vbpool(CVI_S32 fd, const struct vpss_vb_pool_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_ATTACH_VB_POOL, cfg); +} + +CVI_S32 vpss_detach_vbpool(CVI_S32 fd, const struct vpss_vb_pool_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_DETACH_VB_POOL, cfg); +} + +CVI_S32 vpss_trigger_snap_frame(CVI_S32 fd, struct vpss_snap_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_TRIGGER_SNAP_FRAME, cfg); +} + +CVI_S32 vpss_get_proc_amp_ctrl(CVI_S32 fd, struct vpss_proc_amp_ctrl_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_AMP_CTRL, cfg); +} + +CVI_S32 vpss_get_proc_amp(CVI_S32 fd, struct vpss_proc_amp_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_AMP_CFG, cfg); +} + +CVI_S32 vpss_get_all_proc_amp(CVI_S32 fd, struct vpss_all_proc_amp_cfg *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_ALL_AMP, cfg); +} + +CVI_S32 vpss_get_binscene(CVI_S32 fd, struct vpss_scene *cfg) +{ + return ioctl(fd, CVI_VPSS_GET_SCENE, cfg); +} + +