diff --git a/arch/arm/include/cxd56xx/cisif.h b/arch/arm/include/cxd56xx/cisif.h index b42fcb73a1..9e600681de 100644 --- a/arch/arm/include/cxd56xx/cisif.h +++ b/arch/arm/include/cxd56xx/cisif.h @@ -21,54 +21,6 @@ #ifndef __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H #define __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H -/**************************************************************************** - * Public Types - ****************************************************************************/ - -typedef void (*notify_callback_t)(uint8_t code, - uint32_t size, - uint32_t addr); -typedef void (*comp_callback_t)(uint8_t code, - uint32_t size, - uint32_t addr); - -struct cisif_init_yuv_param_s -{ - uint16_t hsize; - uint16_t vsize; - uint32_t notify_size; - notify_callback_t notify_func; -}; - -typedef struct cisif_init_yuv_param_s cisif_init_yuv_param_t; - -struct cisif_init_jpeg_param_s -{ - uint32_t notify_size; - notify_callback_t notify_func; -}; - -typedef struct cisif_init_jpeg_param_s cisif_init_jpeg_param_t; - -struct cisif_sarea_s -{ - uint8_t *strg_addr; - uint32_t strg_size; -}; - -typedef struct cisif_sarea_s cisif_sarea_t; - -struct cisif_param_s -{ - uint32_t format; - cisif_init_yuv_param_t yuv_param; - cisif_init_jpeg_param_t jpg_param; - cisif_sarea_t sarea; - comp_callback_t comp_func; -}; - -typedef struct cisif_param_s cisif_param_t; - #ifndef __ASSEMBLY__ #undef EXTERN @@ -84,11 +36,7 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -int cxd56_cisifinit(void); -int cxd56_cisiffinalize(void); -int cxd56_cisifstartcapture(cisif_param_t *param, cisif_sarea_t *sarea); -int cxd56_cisifstopcapture(void); -int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea); +int cxd56_cisif_initialize(void); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/arm/src/cxd56xx/cxd56_cisif.c b/arch/arm/src/cxd56xx/cxd56_cisif.c index 1e0951991f..b3f8cbd83b 100644 --- a/arch/arm/src/cxd56xx/cxd56_cisif.c +++ b/arch/arm/src/cxd56xx/cxd56_cisif.c @@ -35,8 +35,7 @@ #include #include -#include - +#include #include "arm_arch.h" #include "cxd56_clock.h" @@ -52,10 +51,22 @@ /* #define CISIF_DBG_CONTI_CAP */ -#define YUV_VSIZE_MIN (64) -#define YUV_HSIZE_MIN (96) -#define YUV_VSIZE_MAX (360) -#define YUV_HSIZE_MAX (480) +#define YUV_VSIZE_STEP (1) +#define YUV_HSIZE_STEP (1) +#define YUV_VSIZE_MIN (64) +#define YUV_HSIZE_MIN (96) +#define YUV_VSIZE_MAX (360) +#define YUV_HSIZE_MAX (480) + +#define JPG_VSIZE_STEP (1) +#define JPG_HSIZE_STEP (1) +#define JPG_VSIZE_MIN (64) +#define JPG_HSIZE_MIN (96) +#define JPG_VSIZE_MAX (1944) +#define JPG_HSIZE_MAX (2592) + +#define CISIF_FMT_MIN (1) +#define CISIF_FMT_MAX (3) #define JPG_INT_ALL (JPG_ERR_STATUS_INT | \ JPG_MEM_OVF_INT | \ @@ -108,6 +119,40 @@ typedef enum state_e state_t; typedef void (*intc_func_table)(uint8_t code); +typedef void (*notify_callback_t)(uint8_t code, + uint32_t size, + uint32_t addr); +typedef void (*comp_callback_t)(uint8_t code, + uint32_t size, + uint32_t addr); + +struct cisif_yuv_param_s +{ + uint16_t hsize; + uint16_t vsize; + uint32_t notify_size; + notify_callback_t notify_func; +}; + +typedef struct cisif_yuv_param_s cisif_yuv_param_t; + +struct cisif_jpg_param_s +{ + uint32_t notify_size; + notify_callback_t notify_func; +}; + +typedef struct cisif_jpg_param_s cisif_jpg_param_t; + +struct cisif_param_s +{ + uint32_t format; + cisif_yuv_param_t yuv_param; + cisif_jpg_param_t jpg_param; +}; + +typedef struct cisif_param_s cisif_param_t; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -115,9 +160,8 @@ typedef void (*intc_func_table)(uint8_t code); static state_t g_state = STATE_STANDBY; static uint32_t g_storage_addr = 0; -notify_callback_t g_jpg_notify_callback_func; -notify_callback_t g_ycc_notify_callback_func; -comp_callback_t g_comp_callback_func; +static notify_callback_t g_jpg_notify_callback_func; +static notify_callback_t g_ycc_notify_callback_func; static bool g_jpgint_receive; static bool g_errint_receive; @@ -129,6 +173,8 @@ static uint32_t g_cisif_time_start; static uint32_t g_cisif_time_stop; #endif +static imgdata_capture_t g_cxd56_cisif_complete_capture; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -145,15 +191,32 @@ static void cisif_reg_write(uint16_t reg, uint32_t val); static uint32_t cisif_reg_read(uint16_t reg); static int cisif_check_param(cisif_param_t *p); -static int cisif_set_yuv_param(cisif_param_t *p); -static int cisif_set_jpg_param(cisif_param_t *p); +static int cisif_set_yuv_param(cisif_yuv_param_t *p); +static int cisif_set_jpg_param(cisif_jpg_param_t *p); -static int cisif_check_sarea(void *s); -static int cisif_set_yuv_sarea(void *s); -static int cisif_set_jpg_sarea(void *s); -static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size); +static int cisif_set_yuv_sarea(uint8_t *addr, uint32_t size); +static int cisif_set_jpg_sarea(uint8_t *addr, uint32_t size); +static int cisif_set_intlev_sarea(uint8_t *addr, + uint32_t total_size, + uint32_t yuv_size); +static int cisif_intc_handler(int irq, FAR void *context, FAR void *arg); -int cisif_intc_handler(int irq, FAR void *context, FAR void *arg); +/* video image data operations */ + +static int cxd56_cisif_init(void); +static int cxd56_cisif_uninit(void); +static int cxd56_cisif_validate_frame_setting + (uint8_t nr_datafmt, + FAR imgdata_format_t *datafmt, + FAR imgdata_interval_t *interval); +static int cxd56_cisif_start_capture + (uint8_t nr_datafmt, + FAR imgdata_format_t *datafmt, + FAR imgdata_interval_t *interval, + imgdata_capture_t callback); +static int cxd56_cisif_stop_capture(void); +static int cxd56_cisif_validate_buf(uint8_t *addr, uint32_t size); +static int cxd56_cisif_set_buf(uint8_t *addr, uint32_t size); const intc_func_table g_intcomp_func[] = { @@ -188,6 +251,17 @@ const intc_func_table g_intcomp_func[] = cisif_jpg_err_int, /* JPG_ERR_STATUS_INT */ }; +const struct imgdata_ops_s g_cxd56_cisif_ops = + { + .init = cxd56_cisif_init, + .uninit = cxd56_cisif_uninit, + .validate_buf = cxd56_cisif_validate_buf, + .set_buf = cxd56_cisif_set_buf, + .validate_frame_setting = cxd56_cisif_validate_frame_setting, + .start_capture = cxd56_cisif_start_capture, + .stop_capture = cxd56_cisif_stop_capture, + }; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -290,7 +364,7 @@ static void cisif_callback_for_intlev(uint8_t code) /* Notify and get next addr */ - g_comp_callback_func(0, size, g_storage_addr); + g_cxd56_cisif_complete_capture(0, size); g_jpgint_receive = false; @@ -332,7 +406,7 @@ static void cisif_ycc_axi_trdn_int(uint8_t code) else { size = cisif_reg_read(CISIF_YCC_DSTRG_CONT); - g_comp_callback_func(0, size, g_storage_addr); + g_cxd56_cisif_complete_capture(0, size); cisif_reg_write(CISIF_YCC_DREAD_CONT, 0); } } @@ -382,7 +456,7 @@ static void cisif_jpg_axi_trdn_int(uint8_t code) else { size = cisif_reg_read(CISIF_JPG_DSTRG_CONT); - g_comp_callback_func(0, size, g_storage_addr); + g_cxd56_cisif_complete_capture(0, size); cisif_reg_write(CISIF_JPG_DREAD_CONT, 0); } } @@ -414,7 +488,7 @@ static void cisif_ycc_err_int(uint8_t code) #endif size = cisif_reg_read(CISIF_YCC_DSTRG_CONT); - g_comp_callback_func(code, size, g_storage_addr); + g_cxd56_cisif_complete_capture(code, size); cisif_reg_write(CISIF_YCC_DREAD_CONT, 0); g_errint_receive = true; } @@ -426,16 +500,13 @@ static void cisif_ycc_err_int(uint8_t code) static void cisif_jpg_err_int(uint8_t code) { uint32_t size; - uint32_t addr; #ifdef CISIF_INTR_TRACE cisif_trace_time_stop("cisif_jpg_err_int"); #endif - addr = g_storage_addr; - size = cisif_reg_read(CISIF_JPG_DSTRG_CONT); - g_comp_callback_func(code, size, addr); + g_cxd56_cisif_complete_capture(code, size); cisif_reg_write(CISIF_JPG_DREAD_CONT, 0); g_errint_receive = true; } @@ -444,7 +515,7 @@ static void cisif_jpg_err_int(uint8_t code) * cisif_intc_handler ****************************************************************************/ -int cisif_intc_handler(int irq, FAR void *context, FAR void *arg) +static int cisif_intc_handler(int irq, FAR void *context, FAR void *arg) { uint32_t value; uint32_t enable; @@ -488,6 +559,19 @@ static uint32_t cisif_reg_read(uint16_t reg) return getreg32(CXD56_CISIF_BASE + reg); } +static bool is_uncompressed(uint32_t fmt) +{ + bool ret = false; + + if ((fmt == IMGDATA_PIX_FMT_UYVY) || + (fmt == IMGDATA_PIX_FMT_RGB565)) + { + ret = true; + } + + return ret; +} + /**************************************************************************** * cisif_check_param ****************************************************************************/ @@ -499,23 +583,19 @@ static int cisif_check_param(cisif_param_t *p) return -EINVAL; } - if (p->comp_func == NULL) - { - return -EINVAL; - } - switch (p->format) { - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_JPEG: - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: + case IMGDATA_PIX_FMT_UYVY: + case IMGDATA_PIX_FMT_RGB565: + case IMGDATA_PIX_FMT_JPEG: + case IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG: break; default: return -EINVAL; } - if (p->format != V4L2_PIX_FMT_JPEG) + if (p->format != IMGDATA_PIX_FMT_JPEG) { if (p->yuv_param.hsize < YUV_HSIZE_MIN || p->yuv_param.hsize > YUV_HSIZE_MAX || @@ -534,7 +614,7 @@ static int cisif_check_param(cisif_param_t *p) } } - if (p->format != V4L2_PIX_FMT_UYVY) + if (!is_uncompressed(p->format)) { if (p->jpg_param.notify_func != NULL) { @@ -548,47 +628,26 @@ static int cisif_check_param(cisif_param_t *p) return OK; } -/**************************************************************************** - * cisif_check_sarea - ****************************************************************************/ - -static int cisif_check_sarea(void *s) -{ - if (s == NULL) - { - return -EINVAL; - } - - cisif_sarea_t *ss = (cisif_sarea_t *)s; - if (ILLEGAL_BUFADDR_ALIGNMENT(ss->strg_addr) || - ss->strg_size == 0) - { - return -EINVAL; - } - - return OK; -} - /**************************************************************************** * cisif_set_yuvparam ****************************************************************************/ -static int cisif_set_yuv_param(cisif_param_t *p) +static int cisif_set_yuv_param(cisif_yuv_param_t *p) { uint32_t act_size = 0; - act_size = (p->yuv_param.vsize & 0x1ff) << 16; - act_size |= p->yuv_param.hsize & 0x1ff; + act_size = (p->vsize & 0x1ff) << 16; + act_size |= p->hsize & 0x1ff; cisif_reg_write(CISIF_ACT_SIZE, act_size); cisif_reg_write(CISIF_CIS_SIZE, act_size); /* must align 32 bytes */ - cisif_reg_write(CISIF_YCC_NSTRG_SIZE, (p->yuv_param.notify_size - & 0xffffffe0)); + cisif_reg_write(CISIF_YCC_NSTRG_SIZE, + (p->notify_size & 0xffffffe0)); - g_ycc_notify_callback_func = p->yuv_param.notify_func; + g_ycc_notify_callback_func = p->notify_func; return OK; } @@ -597,14 +656,12 @@ static int cisif_set_yuv_param(cisif_param_t *p) * cisif_set_yuvsarea ****************************************************************************/ -static int cisif_set_yuv_sarea(void *s) +static int cisif_set_yuv_sarea(uint8_t *addr, uint32_t size) { - cisif_sarea_t *ss = (cisif_sarea_t *)s; - /* must align 32 bytes */ - cisif_reg_write(CISIF_YCC_DAREA_SIZE, (ss->strg_size & 0xffffffe0)); - cisif_reg_write(CISIF_YCC_START_ADDR, CXD56_PHYSADDR(ss->strg_addr)); + cisif_reg_write(CISIF_YCC_DAREA_SIZE, (size & 0xffffffe0)); + cisif_reg_write(CISIF_YCC_START_ADDR, CXD56_PHYSADDR(addr)); return OK; } @@ -613,14 +670,14 @@ static int cisif_set_yuv_sarea(void *s) * cisif_set_jpg_param ****************************************************************************/ -static int cisif_set_jpg_param(cisif_param_t *p) +static int cisif_set_jpg_param(cisif_jpg_param_t *p) { /* must align 32 bytes */ - cisif_reg_write(CISIF_JPG_NSTRG_SIZE, (p->jpg_param.notify_size + cisif_reg_write(CISIF_JPG_NSTRG_SIZE, (p->notify_size & 0xffffffe0)); - g_jpg_notify_callback_func = p->jpg_param.notify_func; + g_jpg_notify_callback_func = p->notify_func; return OK; } @@ -629,14 +686,12 @@ static int cisif_set_jpg_param(cisif_param_t *p) * cisif_set_jpg_sarea ****************************************************************************/ -static int cisif_set_jpg_sarea(void *s) +static int cisif_set_jpg_sarea(uint8_t *addr, uint32_t size) { - cisif_sarea_t *ss = (cisif_sarea_t *)s; - /* must align 32 bytes */ - cisif_reg_write(CISIF_JPG_DAREA_SIZE, (ss->strg_size & 0xffffffe0)); - cisif_reg_write(CISIF_JPG_START_ADDR, CXD56_PHYSADDR(ss->strg_addr)); + cisif_reg_write(CISIF_JPG_DAREA_SIZE, (size & 0xffffffe0)); + cisif_reg_write(CISIF_JPG_START_ADDR, CXD56_PHYSADDR(addr)); return OK; } @@ -645,41 +700,73 @@ static int cisif_set_jpg_sarea(void *s) * cisif_set_jpg_sarea ****************************************************************************/ -static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size) +static int cisif_set_intlev_sarea(uint8_t *addr, + uint32_t total_size, + uint32_t yuv_size) { - cisif_sarea_t *sarea = (cisif_sarea_t *)s; - cisif_sarea_t sarea_int; - - if (sarea->strg_size < yuv_size) + if (total_size < yuv_size) { return -EINVAL; } /* Set for YUV */ - sarea_int.strg_addr = sarea->strg_addr; - sarea_int.strg_size = yuv_size; - cisif_set_yuv_sarea(&sarea_int); + cisif_set_yuv_sarea(addr, yuv_size); /* Set for JPEG */ - sarea_int.strg_addr = sarea->strg_addr + yuv_size; - sarea_int.strg_size = sarea->strg_size - yuv_size; - - cisif_set_jpg_sarea(&sarea_int); + cisif_set_jpg_sarea(addr + yuv_size, total_size - yuv_size); return OK; } /**************************************************************************** - * Public Functions + * cisif_chk_jpgfrmsize ****************************************************************************/ +static int cisif_chk_jpgfrmsize(int w, int h) +{ + if ((w < JPG_HSIZE_MIN) || + (w > JPG_HSIZE_MAX)) + { + return -EINVAL; + } + + if ((h < JPG_VSIZE_MIN) || + (h > JPG_VSIZE_MAX)) + { + return -EINVAL; + } + + return OK; +} + /**************************************************************************** - * cxd56_cisifinit + * cisif_chk_yuvfrmsize ****************************************************************************/ -int cxd56_cisifinit(void) +static int cisif_chk_yuvfrmsize(int w, int h) +{ + if ((w < YUV_HSIZE_MIN) || + (w > YUV_HSIZE_MAX)) + { + return -EINVAL; + } + + if ((h < YUV_VSIZE_MIN) || + (h > YUV_VSIZE_MAX)) + { + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * cxd56_cisif_init + ****************************************************************************/ + +static int cxd56_cisif_init(void) { if (g_state != STATE_STANDBY) { @@ -708,15 +795,14 @@ int cxd56_cisifinit(void) #endif g_state = STATE_READY; - return OK; } /**************************************************************************** - * cxd56_cisiffinalize + * cxd56_cisif_uninit ****************************************************************************/ -int cxd56_cisiffinalize(void) +static int cxd56_cisif_uninit(void) { if (g_state != STATE_READY) { @@ -741,19 +827,28 @@ int cxd56_cisiffinalize(void) cxd56_img_cisif_clock_disable(); g_state = STATE_STANDBY; - return OK; } /**************************************************************************** - * cxd56_cisifstartcapturing + * cxd56_cisif_start_capture ****************************************************************************/ -int cxd56_cisifstartcapture( - cisif_param_t *param, - cisif_sarea_t *sarea) +static int cxd56_cisif_start_capture + (uint8_t nr_fmt, + FAR imgdata_format_t *fmt, + FAR imgdata_interval_t *interval, + imgdata_capture_t callback) { - uint32_t cisif_mode; + cisif_param_t param = + { + 0 + }; + + cisif_yuv_param_t *yuv = ¶m.yuv_param; + cisif_jpg_param_t *jpg = ¶m.jpg_param; + + uint32_t mode; uint32_t interrupts = VS_INT; int ret; @@ -762,7 +857,22 @@ int cxd56_cisifstartcapture( return -EPERM; } - ret = cisif_check_param(param); + param.format = fmt[IMGDATA_FMT_MAIN].pixelformat; + if (param.format != IMGDATA_PIX_FMT_JPEG) + { + if (is_uncompressed(param.format)) + { + yuv->hsize = fmt[IMGDATA_FMT_MAIN].width; + yuv->vsize = fmt[IMGDATA_FMT_MAIN].height; + } + else + { + yuv->hsize = fmt[IMGDATA_FMT_SUB].width; + yuv->vsize = fmt[IMGDATA_FMT_SUB].height; + } + } + + ret = cisif_check_param(¶m); if (ret != OK) { return ret; @@ -770,39 +880,29 @@ int cxd56_cisifstartcapture( cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT); - ret = cisif_check_sarea(sarea); - if (ret != OK) + switch (param.format) { - return ret; - } + case IMGDATA_PIX_FMT_UYVY: + case IMGDATA_PIX_FMT_RGB565: - switch (param->format) - { - case V4L2_PIX_FMT_UYVY: - cisif_set_yuv_param(param); - cisif_set_yuv_sarea(sarea); + cisif_set_yuv_param(yuv); - cisif_mode = MODE_YUV_TRS_EN; + mode = MODE_YUV_TRS_EN; interrupts |= YCC_INT_ALL; break; - case V4L2_PIX_FMT_JPEG: - cisif_set_jpg_param(param); - cisif_set_jpg_sarea(sarea); + case IMGDATA_PIX_FMT_JPEG: + cisif_set_jpg_param(jpg); - cisif_mode = MODE_JPG_TRS_EN; + mode = MODE_JPG_TRS_EN; interrupts |= JPG_INT_ALL; break; - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: - cisif_set_yuv_param(param); - cisif_set_jpg_param(param); + case IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG: + cisif_set_yuv_param(yuv); + cisif_set_jpg_param(jpg); - cisif_set_intlev_sarea(sarea, - YUV_SIZE(param->yuv_param.vsize, - param->yuv_param.hsize)); - - cisif_mode = MODE_INTLEV_TRS_EN; + mode = MODE_INTLEV_TRS_EN; interrupts |= YCC_INT_ALL | JPG_INT_ALL; g_jpgint_receive = false; break; @@ -811,8 +911,7 @@ int cxd56_cisifstartcapture( return -EINVAL; } - g_comp_callback_func = param->comp_func; - g_storage_addr = (uint32_t)sarea->strg_addr; + g_cxd56_cisif_complete_capture = callback; g_state = STATE_CAPTURE; @@ -826,17 +925,16 @@ int cxd56_cisifstartcapture( interrupts |= JPG_NSTORAGE_INT; } - cisif_reg_write(CISIF_MODE, cisif_mode); + cisif_reg_write(CISIF_MODE, mode); cisif_reg_write(CISIF_INTR_CLEAR, interrupts); cisif_reg_write(CISIF_INTR_ENABLE, interrupts); cisif_reg_write(CISIF_DIN_ENABLE, 1); - cisif_reg_write(CISIF_EXE_CMD, 1); return OK; } -int cxd56_cisifstopcapture(void) +static int cxd56_cisif_stop_capture(void) { g_state = STATE_READY; cisif_reg_write(CISIF_DIN_ENABLE, 0); @@ -846,42 +944,54 @@ int cxd56_cisifstopcapture(void) return OK; } -int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) +static int cxd56_cisif_validate_buf(uint8_t *addr, uint32_t size) +{ + if (ILLEGAL_BUFADDR_ALIGNMENT(addr) || + size == 0) + { + return -EINVAL; + } + + return OK; +} + +static int cxd56_cisif_set_buf(uint8_t *addr, uint32_t size) { int ret; - uint32_t cisif_mode; - uint32_t yuv_regsize; - uint32_t yuv_hsize; - uint32_t yuv_vsize; + uint32_t mode; + uint32_t regval; + uint16_t w; + uint16_t h; - ret = cisif_check_sarea(sarea); + ret = cxd56_cisif_validate_buf(addr, size); if (ret != OK) { return ret; } - cisif_mode = cisif_reg_read(CISIF_MODE); + mode = cisif_reg_read(CISIF_MODE); - switch (cisif_mode) + switch (mode) { case MODE_YUV_TRS_EN: - ret = cisif_set_yuv_sarea(sarea); + ret = cisif_set_yuv_sarea(addr, size); break; case MODE_JPG_TRS_EN: - ret = cisif_set_jpg_sarea(sarea); + ret = cisif_set_jpg_sarea(addr, size); break; default: /* MODE_INTLEV_TRS_EN */ /* Get YUV frame size information */ - yuv_regsize = cisif_reg_read(CISIF_ACT_SIZE); - yuv_vsize = (yuv_regsize >> 16) & 0x1ff; - yuv_hsize = yuv_regsize & 0x01ff; + regval = cisif_reg_read(CISIF_ACT_SIZE); + h = (regval >> 16) & 0x1ff; + w = regval & 0x01ff; - ret = cisif_set_intlev_sarea(sarea, - YUV_SIZE(yuv_vsize, yuv_hsize)); + ret = cisif_set_intlev_sarea(addr, + size, + YUV_SIZE(w, h)); break; } @@ -891,7 +1001,83 @@ int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) } cisif_reg_write(CISIF_EXE_CMD, 1); - g_storage_addr = (uint32_t)sarea->strg_addr; + g_storage_addr = (uint32_t)addr; return ret; } + +static int cxd56_cisif_validate_frame_setting + (uint8_t nr_datafmt, + FAR imgdata_format_t *datafmt, + FAR imgdata_interval_t *interval) +{ + int ret = OK; + + if ((nr_datafmt < CISIF_FMT_MIN) || (nr_datafmt > CISIF_FMT_MAX)) + { + return -EINVAL; + } + + switch (datafmt[IMGDATA_FMT_MAIN].pixelformat) + { + case IMGDATA_PIX_FMT_UYVY: /* YUV 4:2:2 */ + case IMGDATA_PIX_FMT_RGB565: /* RGB565 */ + + ret = cisif_chk_yuvfrmsize(datafmt[IMGDATA_FMT_MAIN].width, + datafmt[IMGDATA_FMT_MAIN].height); + break; + + case IMGDATA_PIX_FMT_JPEG: /* JPEG */ + + ret = cisif_chk_jpgfrmsize(datafmt[IMGDATA_FMT_MAIN].width, + datafmt[IMGDATA_FMT_MAIN].height); + break; + + case IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + YUV 4:2:2 */ + + if ((nr_datafmt == 2) && + !is_uncompressed(datafmt[IMGDATA_FMT_SUB].pixelformat)) + { + /* Unsupported pixel format */ + + return -EINVAL; + } + + ret = cisif_chk_jpgfrmsize(datafmt[IMGDATA_FMT_MAIN].width, + datafmt[IMGDATA_FMT_MAIN].height); + if (ret != OK) + { + return ret; + } + + if (nr_datafmt == 2) + { + ret = cisif_chk_yuvfrmsize + (datafmt[IMGDATA_FMT_SUB].width, + datafmt[IMGDATA_FMT_SUB].height); + } + + break; + + default: /* Unsupported pixel format */ + + return -EINVAL; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * cxd56_cisif_initialize + ****************************************************************************/ + +int cxd56_cisif_initialize(void) +{ + imgdata_register(&g_cxd56_cisif_ops); + return OK; +} + diff --git a/boards/arm/cxd56xx/common/src/cxd56_isx012.c b/boards/arm/cxd56xx/common/src/cxd56_isx012.c index a36d9bc28c..f8f5f7c0e5 100644 --- a/boards/arm/cxd56xx/common/src/cxd56_isx012.c +++ b/boards/arm/cxd56xx/common/src/cxd56_isx012.c @@ -184,10 +184,10 @@ int board_isx012_initialize(int i2c_bus_num) return -ENODEV; } - ret = isx012_register(i2c); + ret = isx012_initialize(i2c); if (ret < 0) { - _err("Error registering ISX012.\n"); + _err("Failed to initialize ISX012.\n"); } return ret; @@ -201,10 +201,10 @@ int board_isx012_uninitialize(void) /* Initialize i2c device */ - ret = isx012_unregister(); + ret = isx012_uninitialize(); if (ret < 0) { - _err("Error unregistering ISX012.\n"); + _err("Failed to uninitialize ISX012.\n"); } if (!i2c) diff --git a/boards/arm/cxd56xx/drivers/Kconfig b/boards/arm/cxd56xx/drivers/Kconfig index 0c9ede0472..d336be8102 100644 --- a/boards/arm/cxd56xx/drivers/Kconfig +++ b/boards/arm/cxd56xx/drivers/Kconfig @@ -6,5 +6,4 @@ if SPECIFIC_DRIVERS source "drivers/platform/audio/Kconfig" source "drivers/platform/sensors/Kconfig" -source "drivers/platform/camera/Kconfig" endif diff --git a/boards/arm/cxd56xx/drivers/Make.defs b/boards/arm/cxd56xx/drivers/Make.defs index 16578f9850..39073bd44b 100644 --- a/boards/arm/cxd56xx/drivers/Make.defs +++ b/boards/arm/cxd56xx/drivers/Make.defs @@ -20,4 +20,3 @@ include platform/audio/Make.defs include platform/sensors/Make.defs -include platform/camera/Make.defs diff --git a/boards/arm/cxd56xx/drivers/camera/Kconfig b/boards/arm/cxd56xx/drivers/camera/Kconfig deleted file mode 100644 index fc563dfd50..0000000000 --- a/boards/arm/cxd56xx/drivers/camera/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see the file kconfig-language.txt in the NuttX tools repository. -# - -config VIDEO_ISX012 - bool "ISX012 Image sensor" - default n - select I2C diff --git a/boards/arm/cxd56xx/drivers/camera/Make.defs b/boards/arm/cxd56xx/drivers/camera/Make.defs deleted file mode 100644 index 637f196bcc..0000000000 --- a/boards/arm/cxd56xx/drivers/camera/Make.defs +++ /dev/null @@ -1,27 +0,0 @@ -############################################################################ -# boards/arm/cxd56xx/drivers/camera/Make.defs -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. The -# ASF licenses this file to you 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. -# -############################################################################ - -ifeq ($(CONFIG_VIDEO_ISX012),y) - CSRCS += isx012.c -endif - -DEPPATH += --dep-path platform$(DELIM)camera -VPATH += :platform$(DELIM)camera -CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)platform$(DELIM)camera) diff --git a/boards/arm/cxd56xx/drivers/camera/isx012.c b/boards/arm/cxd56xx/drivers/camera/isx012.c deleted file mode 100644 index bbda6d3cf8..0000000000 --- a/boards/arm/cxd56xx/drivers/camera/isx012.c +++ /dev/null @@ -1,3869 +0,0 @@ -/**************************************************************************** - * boards/arm/cxd56xx/drivers/camera/isx012.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* The following macro is enabled because - * it is to make stable startup. (other case) - */ - -/* #define ISX012_NOT_USE_NSTBY */ - -/* The following macro is disabled because it is to see detailed control. */ - -/* #define ISX012_CHECK_IN_DETAIL */ - -/* Skip invalid frame because it occurs first due to the spec of isx012. */ - -#define ISX012_FRAME_SKIP_EN - -#define OUT_HSIZE_QVGA (320) -#define OUT_VSIZE_QVGA (240) -#define OUT_HSIZE_VGA (640) -#define OUT_VSIZE_VGA (480) -#define OUT_HSIZE_HD (1280) -#define OUT_VSIZE_HD (720) -#define OUT_HSIZE_QUADVGA (1280) -#define OUT_VSIZE_QUADVGA (960) -#define OUT_HSIZE_FULLHD (1920) -#define OUT_VSIZE_FULLHD (1080) -#define OUT_HSIZE_3M (2048) -#define OUT_VSIZE_3M (1536) -#define OUT_HSIZE_5M (2560) -#define OUT_VSIZE_5M (1920) - -#define OUT_YUV_VSIZE_MIN (64) -#define OUT_YUV_HSIZE_MIN (96) -#define OUT_JPG_VSIZE_MIN (64) -#define OUT_JPG_HSIZE_MIN (96) -#define OUT_YUV_15FPS_VSIZE_MAX (360) -#define OUT_YUV_15FPS_HSIZE_MAX (480) -#define OUT_YUV_30FPS_VSIZE_MAX (360) -#define OUT_YUV_30FPS_HSIZE_MAX (480) -#define OUT_YUV_60FPS_VSIZE_MAX (360) -#define OUT_YUV_60FPS_HSIZE_MAX (480) -#define OUT_YUV_120FPS_VSIZE_MAX (240) -#define OUT_YUV_120FPS_HSIZE_MAX (320) -#define OUT_JPG_15FPS_VSIZE_MAX (1944) -#define OUT_JPG_15FPS_HSIZE_MAX (2592) -#define OUT_JPG_30FPS_VSIZE_MAX (960) -#define OUT_JPG_30FPS_HSIZE_MAX (1280) -#define OUT_JPG_60FPS_VSIZE_MAX (480) -#define OUT_JPG_60FPS_HSIZE_MAX (640) -#define OUT_JPG_120FPS_VSIZE_MAX (240) -#define OUT_JPG_120FPS_HSIZE_MAX (320) - -#define OUT_YUVINT_30FPS_VSIZE_MAX (240) -#define OUT_YUVINT_30FPS_HSIZE_MAX (400) -#define OUT_JPGINT_30FPS_VSIZE_MAX (960) -#define OUT_JPGINT_30FPS_HSIZE_MAX (1280) -#define OUT_JPGINT_15FPS_VSIZE_MAX (1224) -#define OUT_JPGINT_15FPS_HSIZE_MAX (1632) - -#define VINT_TIMEOUT (400) /* ms */ -#define VINT_WAIT_TIME (5) /* ms */ -#define VINT_DELAY_TIME (0) /* ms */ -#define CAMERA_MODE_TIMEOUT (800) /* ms */ -#define CAMERA_MODE_WAIT_TIME (10) /* ms */ -#define CAMERA_MODE_DELAY_TIME (0) /* ms */ -#define DEVICE_STATE_TIMEOUT (100) /* ms */ -#define DEVICE_STATE_WAIT_TIME (1) /* ms */ -#define DEVICE_STATE_DELAY_TIME (2) /* ms */ - -#define I2CFREQ_STANDARD (100000) /* Standard mode : 100kHz */ -#define I2CFREQ_FAST (400000) /* Fast mode : 400kHz */ - -#define ISX012_SIZE_STEP (2) - -#define CXC_RGB_DATA_UNIT_NUM (27) -#define CXC_RGB_DATA_UNIT_SIZE (7) -#define CXC_GRB_DATA_UNIT_NUM (27) -#define CXC_GRB_DATA_UNIT_SIZE (7) -#define SHD_RGB_DATA_UNIT_NUM (27) -#define SHD_RGB_DATA_UNIT_SIZE (11) -#define SHD_GRB_DATA_UNIT_NUM (27) -#define SHD_GRB_DATA_UNIT_SIZE (11) -#define SHD_R1_DATA_UNIT_NUM (14) -#define SHD_R1_DATA_UNIT_SIZE (11) -#define SHD_R2_DATA_UNIT_NUM (14) -#define SHD_R2_DATA_UNIT_SIZE (11) -#define SHD_B2_DATA_UNIT_NUM (14) -#define SHD_B2_DATA_UNIT_SIZE (11) - -#ifdef CONFIG_DEBUG_IMAGER_ERROR -#define imagererr(format, ...) _err(format, ##__VA_ARGS__) -#else -#define imagererr(x...) -#endif - -#ifdef CONFIG_DEBUG_IMAGER_WARN -#define imagerwarn(format, ...) _warn(format, ##__VA_ARGS__) -#else -#define imagerwarn(x...) -#endif - -#ifdef CONFIG_DEBUG_IMAGER_INFO -#define imagerinfo(format, ...) _info(format, ##__VA_ARGS__) -#else -#define imagerinfo(x...) -#endif - -#define CHECK_RANGE(value,min,max,step) do { \ - if ((value < min) || \ - (value > max) || \ - ((value - min) % step != 0)) \ - { \ - return -EINVAL;\ - } \ - } while (0) - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -enum isx012_state_e -{ - STATE_ISX012_PRESLEEP, - STATE_ISX012_SLEEP, - STATE_ISX012_ACTIVE, - STATE_ISX012_POWEROFF, -}; - -typedef enum isx012_state_e isx012_state_t; - -struct isx012_reg_s -{ - uint16_t regaddr; - uint16_t regval; - uint8_t regsize; -}; - -typedef struct isx012_reg_s isx012_reg_t; - -struct isx012_conv_v4l2_to_regval_s -{ - int32_t v4l2; - int16_t regval; -}; - -typedef struct isx012_conv_v4l2_to_regval_s isx012_conv_v4l2_to_regval_t; - -struct isx012_modeparam_s -{ - uint8_t fps; /* use ISX012 register setting value */ - uint32_t format; /* use V4L2 definition */ - uint16_t hsize; - uint16_t vsize; - uint16_t int_hsize; - uint16_t int_vsize; -}; - -typedef struct isx012_modeparam_s isx012_modeparam_t; - -struct isx012_param_s -{ - isx012_modeparam_t video; /* Parameter for video capture mode */ - isx012_modeparam_t still; /* Parameter for still capture mode */ -}; - -typedef struct isx012_param_s isx012_param_t; - -struct isx012_dev_s -{ - FAR struct i2c_master_s *i2c; /* I2C interface */ - uint8_t i2c_addr; /* I2C address */ - int i2c_freq; /* Frequency */ - isx012_state_t state; /* ISX012 status */ - bool dma_state; /* true means "in DMA" */ - uint8_t mode; /* ISX012 mode */ - isx012_param_t param; /* ISX012 parameters */ - void *video_priv; /* pointer to video private data */ -}; - -typedef struct isx012_dev_s isx012_dev_t; - -#define ARRAY_NENTRIES(a) (sizeof(a)/sizeof(isx012_reg_t)) - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/* register operations */ - -static uint16_t isx012_getreg(isx012_dev_t *priv, - uint16_t regaddr, uint16_t regsize); -static int isx012_putreg(isx012_dev_t *priv, uint16_t regaddr, - uint16_t regval, uint16_t regsize); -static int isx012_putreglist(isx012_dev_t *priv, - FAR const isx012_reg_t *reglist, size_t nentries); -#ifdef ISX012_CHECK_IN_DETAIL -static int isx012_putregs(isx012_dev_t *priv, uint16_t regaddr, - uint8_t *regvals, uint8_t regsize); -static int isx012_chipid(FAR struct i2c_master_s *i2c); -#endif - -static int isx012_chk_int_state(isx012_dev_t *priv, - uint8_t sts, uint32_t delay_time, - uint32_t wait_time, uint32_t timeout); -static int isx012_set_mode_param(isx012_dev_t *priv, - enum v4l2_buf_type type, - isx012_modeparam_t *param); -static int isx012_change_camera_mode(isx012_dev_t *priv, uint8_t mode); -static int isx012_change_device_state(isx012_dev_t *priv, - isx012_state_t state); -static int isx012_set_supported_frminterval(uint32_t fps_index, - FAR struct v4l2_fract *interval); -static int8_t isx012_get_maximum_fps(FAR struct v4l2_frmivalenum *frmival); -static int isx012_set_shd(FAR isx012_dev_t *priv); - -static bool is_movie_needed(isx012_modeparam_t *param); - -/* video driver HAL infterface */ - -static int isx012_open(FAR void *video_private); -static int isx012_close(void); -static int isx012_do_halfpush(bool enable); -static int isx012_set_buftype(enum v4l2_buf_type type); -static int isx012_set_buf(uint32_t bufaddr, uint32_t bufsize); -static int isx012_cancel_dma(void); -static int isx012_check_fmt(enum v4l2_buf_type buf_type, - uint32_t pixel_format); -static int isx012_get_range_of_fmt(FAR struct v4l2_fmtdesc *format); -static int isx012_get_range_of_framesize(FAR struct v4l2_frmsizeenum - *frmsize); -static int isx012_try_format(FAR struct v4l2_format *format); -static int isx012_set_format(FAR struct v4l2_format *format); -static int isx012_get_range_of_frameinterval(FAR struct v4l2_frmivalenum - *frmival); -static int isx012_set_frameinterval(FAR struct v4l2_streamparm *parm); -static int isx012_get_range_of_ctrlval(FAR struct v4l2_query_ext_ctrl - *range); -static int isx012_get_menu_of_ctrlval(FAR struct v4l2_querymenu *menu); -static int isx012_get_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); -static int isx012_set_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); -static int isx012_refresh(void); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static isx012_dev_t g_isx012_private; - -#ifndef ISX012_NOT_USE_NSTBY -static const isx012_reg_t g_isx012_presleep[] = -{ - {PLL_CKSEL, 0x00, 0x01}, /* PLL_CKSEL */ - {SRCCK_DIV, 0x00, 0x01}, /* SRCCK_DIV */ - {INCK_SET, 0x17, 0x01}, /* INCK_SET */ -}; -#define ISX012_PRESLEEP_NENTRIES ARRAY_NENTRIES(g_isx012_presleep) -#endif - -static const isx012_reg_t g_isx012_def_init[] = -{ -#ifdef ISX012_NOT_USE_NSTBY - {PLL_CKSEL, 0x00, 0x01}, - {SRCCK_DIV, 0x00, 0x01}, -#endif - {DRIVABILITY, 0xaa, 0x01}, - {VIFCONFIG, 0x0200, 0x02}, - {YUVCONFIG_TN, 0xff0a, 0x02}, - {ILCODELEN, 0x00, 0x01}, - {AFMODE_MONI, 0x01, 0x01}, - {YUVCONFIG, 0xff6a, 0x02}, - {VIF_REC601_Y, 0x10fe, 0x02}, - {VIF_REC601_C, 0x10f0, 0x02}, - {HSENS_MODE_SEL, 0x11, 0x01}, - {VIF_CLKCONFIG1, 0x30, 0x01}, - {VIF_CLKCONFIG2, 0x30, 0x01}, - {VIF_CLKCONFIG3, 0x30, 0x01}, - {VIF_CLKCONFIG4, 0x30, 0x01}, - {VIF_CLKCONFIG5, 0x30, 0x01}, - {VIF_CLKCONFIG6, 0x30, 0x01}, - {VIF_CLKCONFIG7, 0x30, 0x01}, - {VIF_CLKCONFIG8, 0x30, 0x01}, - {VIF_CLKCONFIG9, 0x30, 0x01}, - {VIF_CLKCONFIG10, 0x30, 0x01}, - {VIF_CLKCONFIG11, 0x30, 0x01}, - {VIF_CLKCONFIG12, 0x30, 0x01}, - {VIF_CLKCONFIG13, 0x11, 0x01}, - {VIF_CLKCONFIG14, 0x11, 0x01}, - {VIF_CLKCONFIG15, 0x11, 0x01}, - {VIF_CLKCONFIG16, 0x11, 0x01}, -#ifdef ISX012_NOT_USE_NSTBY - {INCK_SET, 0x17, 0x01}, /* INCK_SET */ -#endif - {FRM_FIX_SN1_2, 0xff, 0x01}, /* Fix framerate */ - {FAST_MODECHG_EN, 0x01, 0x01}, - {FAST_SHT_MODE_SEL, 0x01, 0x01}, - {CAP_HALF_AE_CTRL, 0x07, 0x01}, /* HAFREL=HIGHSPEED, CAP=Auto */ - {HALF_AWB_CTRL, 0x01, 0x01}, - {AESPEED_FAST, 0x0f, 0x01}, - {FASTMOVE_TIMEOUT, 0x2d, 0x01}, - {YGAMMA_MODE, 0x01, 0x01}, - {INT_QLTY2, 0x50, 0x01}, -}; -#define ISX012_RESET_NENTRIES ARRAY_NENTRIES(g_isx012_def_init) - -static const uint8_t g_isx012_cxc_rgb_data[CXC_RGB_DATA_UNIT_NUM] - [CXC_RGB_DATA_UNIT_SIZE] = -{ - {0x01, 0x43, 0xc0, 0xf0, 0x4f, 0xfc, 0x13}, /* CXC_RGB_UNIT0 */ - {0x80, 0x44, 0x20, 0x21, 0x48, 0x04, 0x0e}, /* CXC_RGB_UNIT1 */ - {0x81, 0x43, 0xc0, 0x10, 0x30, 0xfc, 0x13}, /* CXC_RGB_UNIT2 */ - {0xff, 0x04, 0x20, 0x11, 0x48, 0x08, 0x12}, /* CXC_RGB_UNIT3 */ - {0x81, 0x43, 0xe0, 0x20, 0x48, 0x08, 0x12}, /* CXC_RGB_UNIT4 */ - {0x80, 0x03, 0xe0, 0x00, 0x38, 0x04, 0x10}, /* CXC_RGB_UNIT5 */ - {0x01, 0x84, 0x20, 0x21, 0x48, 0x04, 0x10}, /* CXC_RGB_UNIT6 */ - {0x01, 0x04, 0xc0, 0x10, 0x20, 0x00, 0x08}, /* CXC_RGB_UNIT7 */ - {0x81, 0x82, 0xc0, 0x20, 0x38, 0x08, 0x0e}, /* CXC_RGB_UNIT8 */ - {0x01, 0x43, 0xc0, 0x10, 0x20, 0x04, 0x04}, /* CXC_RGB_UNIT9 */ - {0x01, 0x41, 0x40, 0x10, 0x20, 0x08, 0x0a}, /* CXC_RGB_UNIT10 */ - {0x82, 0x82, 0x80, 0x20, 0x20, 0x04, 0x04}, /* CXC_RGB_UNIT11 */ - {0x82, 0x80, 0x20, 0x20, 0x08, 0x04, 0x06}, /* CXC_RGB_UNIT12 */ - {0x81, 0x42, 0xa0, 0x10, 0x20, 0x04, 0x08}, /* CXC_RGB_UNIT13 */ - {0x81, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00}, /* CXC_RGB_UNIT14 */ - {0x01, 0x41, 0x80, 0x10, 0x20, 0x00, 0x08}, /* CXC_RGB_UNIT15 */ - {0x00, 0x42, 0x20, 0x20, 0x08, 0x08, 0x00}, /* CXC_RGB_UNIT16 */ - {0x82, 0xc0, 0x40, 0x20, 0x20, 0x08, 0x08}, /* CXC_RGB_UNIT17 */ - {0x80, 0x02, 0xa0, 0x10, 0x20, 0x08, 0x04}, /* CXC_RGB_UNIT18 */ - {0x02, 0x81, 0x60, 0x30, 0x20, 0x08, 0x0a}, /* CXC_RGB_UNIT19 */ - {0x82, 0x42, 0xc0, 0x10, 0x30, 0x04, 0x0a}, /* CXC_RGB_UNIT20 */ - {0x03, 0xc3, 0xa0, 0x40, 0x28, 0x0c, 0x0a}, /* CXC_RGB_UNIT21 */ - {0x03, 0xc3, 0xc0, 0x20, 0x20, 0x08, 0x08}, /* CXC_RGB_UNIT22 */ - {0x82, 0xc2, 0xc0, 0x30, 0x40, 0x10, 0x0e}, /* CXC_RGB_UNIT23 */ - {0x84, 0x03, 0xa1, 0x40, 0x28, 0x08, 0x08}, /* CXC_RGB_UNIT24 */ - {0x02, 0x82, 0xa0, 0x30, 0x30, 0x0c, 0x10}, /* CXC_RGB_UNIT25 */ - {0x84, 0x03, 0xe1, 0x40, 0x28, 0x10, 0x0a}, /* CXC_RGB_UNIT26 */ -}; - -static const uint8_t g_isx012_cxc_grb_data[CXC_GRB_DATA_UNIT_NUM] - [CXC_GRB_DATA_UNIT_SIZE] = -{ - {0x00, 0x3d, 0x40, 0x0f, 0xc0, 0x03, 0xf2}, /* CXC_GRB_UNIT0 */ - {0x80, 0x7c, 0x80, 0x1f, 0xd8, 0x03, 0xf0}, /* CXC_GRB_UNIT1 */ - {0x00, 0x3c, 0x40, 0x0f, 0xd0, 0x03, 0xf0}, /* CXC_GRB_UNIT2 */ - {0x80, 0x3c, 0x20, 0x1f, 0xe0, 0x07, 0xf6}, /* CXC_GRB_UNIT3 */ - {0x00, 0x3c, 0x00, 0x1f, 0xd0, 0x07, 0xf4}, /* CXC_GRB_UNIT4 */ - {0x00, 0x3d, 0x40, 0x0f, 0xc8, 0x03, 0xf2}, /* CXC_GRB_UNIT5 */ - {0x80, 0xfc, 0x5f, 0xff, 0xd7, 0x07, 0xf4}, /* CXC_GRB_UNIT6 */ - {0x01, 0x7d, 0x40, 0x0f, 0xd0, 0xff, 0xf3}, /* CXC_GRB_UNIT7 */ - {0x7f, 0xfd, 0x3f, 0x0f, 0xc8, 0x03, 0xf2}, /* CXC_GRB_UNIT8 */ - {0x81, 0x7c, 0x20, 0x0f, 0xd0, 0xff, 0xf7}, /* CXC_GRB_UNIT9 */ - {0x7e, 0xfe, 0x5f, 0x0f, 0xd8, 0x03, 0xf6}, /* CXC_GRB_UNIT10 */ - {0x80, 0xbd, 0xa0, 0x2f, 0xe8, 0x07, 0xfa}, /* CXC_GRB_UNIT11 */ - {0x80, 0xfe, 0xbf, 0x0f, 0xe8, 0xff, 0xf9}, /* CXC_GRB_UNIT12 */ - {0x00, 0x3e, 0x80, 0x3f, 0xe8, 0x0f, 0xfa}, /* CXC_GRB_UNIT13 */ - {0x02, 0x40, 0xe0, 0x0f, 0xf8, 0x03, 0xfe}, /* CXC_GRB_UNIT14 */ - {0x80, 0x7f, 0xe0, 0x1f, 0xf8, 0x17, 0xfe}, /* CXC_GRB_UNIT15 */ - {0x85, 0xff, 0xe0, 0x2f, 0x08, 0x04, 0x04}, /* CXC_GRB_UNIT16 */ - {0x81, 0x40, 0x20, 0x20, 0x00, 0x08, 0x00}, /* CXC_GRB_UNIT17 */ - {0x84, 0x00, 0x21, 0x30, 0x10, 0x0c, 0x06}, /* CXC_GRB_UNIT18 */ - {0x02, 0x82, 0x40, 0x20, 0x10, 0x0c, 0x02}, /* CXC_GRB_UNIT19 */ - {0x83, 0x00, 0x21, 0x40, 0x08, 0x10, 0x06}, /* CXC_GRB_UNIT20 */ - {0x83, 0x82, 0xa0, 0x20, 0x20, 0x08, 0x08}, /* CXC_GRB_UNIT21 */ - {0x02, 0x81, 0x40, 0x30, 0x18, 0x0c, 0x06}, /* CXC_GRB_UNIT22 */ - {0x03, 0x81, 0x80, 0x10, 0x20, 0x04, 0x08}, /* CXC_GRB_UNIT23 */ - {0x82, 0x82, 0x80, 0x20, 0x20, 0x0c, 0x06}, /* CXC_GRB_UNIT24 */ - {0x83, 0xc1, 0x40, 0x20, 0x20, 0x04, 0x08}, /* CXC_GRB_UNIT25 */ - {0x01, 0x82, 0xa0, 0x20, 0x20, 0x08, 0x08}, /* CXC_GRB_UNIT26 */ -}; - -static const uint8_t g_isx012_shd_rgb_data[SHD_RGB_DATA_UNIT_NUM] - [SHD_RGB_DATA_UNIT_SIZE] = -{ - {0xf1, 0x59, 0x52, 0x7b, 0x98, 0xc4, 0x9d, 0x23, 0x29, 0x87, 0x46}, /* SHD_RGB_UNIT0 */ - {0xc6, 0x81, 0xd1, 0x70, 0x56, 0xe4, 0x9c, 0x1b, 0x6d, 0x07, 0x48}, /* SHD_RGB_UNIT1 */ - {0xdd, 0xf1, 0x51, 0x7d, 0xa8, 0xb4, 0x1e, 0x25, 0x49, 0xc7, 0x46}, /* SHD_RGB_UNIT2 */ - {0xbd, 0xf1, 0x50, 0x6d, 0x2a, 0x44, 0x1b, 0x0a, 0x01, 0x87, 0x44}, /* SHD_RGB_UNIT3 */ - {0xd0, 0xa9, 0x51, 0x77, 0x84, 0xd4, 0x9d, 0x1f, 0x2d, 0xc7, 0x44}, /* SHD_RGB_UNIT4 */ - {0xa8, 0xa9, 0xcf, 0x62, 0x98, 0xa3, 0x17, 0xdb, 0xfc, 0x05, 0x38}, /* SHD_RGB_UNIT5 */ - {0x90, 0xe1, 0x8e, 0x6a, 0x08, 0xc4, 0x9b, 0x0e, 0x11, 0x07, 0x43}, /* SHD_RGB_UNIT6 */ - {0xac, 0xa9, 0x4f, 0x5d, 0x4e, 0x13, 0x15, 0xb9, 0xf8, 0x44, 0x2b}, /* SHD_RGB_UNIT7 */ - {0x44, 0x21, 0xcb, 0x56, 0x0e, 0x63, 0x98, 0xe3, 0x78, 0x86, 0x3d}, /* SHD_RGB_UNIT8 */ - {0xab, 0x81, 0x4f, 0x62, 0x7c, 0xc3, 0x94, 0xb4, 0x98, 0x84, 0x26}, /* SHD_RGB_UNIT9 */ - {0x14, 0xe9, 0x48, 0x46, 0x4a, 0x12, 0x93, 0xa4, 0x84, 0xc5, 0x31}, /* SHD_RGB_UNIT10 */ - {0x81, 0xe9, 0x4d, 0x67, 0xac, 0x73, 0x17, 0xd0, 0xdc, 0x24, 0x29}, /* SHD_RGB_UNIT11 */ - {0x12, 0xb9, 0x08, 0x40, 0x02, 0x52, 0x10, 0x84, 0x6c, 0x64, 0x25}, /* SHD_RGB_UNIT12 */ - {0x4c, 0x91, 0xcb, 0x5b, 0x4c, 0xe3, 0x19, 0xec, 0xdc, 0x05, 0x34}, /* SHD_RGB_UNIT13 */ - {0x37, 0x39, 0x8a, 0x44, 0x2a, 0x02, 0x10, 0x80, 0x14, 0xe4, 0x20}, /* SHD_RGB_UNIT14 */ - {0x1c, 0x51, 0x49, 0x53, 0xe4, 0x02, 0x17, 0xd3, 0xb8, 0xe6, 0x3d}, /* SHD_RGB_UNIT15 */ - {0x8b, 0xd9, 0x8d, 0x53, 0xc8, 0x72, 0x12, 0x98, 0x50, 0x24, 0x23}, /* SHD_RGB_UNIT16 */ - {0x19, 0x11, 0x89, 0x4c, 0x8c, 0x32, 0x16, 0xc7, 0x14, 0x06, 0x38}, /* SHD_RGB_UNIT17 */ - {0xca, 0xc1, 0x10, 0x6c, 0xe0, 0x83, 0x97, 0xd0, 0x4c, 0xa5, 0x2d}, /* SHD_RGB_UNIT18 */ - {0x3e, 0x99, 0x0a, 0x51, 0xbc, 0xc2, 0x15, 0xc2, 0x28, 0x26, 0x39}, /* SHD_RGB_UNIT19 */ - {0xa5, 0x89, 0x0f, 0x7b, 0x8c, 0x64, 0x9d, 0x14, 0xb9, 0x46, 0x3e}, /* SHD_RGB_UNIT20 */ - {0x8f, 0x41, 0xce, 0x5e, 0x5e, 0x03, 0x98, 0xdc, 0x50, 0xe6, 0x3a}, /* SHD_RGB_UNIT21 */ - {0xb4, 0x49, 0x90, 0x72, 0x50, 0x74, 0xa1, 0x3a, 0x05, 0x88, 0x4b}, /* SHD_RGB_UNIT22 */ - {0xe1, 0xd1, 0x91, 0x71, 0x38, 0xc4, 0x1b, 0x0a, 0xed, 0x86, 0x42}, /* SHD_RGB_UNIT23 */ - {0xcb, 0x49, 0xd1, 0x78, 0x86, 0x74, 0x9f, 0x2d, 0xb9, 0x88, 0x51}, /* SHD_RGB_UNIT24 */ - {0x11, 0x62, 0x93, 0x7c, 0x9c, 0x94, 0x1d, 0x1b, 0x41, 0x67, 0x46}, /* SHD_RGB_UNIT25 */ - {0xcf, 0x81, 0x91, 0x77, 0x82, 0x54, 0x9f, 0x2a, 0x21, 0xa8, 0x4d}, /* SHD_RGB_UNIT26 */ -}; - -static const uint8_t g_isx012_shd_grb_data[SHD_GRB_DATA_UNIT_NUM] - [SHD_GRB_DATA_UNIT_SIZE] = -{ - {0xe8, 0xa9, 0x0f, 0x78, 0xe4, 0x13, 0x9d, 0xf0, 0x04, 0xe7, 0x39}, /* SHD_GRB_UNIT0 */ - {0xbd, 0x51, 0x0e, 0x6f, 0x94, 0x63, 0x1c, 0xea, 0x4c, 0x27, 0x3c}, /* SHD_GRB_UNIT1 */ - {0xd7, 0x19, 0x4f, 0x7a, 0xf4, 0xd3, 0x1d, 0xf7, 0x20, 0xe7, 0x3a}, /* SHD_GRB_UNIT2 */ - {0xb6, 0x11, 0x0e, 0x6c, 0x76, 0x03, 0x9b, 0xdd, 0xf0, 0x06, 0x39}, /* SHD_GRB_UNIT3 */ - {0xc9, 0xc1, 0x8e, 0x75, 0xc8, 0xe3, 0x9c, 0xef, 0xf8, 0xa6, 0x39}, /* SHD_GRB_UNIT4 */ - {0xa0, 0x69, 0x0d, 0x62, 0x20, 0x93, 0x97, 0xbf, 0xf4, 0xa5, 0x30}, /* SHD_GRB_UNIT5 */ - {0x8c, 0xb1, 0x8c, 0x68, 0x60, 0x13, 0x9b, 0xe0, 0xcc, 0xa6, 0x38}, /* SHD_GRB_UNIT6 */ - {0x9f, 0x71, 0x0d, 0x5c, 0xf4, 0x12, 0x15, 0xab, 0x00, 0x65, 0x28}, /* SHD_GRB_UNIT7 */ - {0x44, 0x41, 0x0a, 0x56, 0xbc, 0x02, 0x98, 0xc4, 0x50, 0x26, 0x34}, /* SHD_GRB_UNIT8 */ - {0x9a, 0x59, 0x4d, 0x5f, 0x16, 0x83, 0x14, 0xa8, 0x9c, 0x64, 0x25}, /* SHD_GRB_UNIT9 */ - {0x15, 0xc1, 0xc8, 0x46, 0x38, 0x22, 0x13, 0x9a, 0x74, 0x65, 0x2c}, /* SHD_GRB_UNIT10 */ - {0x78, 0x11, 0x4c, 0x63, 0x36, 0xb3, 0x96, 0xbb, 0xcc, 0x44, 0x27}, /* SHD_GRB_UNIT11 */ - {0x11, 0xa1, 0x48, 0x40, 0x04, 0x72, 0x10, 0x83, 0x70, 0x84, 0x23}, /* SHD_GRB_UNIT12 */ - {0x4a, 0x69, 0xca, 0x59, 0xe0, 0xf2, 0x98, 0xcc, 0xb0, 0xa5, 0x2e}, /* SHD_GRB_UNIT13 */ - {0x33, 0xc1, 0x09, 0x44, 0x24, 0x02, 0x10, 0x80, 0x14, 0x84, 0x20}, /* SHD_GRB_UNIT14 */ - {0x1b, 0xd1, 0x48, 0x52, 0x98, 0x72, 0x96, 0xb7, 0x8c, 0x06, 0x35}, /* SHD_GRB_UNIT15 */ - {0x81, 0x39, 0xcc, 0x51, 0x96, 0x32, 0x92, 0x92, 0x48, 0x44, 0x22}, /* SHD_GRB_UNIT16 */ - {0x17, 0xb9, 0x48, 0x4b, 0x5e, 0xa2, 0x15, 0xb0, 0xd8, 0x45, 0x30}, /* SHD_GRB_UNIT17 */ - {0xc0, 0x19, 0xce, 0x69, 0x56, 0x23, 0x97, 0xba, 0x38, 0x05, 0x2a}, /* SHD_GRB_UNIT18 */ - {0x3b, 0xe1, 0x09, 0x50, 0x82, 0x42, 0x95, 0xac, 0xf8, 0x05, 0x31}, /* SHD_GRB_UNIT19 */ - {0x94, 0x19, 0x4d, 0x78, 0xca, 0xe3, 0x9c, 0xe8, 0xa8, 0xa6, 0x35}, /* SHD_GRB_UNIT20 */ - {0x8b, 0x71, 0xcc, 0x5d, 0xf8, 0xa2, 0x97, 0xc0, 0x24, 0xa6, 0x32}, /* SHD_GRB_UNIT21 */ - {0xa4, 0xb1, 0x8d, 0x6d, 0x96, 0xd3, 0xa0, 0x09, 0xe1, 0xa7, 0x3f}, /* SHD_GRB_UNIT22 */ - {0xde, 0x09, 0xcf, 0x70, 0x92, 0x73, 0x9b, 0xe0, 0xcc, 0x06, 0x38}, /* SHD_GRB_UNIT23 */ - {0xc0, 0x89, 0x4e, 0x74, 0xcc, 0x13, 0x1e, 0xfc, 0x84, 0x48, 0x45}, /* SHD_GRB_UNIT24 */ - {0x06, 0x7a, 0xd0, 0x7a, 0xe6, 0x33, 0x1d, 0xef, 0x24, 0x07, 0x3b}, /* SHD_GRB_UNIT25 */ - {0xc4, 0xb1, 0x0e, 0x74, 0xca, 0x33, 0x1e, 0xfc, 0xc4, 0x07, 0x41}, /* SHD_GRB_UNIT26 */ -}; - -static const uint8_t g_isx012_shd_r1_data[SHD_R1_DATA_UNIT_NUM] - [SHD_R1_DATA_UNIT_SIZE] = -{ - {0x10, 0x92, 0x10, 0x82, 0xf8, 0x43, 0x1f, 0xfb, 0xf0, 0xe7, 0x40}, /* SHD_R1_UNIT0 */ - {0x07, 0x92, 0xd0, 0x82, 0xec, 0x33, 0x9e, 0xed, 0x68, 0xe7, 0x3c}, /* SHD_R1_UNIT1 */ - {0xfa, 0x21, 0xd0, 0x7e, 0xce, 0xa3, 0x1b, 0xcd, 0x20, 0xe6, 0x31}, /* SHD_R1_UNIT2 */ - {0xa6, 0x69, 0xce, 0x78, 0xbc, 0xa3, 0x1b, 0xbe, 0x44, 0x25, 0x28}, /* SHD_R1_UNIT3 */ - {0x45, 0x19, 0xcb, 0x65, 0x78, 0xe3, 0x1b, 0xc8, 0x3c, 0xa5, 0x24}, /* SHD_R1_UNIT4 */ - {0x15, 0xc1, 0x48, 0x4d, 0xd6, 0x72, 0x99, 0xd3, 0xdc, 0x25, 0x27}, /* SHD_R1_UNIT5 */ - {0x11, 0x01, 0x08, 0x41, 0x42, 0x42, 0x15, 0xc1, 0xa4, 0x06, 0x2f}, /* SHD_R1_UNIT6 */ - {0x39, 0x89, 0x08, 0x40, 0x0a, 0x22, 0x12, 0xab, 0x0c, 0x26, 0x38}, /* SHD_R1_UNIT7 */ - {0x91, 0x71, 0x4a, 0x49, 0x2c, 0xa2, 0x11, 0x9c, 0xc4, 0xa5, 0x33}, /* SHD_R1_UNIT8 */ - {0xe2, 0xe1, 0x4d, 0x5f, 0xa4, 0x22, 0x94, 0xa3, 0xa0, 0x05, 0x34}, /* SHD_R1_UNIT9 */ - {0xc7, 0x41, 0x50, 0x7c, 0x7e, 0xd3, 0x19, 0xc5, 0x48, 0x86, 0x35}, /* SHD_R1_UNIT10 */ - {0xda, 0xa9, 0xcf, 0x8c, 0x42, 0x24, 0x20, 0xf5, 0x8c, 0x67, 0x3c}, /* SHD_R1_UNIT11 */ - {0xf6, 0x89, 0xd0, 0x88, 0x90, 0x34, 0x23, 0x0b, 0x15, 0xa8, 0x3f}, /* SHD_R1_UNIT12 */ - {0x00, 0x72, 0x10, 0x89, 0x68, 0x04, 0x69, 0x00, 0x00, 0x19, 0x26}, /* SHD_R1_UNIT13 */ -}; - -static const uint8_t g_isx012_shd_r2_data[SHD_R2_DATA_UNIT_NUM] - [SHD_R2_DATA_UNIT_SIZE] = -{ - {0x3a, 0xe2, 0x11, 0x8c, 0x42, 0x74, 0xa1, 0x0c, 0x89, 0x08, 0x46}, /* SHD_R2_UNIT0 */ - {0x30, 0xe2, 0xd1, 0x8c, 0x36, 0x54, 0x20, 0xfe, 0xec, 0x47, 0x41}, /* SHD_R2_UNIT1 */ - {0x20, 0x5a, 0x91, 0x88, 0x16, 0x94, 0x1d, 0xda, 0x80, 0x26, 0x35}, /* SHD_R2_UNIT2 */ - {0xc2, 0x69, 0x0f, 0x81, 0x00, 0x94, 0x9d, 0xc9, 0x84, 0xe5, 0x29}, /* SHD_R2_UNIT3 */ - {0x54, 0xb1, 0x0b, 0x6c, 0xb2, 0xb3, 0x9d, 0xd4, 0x74, 0x85, 0x25}, /* SHD_R2_UNIT4 */ - {0x1a, 0xf1, 0x08, 0x50, 0xfc, 0xe2, 0x1a, 0xe0, 0x2c, 0x66, 0x28}, /* SHD_R2_UNIT5 */ - {0x14, 0x01, 0x88, 0x41, 0x4e, 0x32, 0x16, 0xcb, 0x08, 0x87, 0x31}, /* SHD_R2_UNIT6 */ - {0x42, 0x99, 0x08, 0x40, 0x0c, 0x72, 0x92, 0xb1, 0x58, 0x86, 0x3b}, /* SHD_R2_UNIT7 */ - {0xa8, 0xd9, 0xca, 0x4a, 0x32, 0xe2, 0x91, 0xa0, 0x04, 0x66, 0x36}, /* SHD_R2_UNIT8 */ - {0x02, 0xc2, 0x4e, 0x64, 0xbe, 0xd2, 0x94, 0xa9, 0xe0, 0xc5, 0x36}, /* SHD_R2_UNIT9 */ - {0xe1, 0x61, 0x91, 0x84, 0xb6, 0x43, 0x9b, 0xcf, 0x9c, 0x66, 0x38}, /* SHD_R2_UNIT10 */ - {0xf6, 0xa1, 0x50, 0x97, 0x8e, 0x34, 0x22, 0x04, 0x01, 0x08, 0x40}, /* SHD_R2_UNIT11 */ - {0x15, 0x9a, 0x51, 0x92, 0xf2, 0xd4, 0xa5, 0x1d, 0x99, 0xa8, 0x43}, /* SHD_R2_UNIT12 */ - {0x21, 0x82, 0x91, 0x92, 0xbe, 0xf4, 0x9e, 0xf3, 0x4c, 0x87, 0x38}, /* SHD_R2_UNIT13 */ -}; - -static const uint8_t g_isx012_shd_b2_data[SHD_B2_DATA_UNIT_NUM] - [SHD_B2_DATA_UNIT_SIZE] = -{ - {0xef, 0x39, 0xcf, 0x74, 0x88, 0xb3, 0x1b, 0xdf, 0x20, 0x47, 0x3b}, /* SHD_B2_UNIT0 */ - {0xdf, 0x59, 0xcf, 0x77, 0x8c, 0x43, 0x1b, 0xd7, 0xb8, 0x46, 0x37}, /* SHD_B2_UNIT1 */ - {0xcc, 0xc1, 0x0e, 0x73, 0x78, 0xa3, 0x99, 0xc1, 0xd0, 0x25, 0x2f}, /* SHD_B2_UNIT2 */ - {0x87, 0x09, 0x0d, 0x6c, 0x64, 0x93, 0x99, 0xb6, 0x30, 0xc5, 0x27}, /* SHD_B2_UNIT3 */ - {0x3f, 0xb1, 0x0a, 0x5f, 0x2a, 0x93, 0x99, 0xbc, 0x1c, 0x85, 0x24}, /* SHD_B2_UNIT4 */ - {0x16, 0xc9, 0x48, 0x4c, 0xb6, 0x92, 0x17, 0xc4, 0x94, 0x85, 0x26}, /* SHD_B2_UNIT5 */ - {0x10, 0x09, 0x88, 0x41, 0x3a, 0x52, 0x94, 0xb2, 0x2c, 0xc6, 0x2c}, /* SHD_B2_UNIT6 */ - {0x33, 0x79, 0x08, 0x40, 0x08, 0xc2, 0x11, 0xa2, 0x94, 0x65, 0x34}, /* SHD_B2_UNIT7 */ - {0x7e, 0x39, 0x4a, 0x48, 0x26, 0x52, 0x91, 0x96, 0x64, 0x05, 0x2f}, /* SHD_B2_UNIT8 */ - {0xbf, 0x09, 0x8d, 0x5b, 0x92, 0xa2, 0x93, 0x9d, 0x4c, 0x65, 0x2f}, /* SHD_B2_UNIT9 */ - {0x95, 0xf9, 0x0e, 0x73, 0x48, 0x63, 0x98, 0xb9, 0xd8, 0xa5, 0x30}, /* SHD_B2_UNIT10 */ - {0xa5, 0xb1, 0x8d, 0x83, 0xf4, 0xa3, 0x1d, 0xe0, 0xd0, 0x06, 0x36}, /* SHD_B2_UNIT11 */ - {0xbe, 0xa9, 0x4e, 0x79, 0x50, 0xd4, 0x20, 0xf6, 0x54, 0xa7, 0x38}, /* SHD_B2_UNIT12 */ - {0xc5, 0x91, 0xce, 0x7a, 0xf4, 0x03, 0x44, 0x00, 0x60, 0x60, 0x00}, /* SHD_B2_UNIT13 */ -}; - -static const isx012_reg_t g_isx012_shd_thresholds[] = -{ - {SHD_INP_TH_HB_H_R2, 0x1478, 2}, - {SHD_INP_TH_HB_L_R2, 0x1380, 2}, - {SHD_INP_TH_LB_H_R2, 0x10cc, 2}, - {SHD_INP_TH_LB_L_R2, 0x1004, 2}, - {SHD_INP_TH_HB_H_RB, 0x10cc, 2}, - {SHD_INP_TH_HB_L_RB, 0x1004, 2}, - {SHD_INP_TH_LB_H_RB, 0x0000, 2}, - {SHD_INP_TH_LB_L_RB, 0x0000, 2}, -}; - -#define ISX012_SHD_THRESHOLDS_NENTRIES ARRAY_NENTRIES(g_isx012_shd_thresholds) - -static const isx012_reg_t g_isx012_shd_wb[] = -{ - {NORMR, 0x1101, 2}, - {NORMB, 0x0f7b, 2}, - {AWBPRER, 0x0147, 2}, - {AWBPREB, 0x022a, 2}, - {SHD_PRER_OFFSET_R2, 0x001b, 2}, - {SHD_PRER_OFFSET_RB, 0x000b, 2}, - {SHD_PREB_OFFSET_RB, 0x0003, 2}, -}; - -#define ISX012_SHD_WB_NENTRIES ARRAY_NENTRIES(g_isx012_shd_wb) - -static isx012_conv_v4l2_to_regval_t - g_isx012_supported_colorfx[ISX012_MAX_COLOREFFECT + 1] = -{ - {V4L2_COLORFX_NONE, REGVAL_EFFECT_NONE}, - {V4L2_COLORFX_BW, REGVAL_EFFECT_MONOTONE}, - {V4L2_COLORFX_SEPIA, REGVAL_EFFECT_SEPIA}, - {V4L2_COLORFX_NEGATIVE, REGVAL_EFFECT_NEGPOS}, - {V4L2_COLORFX_SKETCH, REGVAL_EFFECT_SKETCH}, - {V4L2_COLORFX_SOLARIZATION, REGVAL_EFFECT_SOLARIZATION}, - {V4L2_COLORFX_PASTEL, REGVAL_EFFECT_PASTEL}, -}; - -static isx012_conv_v4l2_to_regval_t - g_isx012_supported_presetwb[ISX012_MAX_PRESETWB + 1] = -{ - {V4L2_WHITE_BALANCE_AUTO, REGVAL_AWB_ATM}, - {V4L2_WHITE_BALANCE_INCANDESCENT, REGVAL_AWB_LIGHTBULB}, - {V4L2_WHITE_BALANCE_FLUORESCENT, REGVAL_AWB_FLUORESCENTLIGHT}, - {V4L2_WHITE_BALANCE_DAYLIGHT, REGVAL_AWB_CLEARWEATHER}, - {V4L2_WHITE_BALANCE_CLOUDY, REGVAL_AWB_CLOUDYWEATHER}, - {V4L2_WHITE_BALANCE_SHADE, REGVAL_AWB_SHADE}, -}; - -static isx012_conv_v4l2_to_regval_t - g_isx012_supported_photometry[ISX012_MAX_PHOTOMETRY + 1] = -{ - {V4L2_EXPOSURE_METERING_AVERAGE, REGVAL_PHOTOMETRY_AVERAGE}, - {V4L2_EXPOSURE_METERING_CENTER_WEIGHTED, REGVAL_PHOTOMETRY_CENTERWEIGHT}, - {V4L2_EXPOSURE_METERING_SPOT, REGVAL_PHOTOMETRY_SPOT}, - {V4L2_EXPOSURE_METERING_MATRIX, REGVAL_PHOTOMETRY_MULTIPATTERN}, -}; - -static isx012_conv_v4l2_to_regval_t - g_isx012_supported_iso[ISX012_MAX_ISO + 1] = -{ - {25 * 1000, REGVAL_ISO_25}, - {32 * 1000, REGVAL_ISO_32}, - {40 * 1000, REGVAL_ISO_40}, - {50 * 1000, REGVAL_ISO_50}, - {64 * 1000, REGVAL_ISO_64}, - {80 * 1000, REGVAL_ISO_80}, - {100 * 1000, REGVAL_ISO_100}, - {125 * 1000, REGVAL_ISO_125}, - {160 * 1000, REGVAL_ISO_160}, - {200 * 1000, REGVAL_ISO_200}, - {250 * 1000, REGVAL_ISO_250}, - {320 * 1000, REGVAL_ISO_320}, - {400 * 1000, REGVAL_ISO_400}, - {500 * 1000, REGVAL_ISO_500}, - {640 * 1000, REGVAL_ISO_640}, - {800 * 1000, REGVAL_ISO_800}, - {1000 * 1000, REGVAL_ISO_1000}, - {1250 * 1000, REGVAL_ISO_1250}, - {1600 * 1000, REGVAL_ISO_1600}, -}; - -static struct video_devops_s g_isx012_video_devops = -{ - .open = isx012_open, - .close = isx012_close, - .do_halfpush = isx012_do_halfpush, - .set_buftype = isx012_set_buftype, - .set_buf = isx012_set_buf, - .cancel_dma = isx012_cancel_dma, - .get_range_of_fmt = isx012_get_range_of_fmt, - .get_range_of_framesize = isx012_get_range_of_framesize, - .try_format = isx012_try_format, - .set_format = isx012_set_format, - .get_range_of_frameinterval = isx012_get_range_of_frameinterval, - .set_frameinterval = isx012_set_frameinterval, - .get_range_of_ctrlvalue = isx012_get_range_of_ctrlval, - .get_menu_of_ctrlvalue = isx012_get_menu_of_ctrlval, - .get_ctrlvalue = isx012_get_ctrlval, - .set_ctrlvalue = isx012_set_ctrlval, - .refresh = isx012_refresh, -}; - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static uint16_t isx012_getreg(isx012_dev_t *priv, - uint16_t regaddr, uint16_t regsize) -{ - struct i2c_config_s config; - volatile uint16_t regval = 0; - volatile uint8_t buffer[2]; - int ret; - - /* Set up the I2C configuration */ - - config.frequency = priv->i2c_freq; - config.address = priv->i2c_addr; - config.addrlen = 7; - buffer[0] = regaddr >> 8; - buffer[1] = regaddr & 0xff; - - /* Write the register address */ - - ret = i2c_write(priv->i2c, &config, (uint8_t *)buffer, 2); - if (ret < 0) - { - imagererr("i2c_write failed: %d\n", ret); - return 0; - } - - /* Restart and read 16bits from the register */ - - ret = i2c_read(priv->i2c, &config, (uint8_t *)buffer, regsize); - if (ret < 0) - { - imagererr("i2c_read failed: %d\n", ret); - return 0; - } - - memcpy((uint8_t *)®val, (uint8_t *)buffer, regsize); - - return regval; -} - -static int isx012_putreg(isx012_dev_t *priv, - uint16_t regaddr, uint16_t regval, uint16_t regsize) -{ - struct i2c_config_s config; - volatile uint8_t buffer[4]; - int ret; - - /* Set up the I2C configuration */ - - config.frequency = priv->i2c_freq; - config.address = priv->i2c_addr; - config.addrlen = 7; - - /* Set up for the transfer */ - - buffer[0] = regaddr >> 8; /* RegAddr Hi */ - buffer[1] = regaddr & 0xff; /* RegAddr Low */ - - memcpy((uint8_t *)&buffer[2], (uint8_t *)®val, regsize); - - /* And do it */ - - ret = i2c_write(priv->i2c, &config, - (uint8_t *)buffer, regsize + 2); - if (ret < 0) - { - imagererr("i2c_write failed: %d\n", ret); - } - - return ret; -} - -static int isx012_putreglist(isx012_dev_t *priv, - FAR const isx012_reg_t *reglist, - size_t nentries) -{ - FAR const isx012_reg_t *entry; - int ret = OK; - - for (entry = reglist; nentries > 0; nentries--, entry++) - { - ret = isx012_putreg(priv, entry->regaddr, - entry->regval, entry->regsize); - if (ret < 0) - { - imagererr("isx012_putreg failed: %d\n", ret); - return ret; - } - } - - return ret; -} - -static int isx012_chk_int_state(isx012_dev_t *priv, - uint8_t sts, uint32_t delay_time, - uint32_t wait_time, uint32_t timeout) -{ - int ret = 0; - volatile uint8_t data; - uint32_t time = 0; - - nxsig_usleep(delay_time * 1000); - while (time < timeout) - { - data = isx012_getreg(priv, INTSTS0, sizeof(data)); - data = data & sts; - if (data != 0) - { - ret = isx012_putreg(priv, INTCLR0, data, sizeof(data)); - return ret; - } - - nxsig_usleep(wait_time * 1000); - time += wait_time; - } - - return ERROR; -} - -static int isx012_replace_fmt_v4l2val_to_regval(uint32_t v4l2val, - uint8_t *regval) -{ - if (regval == NULL) - { - return -EINVAL; - } - - switch (v4l2val) - { - case V4L2_PIX_FMT_UYVY: - *regval = REGVAL_OUTFMT_YUV; - break; - - case V4L2_PIX_FMT_JPEG: - *regval = REGVAL_OUTFMT_JPEG; - break; - - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: - *regval = REGVAL_OUTFMT_INTERLEAVE; - break; - - default: /* Unsupported format */ - - return -EINVAL; - } - - return OK; -} - -static bool is_movie_needed(isx012_modeparam_t *param) -{ - bool need = true; - - if (param->format == V4L2_PIX_FMT_UYVY) - { - if (param->fps >= REGVAL_FPSTYPE_30FPS) /* This means fps <= 30 */ - { - need = false; - } - } - - return need; -} - -static int isx012_set_mode_param(isx012_dev_t *priv, - enum v4l2_buf_type type, - isx012_modeparam_t *param) -{ - int ret = 0; - uint8_t format; - uint16_t fps_regaddr; - uint16_t fmt_regaddr; - uint16_t sensmode_regaddr; - uint16_t hsize_regaddr; - uint16_t vsize_regaddr; - uint8_t sensmode; - - /* Get register address for type */ - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - { - if (is_movie_needed(param)) - { - if (priv->mode == REGVAL_MODESEL_HREL) - { - /* In Half release state, - * the setting which need movie mode is prohibited. - */ - - return -EPERM; - } - - fps_regaddr = FPSTYPE_MOVIE; - fmt_regaddr = OUTFMT_MOVIE; - sensmode_regaddr = SENSMODE_MOVIE; - hsize_regaddr = HSIZE_MOVIE; - vsize_regaddr = VSIZE_MOVIE; - } - else - { - fps_regaddr = FPSTYPE_MONI; - fmt_regaddr = OUTFMT_MONI; - sensmode_regaddr = SENSMODE_MONI; - hsize_regaddr = HSIZE_MONI; - vsize_regaddr = VSIZE_MONI; - } - } - else - { - fps_regaddr = FPSTYPE_CAP; - fmt_regaddr = OUTFMT_CAP; - sensmode_regaddr = SENSMODE_CAP; - hsize_regaddr = HSIZE_CAP; - vsize_regaddr = VSIZE_CAP; - } - - ret = isx012_putreg(priv, fps_regaddr, param->fps, sizeof(uint8_t)); - if (ret < 0) - { - return ret; - } - - ret = isx012_replace_fmt_v4l2val_to_regval(param->format, &format); - if (ret < 0) - { - return ret; - } - - ret = isx012_putreg(priv, fmt_regaddr, format, sizeof(uint8_t)); - if (ret < 0) - { - return ret; - } - - switch (param->fps) - { - case REGVAL_FPSTYPE_120FPS: - sensmode = REGVAL_SENSMODE_1_8; - break; - - case REGVAL_FPSTYPE_60FPS: - sensmode = REGVAL_SENSMODE_1_4; - break; - - case REGVAL_FPSTYPE_30FPS: - sensmode = REGVAL_SENSMODE_1_2; - break; - - default: - sensmode = REGVAL_SENSMODE_ALLPIX; - break; - } - - ret = isx012_putreg(priv, sensmode_regaddr, - sensmode, sizeof(uint8_t)); - if (ret < 0) - { - return ret; - } - - ret = isx012_putreg(priv, hsize_regaddr, - param->hsize, sizeof(uint16_t)); - if (ret < 0) - { - return ret; - } - - ret = isx012_putreg(priv, vsize_regaddr, - param->vsize, sizeof(uint16_t)); - if (ret < 0) - { - return ret; - } - - if (format == REGVAL_OUTFMT_INTERLEAVE) - { - ret = isx012_putreg(priv, HSIZE_TN, - param->int_hsize, sizeof(uint16_t)); - if (ret < 0) - { - return ret; - } - - ret = isx012_putreg(priv, VSIZE_TN, - param->int_vsize, sizeof(uint16_t)); - if (ret < 0) - { - return ret; - } - } - - return ret; -} - -void isx012_callback(uint8_t code, uint32_t size, uint32_t addr) -{ - enum v4l2_buf_type type; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - if (priv->mode == REGVAL_MODESEL_CAP) - { - /* ISX012 capture mode => still capture */ - - type = V4L2_BUF_TYPE_STILL_CAPTURE; - } - else - { - /* ISX012 monitor/halfrelease/movie mode => video capture */ - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - - video_common_notify_dma_done(code, type, size, priv->video_priv); - - return; -} - -/**************************************************************************** - * isx012_change_camera_mode - ****************************************************************************/ - -static int isx012_change_camera_mode(isx012_dev_t *priv, uint8_t mode) -{ - int ret = 0; - uint16_t format_addr; - uint8_t format_data; - uint32_t vifmode; -#ifdef ISX012_FRAME_SKIP_EN - uint8_t mask_num; - int i; -#endif /* ISX012_FRAME_SKIP_EN */ - - if (priv->state != STATE_ISX012_ACTIVE) - { - return -EPERM; - } - - switch (mode) - { - case REGVAL_MODESEL_MON: - case REGVAL_MODESEL_HREL: - format_addr = OUTFMT_MONI; - break; - - case REGVAL_MODESEL_MOV: - format_addr = OUTFMT_MOVIE; - break; - - case REGVAL_MODESEL_CAP: - format_addr = OUTFMT_CAP; - break; - - default: - return -EPERM; - } - - format_data = isx012_getreg(priv, format_addr, 1); - - switch (format_data) /* mode parallel */ - { - case REGVAL_OUTFMT_YUV: - vifmode = REGVAL_VIFMODE_YUV_PARALLEL; - break; - case REGVAL_OUTFMT_JPEG: - vifmode = REGVAL_VIFMODE_JPEG_PARALLEL; - break; - case REGVAL_OUTFMT_INTERLEAVE: - vifmode = REGVAL_VIFMODE_INTERLEAVE_PARALLEL; - break; - case REGVAL_OUTFMT_RGB: - vifmode = REGVAL_VIFMODE_RGB_PARALLEL; - break; - default: - vifmode = REGVAL_VIFMODE_YUV_PARALLEL; - break; - } - - ret = isx012_putreg(priv, VIFMODE, vifmode, sizeof(vifmode)); - if (ret < 0) - { - return ret; - } - - isx012_putreg(priv, INTCLR0, CM_CHANGED_STS, 1); - - ret = isx012_putreg(priv, MODESEL, mode, sizeof(mode)); - if (ret < 0) - { - return ret; - } - - /* Wait CM_CHANGED */ - - ret = isx012_chk_int_state(priv, CM_CHANGED_STS, - CAMERA_MODE_DELAY_TIME, - CAMERA_MODE_WAIT_TIME, - CAMERA_MODE_TIMEOUT); - if (ret != 0) - { - return ret; - } - -#ifdef ISX012_FRAME_SKIP_EN - if (mode != REGVAL_MODESEL_HREL) - { - isx012_putreg(priv, INTCLR0, VINT_STS, 1); - mask_num = isx012_getreg(priv, RO_MASK_NUM, sizeof(mask_num)); - for (i = 0; i < mask_num; i++) - { - /* Wait Next VINT */ - - ret = isx012_chk_int_state(priv, VINT_STS, VINT_DELAY_TIME, - VINT_WAIT_TIME, VINT_TIMEOUT); - if (ret != 0) - { - return ret; - } - } - } -#endif /* ISX012_FRAME_SKIP_EN */ - - return OK; -} - -/**************************************************************************** - * isx012_change_device_state - ****************************************************************************/ - -static int isx012_change_device_state(isx012_dev_t *priv, - isx012_state_t state) -{ - int ret = 0; -#ifdef ISX012_FRAME_SKIP_EN - int i; - uint8_t mute_cnt; -#endif /* ISX012_FRAME_SKIP_EN */ - - if (priv->state == STATE_ISX012_PRESLEEP || priv->state == state) - { - return -EPERM; - } - - switch (state) - { - case STATE_ISX012_SLEEP: - isx012_putreg(priv, INTCLR0, OM_CHANGED_STS, 1); - board_isx012_set_sleep(1); - break; - case STATE_ISX012_ACTIVE: - isx012_putreg(priv, INTCLR0, OM_CHANGED_STS | CM_CHANGED_STS, 1); - board_isx012_release_sleep(); - break; - case STATE_ISX012_PRESLEEP: - return -EPERM; - default: - return -EPERM; - } - - /* Wait OM_CHANGED */ - - ret = isx012_chk_int_state(priv, OM_CHANGED_STS, - DEVICE_STATE_DELAY_TIME, - DEVICE_STATE_WAIT_TIME, - DEVICE_STATE_TIMEOUT); - if (ret != 0) - { - return ret; - } - - priv->state = state; - - if (state == STATE_ISX012_ACTIVE) - { - /* Wait CM_CHANGED -> Monitoring */ - - ret = isx012_chk_int_state(priv, CM_CHANGED_STS, - CAMERA_MODE_DELAY_TIME, - CAMERA_MODE_WAIT_TIME, - CAMERA_MODE_TIMEOUT); - if (ret != 0) - { - return ret; - } - -#ifdef ISX012_FRAME_SKIP_EN - mute_cnt = isx012_getreg(priv, MUTECNT, sizeof(mute_cnt)); - isx012_putreg(priv, INTCLR0, VINT_STS, 1); - for (i = 0; i < mute_cnt; i++) - { - /* Wait Next VINT */ - - ret = isx012_chk_int_state(priv, VINT_STS, VINT_DELAY_TIME, - VINT_WAIT_TIME, VINT_TIMEOUT); - if (ret != 0) - { - return ret; - } - } -#endif /* ISX012_FRAME_SKIP_EN */ - } - - priv->mode = REGVAL_MODESEL_MON; - - return OK; -} - -int init_isx012(FAR struct isx012_dev_s *priv) -{ - int ret; - -#ifdef ISX012_NOT_USE_NSTBY - board_isx012_release_sleep(); - board_isx012_release_reset(); - nxsig_usleep(6000); -#else - board_isx012_release_reset(); - nxsig_usleep(6000); -#endif - -#ifdef ISX012_CHECK_IN_DETAIL - /* check the chip id */ - - ret = isx012_chipid(priv); - if (ret < 0) - { - imagererr("isx012_chipid failed: %d\n", ret); - board_isx012_set_reset(); - return ret; - } -#endif - - /* Wait OM_CHANGED Power OFF -> PreSleep */ - - ret = isx012_chk_int_state(priv, OM_CHANGED_STS, DEVICE_STATE_DELAY_TIME, - DEVICE_STATE_WAIT_TIME, DEVICE_STATE_TIMEOUT); - if (ret != OK) - { - imagererr("OM_CHANGED_STS(PreSleep) is Not occurred: %d\n", ret); - return ret; - } - - priv->state = STATE_ISX012_PRESLEEP; - -#ifndef ISX012_NOT_USE_NSTBY - /* set the isx012 clock */ - - /* Write INCK_SET register ISX012 change state PreSleep -> Sleep */ - - ret = isx012_putreglist(priv, g_isx012_presleep, ISX012_PRESLEEP_NENTRIES); - if (ret != OK) - { - imagererr("isx012_putreglist(INCK_SET) failed: %d\n", ret); - return ret; - } - - /* Wait OM_CHANGED PreSleep -> Sleep */ - - ret = isx012_chk_int_state(priv, OM_CHANGED_STS, DEVICE_STATE_DELAY_TIME, - DEVICE_STATE_WAIT_TIME, DEVICE_STATE_TIMEOUT); - if (ret != OK) - { - imagererr("OM_CHANGED_STS(Sleep) is Not occurred: %d\n", ret); - return ret; - } -#endif - - priv->state = STATE_ISX012_SLEEP; - priv->i2c_freq = I2CFREQ_FAST; - - /* initialize the isx012 hardware */ - - ret = isx012_putreglist(priv, g_isx012_def_init, ISX012_RESET_NENTRIES); - if (ret < 0) - { - imagererr("isx012_putreglist failed: %d\n", ret); - board_isx012_set_reset(); - return ret; - } - - /* Set shading adjustment */ - - ret = isx012_set_shd(priv); - if (ret < 0) - { - imagererr("isx012_set_shd failed: %d\n", ret); - board_isx012_set_reset(); - return ret; - } - - /* monitor mode default format: YUV4:2:2 QVGA */ - - priv->param.video.fps = REGVAL_FPSTYPE_30FPS; - priv->param.video.format = V4L2_PIX_FMT_UYVY; - priv->param.video.hsize = VIDEO_HSIZE_QVGA; - priv->param.video.vsize = VIDEO_VSIZE_QVGA; - priv->param.video.int_hsize = 0; - priv->param.video.int_vsize = 0; - - ret = isx012_set_mode_param(priv, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - &priv->param.video); - if (ret < 0) - { - board_isx012_set_reset(); - return ret; - } - - /* capture mode default format: JPEG FULLHD */ - - priv->param.still.fps = REGVAL_FPSTYPE_15FPS; - priv->param.still.format = V4L2_PIX_FMT_JPEG; - priv->param.still.hsize = VIDEO_HSIZE_FULLHD; - priv->param.still.vsize = VIDEO_VSIZE_FULLHD; - priv->param.still.int_hsize = 0; - priv->param.still.int_vsize = 0; - - ret = isx012_set_mode_param(priv, - V4L2_BUF_TYPE_STILL_CAPTURE, - &priv->param.still); - if (ret < 0) - { - board_isx012_set_reset(); - return ret; - } - - return ret; -} - -static int isx012_open(FAR void *video_private) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - int ret = 0; - - ret = board_isx012_power_on(); - if (ret < 0) - { - imagererr("Failed to power on %d\n", ret); - return ret; - } - - ret = init_isx012(priv); - if (ret < 0) - { - imagererr("Failed to init_isx012 %d\n", ret); - board_isx012_set_reset(); - board_isx012_power_off(); - return ret; - } - - ret = cxd56_cisifinit(); - if (ret < 0) - { - imagererr("Fail cxd56_cisifinit %d\n", ret); - return ret; - } - - /* Save video private information address */ - - g_isx012_private.video_priv = video_private; - - return ret; -} - -static int isx012_close(void) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - - g_isx012_private.video_priv = NULL; - - int ret = 0; - - if (priv->state == STATE_ISX012_ACTIVE) - { - board_isx012_set_sleep(1); - } - - board_isx012_set_reset(); - - ret = board_isx012_power_off(); - if (ret < 0) - { - imagererr("Failed to power off %d\n", ret); - return ret; - } - - ret = cxd56_cisifstopcapture(); - if (ret < 0) - { - imagererr("Fail cxd56_cisifstopcapture %d\n", ret); - return ret; - } - - ret = cxd56_cisiffinalize(); - if (ret < 0) - { - imagererr("Fail cxd56_cisiffinalize %d\n", ret); - return ret; - } - - priv->i2c_freq = I2CFREQ_STANDARD; - priv->state = STATE_ISX012_POWEROFF; - - return ret; -} - -static int isx012_do_halfpush(bool enable) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - uint8_t mode; - int ret = -EPERM; - - if (enable) - { - /* state transition : MONITORING -> HALFRELEASE */ - - if (priv->mode == REGVAL_MODESEL_MON) - { - mode = REGVAL_MODESEL_HREL; - ret = OK; - } - } - else - { - /* state transition : HALFRELEASE -> MONITORING */ - - if (priv->mode == REGVAL_MODESEL_HREL) - { - mode = REGVAL_MODESEL_MON; - ret = OK; - } - } - - if (ret == OK) - { - ret = isx012_change_camera_mode(priv, mode); - if (ret == OK) - { - priv->mode = mode; - } - } - - return ret; -} - -static int isx012_set_buftype(enum v4l2_buf_type type) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - uint8_t mode; - int ret = OK; - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - { - if (priv->mode == REGVAL_MODESEL_HREL) - { - /* state transition : HALFRELEASE -> HALFRELEASE */ - - mode = REGVAL_MODESEL_HREL; - } - else - { - /* state transition : CAPTURE -> MONITORING - * or MONITORING -> MONITORING - */ - - if (is_movie_needed(&priv->param.video)) - { - mode = REGVAL_MODESEL_MOV; - } - else - { - mode = REGVAL_MODESEL_MON; - } - } - } - else - { - /* state transition : any -> CAPTURE */ - - mode = REGVAL_MODESEL_CAP; - } - - /* In no active case, activate */ - - if (priv->state != STATE_ISX012_ACTIVE) - { - isx012_change_device_state(priv, STATE_ISX012_ACTIVE); - } - - if (mode != priv->mode) - { - ret = isx012_change_camera_mode(priv, mode); - if (ret == OK) - { - priv->mode = mode; - } - } - - return ret; -} - -static int isx012_set_buf(uint32_t bufaddr, uint32_t bufsize) -{ - int ret; - FAR struct isx012_dev_s *priv = &g_isx012_private; - isx012_modeparam_t *mode_param = NULL; - - cisif_param_t cis_param = - { - 0 - }; - - cisif_sarea_t sarea = - { - 0 - }; - - sarea.strg_addr = (uint8_t *)bufaddr; - sarea.strg_size = bufsize; - - if (priv->dma_state) - { - ret = cxd56_cisifsetdmabuf(&sarea); - } - else - { - if (priv->mode == REGVAL_MODESEL_CAP) - { - mode_param = &priv->param.still; - } - else - { - mode_param = &priv->param.video; - } - - switch (mode_param->format) - { - case V4L2_PIX_FMT_UYVY: /* Set YUV 4:2:2 information */ - - cis_param.yuv_param.hsize = mode_param->hsize; - cis_param.yuv_param.vsize = mode_param->vsize; - - break; - - case V4L2_PIX_FMT_JPEG: /* Set JPEG information */ - - /* no setting */ - - break; - - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* Set JPEG + YUV 4:2:2 information */ - - cis_param.yuv_param.hsize = mode_param->int_hsize; - cis_param.yuv_param.vsize = mode_param->int_vsize; - - break; - - default: /* Unsupported format */ - - return -EINVAL; - } - - cis_param.format = mode_param->format; - cis_param.comp_func = isx012_callback; - - ret = cxd56_cisifstartcapture(&cis_param, &sarea); - if (ret != OK) - { - return ret; - } - - priv->dma_state = true; - } - - return ret; -} - -static int isx012_cancel_dma(void) -{ - int ret; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - ret = cxd56_cisifstopcapture(); - if (ret != OK) - { - return ret; - } - - priv->dma_state = false; - return ret; -} - -static int isx012_check_fmt(enum v4l2_buf_type buf_type, - uint32_t pixel_format) -{ - switch (buf_type) - { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_STILL_CAPTURE: - if ((pixel_format != V4L2_PIX_FMT_JPEG) && - (pixel_format != V4L2_PIX_FMT_JPEG_WITH_SUBIMG) && - (pixel_format != V4L2_PIX_FMT_UYVY)) - { - /* Unsupported format */ - - return -EINVAL; - } - - break; - - default: /* Unsupported type */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_get_range_of_fmt(FAR struct v4l2_fmtdesc *format) -{ - if (format == NULL) - { - return -EINVAL; - } - - switch (format->type) - { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_STILL_CAPTURE: - switch (format->index) - { - case 0: /* JPEG */ - - strncpy(format->description, "JPEG", V4L2_FMT_DSC_MAX); - format->pixelformat = V4L2_PIX_FMT_JPEG; - - break; - - case 1: /* JPEG + YUV 4:2:2 */ - - strncpy(format->description, - "JPEG + YUV 4:2:2", - V4L2_FMT_DSC_MAX); - format->pixelformat = V4L2_PIX_FMT_JPEG_WITH_SUBIMG; - format->subimg_pixelformat = V4L2_PIX_FMT_UYVY; - - break; - - case 2: /* YUV 4:2:2 */ - - strncpy(format->description, "YUV 4:2:2", V4L2_FMT_DSC_MAX); - format->pixelformat = V4L2_PIX_FMT_UYVY; - - break; - - default: /* 3, 4, ... */ - return -EINVAL; - } - - break; - - default: /* Unsupported type */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_get_range_of_framesize( - FAR struct v4l2_frmsizeenum *frmsize) -{ - int ret; - - if (frmsize == NULL) - { - return -EINVAL; - } - - if (frmsize->index != 0) - { - return -EINVAL; - } - - ret = isx012_check_fmt(frmsize->buf_type, frmsize->pixel_format); - if (ret != OK) - { - return ret; - } - - switch (frmsize->pixel_format) - { - case V4L2_PIX_FMT_UYVY: /* YUV 4:2:2 */ - frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize->stepwise.min_width = OUT_YUV_HSIZE_MIN; - frmsize->stepwise.max_width = OUT_YUV_15FPS_HSIZE_MAX; - frmsize->stepwise.step_width = ISX012_SIZE_STEP; - frmsize->stepwise.min_height = OUT_YUV_VSIZE_MIN; - frmsize->stepwise.max_height = OUT_YUV_15FPS_VSIZE_MAX; - frmsize->stepwise.step_height = ISX012_SIZE_STEP; - - break; - - case V4L2_PIX_FMT_JPEG: /* JPEG */ - frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize->stepwise.min_width = OUT_JPG_HSIZE_MIN; - frmsize->stepwise.max_width = OUT_JPG_15FPS_HSIZE_MAX; - frmsize->stepwise.step_width = ISX012_SIZE_STEP; - frmsize->stepwise.min_height = OUT_JPG_VSIZE_MIN; - frmsize->stepwise.max_height = OUT_JPG_15FPS_VSIZE_MAX; - frmsize->stepwise.step_height = ISX012_SIZE_STEP; - - break; - - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + YUV 4:2:2 */ - if (frmsize->subimg_pixel_format != V4L2_PIX_FMT_UYVY) - { - /* Unsupported pixel format */ - - return -EINVAL; - } - - frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize->stepwise.min_width = OUT_JPG_HSIZE_MIN; - frmsize->stepwise.max_width = OUT_JPGINT_15FPS_HSIZE_MAX; - frmsize->stepwise.step_width = ISX012_SIZE_STEP; - frmsize->stepwise.min_height = OUT_JPG_VSIZE_MIN; - frmsize->stepwise.max_height = OUT_JPGINT_15FPS_VSIZE_MAX; - frmsize->stepwise.step_height = ISX012_SIZE_STEP; - - frmsize->subimg_type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize->subimg.stepwise.min_width = OUT_YUV_HSIZE_MIN; - frmsize->subimg.stepwise.max_width = OUT_YUVINT_30FPS_HSIZE_MAX; - frmsize->subimg.stepwise.step_width = ISX012_SIZE_STEP; - frmsize->subimg.stepwise.min_height = OUT_YUV_VSIZE_MIN; - frmsize->subimg.stepwise.max_height = OUT_YUVINT_30FPS_VSIZE_MAX; - frmsize->subimg.stepwise.step_height = ISX012_SIZE_STEP; - - break; - - default: /* Unsupported pixel format */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_try_format(FAR struct v4l2_format *format) -{ - int ret; - FAR struct v4l2_frmsizeenum support; - - if (format == NULL) - { - return -EINVAL; - } - - /* Get supported frame size information */ - - support.index = 0; - support.buf_type = format->type; - support.pixel_format = format->fmt.pix.pixelformat; - support.subimg_pixel_format = format->fmt.pix.subimg_pixelformat; - - ret = isx012_get_range_of_framesize(&support); - if (ret != OK) - { - return ret; - } - - CHECK_RANGE(format->fmt.pix.width, - support.stepwise.min_width, - support.stepwise.max_width, - support.stepwise.step_width); - - CHECK_RANGE(format->fmt.pix.height, - support.stepwise.min_height, - support.stepwise.max_height, - support.stepwise.step_height); - - if (support.pixel_format == V4L2_PIX_FMT_JPEG_WITH_SUBIMG) - { - CHECK_RANGE(format->fmt.pix.subimg_width, - support.subimg.stepwise.min_width, - support.subimg.stepwise.max_width, - support.subimg.stepwise.step_width); - - CHECK_RANGE(format->fmt.pix.subimg_height, - support.subimg.stepwise.min_height, - support.subimg.stepwise.max_height, - support.subimg.stepwise.step_height); - } - - return OK; -} - -static int isx012_set_format(FAR struct v4l2_format *format) -{ - int ret; - int8_t max_fps; - struct v4l2_frmivalenum frmival; - isx012_modeparam_t mode_param; - FAR isx012_modeparam_t *current_param; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - ret = isx012_try_format(format); - if (ret < 0) - { - return ret; - } - - frmival.index = 0; - frmival.buf_type = format->type; - frmival.pixel_format = format->fmt.pix.pixelformat; - frmival.width = format->fmt.pix.width; - frmival.height = format->fmt.pix.height; - frmival.subimg_pixel_format = format->fmt.pix.subimg_pixelformat; - frmival.subimg_width = format->fmt.pix.subimg_width; - frmival.subimg_height = format->fmt.pix.subimg_height; - - max_fps = isx012_get_maximum_fps(&frmival); - if (max_fps < 0) - { - return max_fps; - } - - switch (format->type) - { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - current_param = &priv->param.video; - break; - - case V4L2_BUF_TYPE_STILL_CAPTURE: - current_param = &priv->param.still; - break; - - default: - return -EINVAL; - } - - memcpy(&mode_param, current_param, sizeof(mode_param)); - - mode_param.format = format->fmt.pix.pixelformat; - mode_param.hsize = format->fmt.pix.width; - mode_param.vsize = format->fmt.pix.height; - mode_param.int_hsize = format->fmt.pix.subimg_width; - mode_param.int_vsize = format->fmt.pix.subimg_height; - - if (mode_param.fps < max_fps) - { - mode_param.fps = max_fps; - } - - ret = isx012_set_mode_param(priv, - format->type, - &mode_param); - if (ret != OK) - { - return ret; - } - - memcpy(current_param, &mode_param, sizeof(mode_param)); - - return OK; -} - -static int isx012_set_supported_frminterval(uint32_t fps_index, - FAR struct v4l2_fract *interval) -{ - switch (fps_index) - { - case REGVAL_FPSTYPE_120FPS: - interval->numerator = 1; - interval->denominator = 120; - - break; - - case REGVAL_FPSTYPE_60FPS: - interval->numerator = 1; - interval->denominator = 60; - - break; - - case REGVAL_FPSTYPE_30FPS: - interval->numerator = 1; - interval->denominator = 30; - - break; - - case REGVAL_FPSTYPE_15FPS: - interval->numerator = 1; - interval->denominator = 15; - - break; - - case REGVAL_FPSTYPE_7_5FPS: - interval->numerator = 2; - interval->denominator = 15; - - break; - - case REGVAL_FPSTYPE_6FPS: - interval->numerator = 1; - interval->denominator = 6; - - break; - - case REGVAL_FPSTYPE_5FPS: - interval->numerator = 1; - interval->denominator = 5; - - break; - - default: - return -EINVAL; - } - - return OK; -} - -static int8_t isx012_get_maximum_fps(FAR struct v4l2_frmivalenum *frmival) -{ - int ret; - uint8_t max_fps = REGVAL_FPSTYPE_120FPS; - - if (frmival == NULL) - { - return -EINVAL; - } - - ret = isx012_check_fmt(frmival->buf_type, frmival->pixel_format); - if (ret != OK) - { - return ret; - } - - switch (frmival->pixel_format) - { - case V4L2_PIX_FMT_UYVY: /* YUV 4:2:2 */ - if ((frmival->width < OUT_YUV_HSIZE_MIN) || - (frmival->height < OUT_YUV_VSIZE_MIN) || - (frmival->width > OUT_YUV_15FPS_HSIZE_MAX) || - (frmival->height > OUT_YUV_15FPS_VSIZE_MAX)) - { - /* IN frame size is out of range */ - - return -EINVAL; - } - else if ((frmival->width <= OUT_YUV_120FPS_HSIZE_MAX) && - (frmival->height <= OUT_YUV_120FPS_VSIZE_MAX)) - { - /* support 120FPS, 60FPS, 30FPS, 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_120FPS; - } - else - { - /* support 60FPS, 30FPS, 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_60FPS; - } - - break; - - case V4L2_PIX_FMT_JPEG: /* JPEG */ - if ((frmival->width < OUT_JPG_HSIZE_MIN) || - (frmival->height < OUT_JPG_VSIZE_MIN) || - (frmival->width > OUT_JPG_15FPS_HSIZE_MAX) || - (frmival->height > OUT_JPG_15FPS_VSIZE_MAX)) - { - /* IN frame size is out of range */ - - return -EINVAL; - } - else if ((frmival->width <= OUT_JPG_120FPS_HSIZE_MAX) && - (frmival->height <= OUT_JPG_120FPS_VSIZE_MAX)) - { - /* support 120FPS, 60FPS, 30FPS, 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_120FPS; - } - else if ((frmival->width <= OUT_JPG_60FPS_HSIZE_MAX) && - (frmival->height <= OUT_JPG_60FPS_VSIZE_MAX)) - { - /* support 60FPS, 30FPS, 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_60FPS; - } - else if ((frmival->width <= OUT_JPG_30FPS_HSIZE_MAX) && - (frmival->height <= OUT_JPG_30FPS_VSIZE_MAX)) - { - /* support 30FPS, 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_30FPS; - } - else - { - /* support 15FPS, 7.5FPS, 6FPS, and 5FPS */ - - max_fps = REGVAL_FPSTYPE_15FPS; - } - - break; - - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + YUV 4:2:2 */ - if (frmival->subimg_pixel_format != V4L2_PIX_FMT_UYVY) - { - /* Unsupported pixel format */ - - return -EINVAL; - } - - if ((frmival->width < OUT_JPG_HSIZE_MIN) || - (frmival->height < OUT_JPG_VSIZE_MIN) || - (frmival->width > OUT_JPGINT_15FPS_HSIZE_MAX) || - (frmival->height > OUT_JPGINT_15FPS_VSIZE_MAX) || - (frmival->subimg_width < OUT_YUV_HSIZE_MIN) || - (frmival->subimg_height < OUT_YUV_VSIZE_MIN) || - (frmival->subimg_width > OUT_YUVINT_30FPS_HSIZE_MAX) || - (frmival->subimg_height > OUT_YUVINT_30FPS_VSIZE_MAX)) - { - /* IN frame size is out of range */ - - return -EINVAL; - } - else if ((frmival->width <= OUT_JPGINT_30FPS_HSIZE_MAX) && - (frmival->height <= OUT_JPGINT_30FPS_VSIZE_MAX)) - { - /* support 30FPS, 15FPS, 7.5FPS, 6FPS, 5FPS */ - - max_fps = REGVAL_FPSTYPE_30FPS; - } - else - { - /* support 15FPS, 7.5FPS, 6FPS, 5FPS */ - - max_fps = REGVAL_FPSTYPE_15FPS; - } - - break; - - default: - return -EINVAL; - } - - return (int8_t)max_fps; -} - -static int isx012_get_range_of_frameinterval - (FAR struct v4l2_frmivalenum *frmival) -{ - int ret; - int8_t max_fps; - - max_fps = isx012_get_maximum_fps(frmival); - if (max_fps < 0) - { - return max_fps; - } - - frmival->type = V4L2_FRMIVAL_TYPE_DISCRETE; - ret = isx012_set_supported_frminterval(frmival->index + max_fps, - &frmival->discrete); - return ret; -} - -static int isx012_change_fraction_to_fps(FAR struct v4l2_fract *interval) -{ - if (interval->denominator == interval->numerator * 120) /* 120FPS */ - { - return REGVAL_FPSTYPE_120FPS; - } - else if(interval->denominator == interval->numerator * 60) /* 60FPS */ - { - return REGVAL_FPSTYPE_60FPS; - } - else if(interval->denominator == interval->numerator * 30) /* 30FPS */ - { - return REGVAL_FPSTYPE_30FPS; - } - else if(interval->denominator == interval->numerator * 15) /* 15FPS */ - { - return REGVAL_FPSTYPE_15FPS; - } - else if(interval->denominator * 10 == interval->numerator * 75) /* 7.5FPS */ - { - return REGVAL_FPSTYPE_7_5FPS; - } - else if(interval->denominator == interval->numerator * 6) /* 6FPS */ - { - return REGVAL_FPSTYPE_6FPS; - } - else if(interval->denominator == interval->numerator * 5) /* 5FPS */ - { - return REGVAL_FPSTYPE_5FPS; - } - else - { - return -EINVAL; - } -} - -static int isx012_set_frameinterval(FAR struct v4l2_streamparm *parm) -{ - int ret; - int8_t fps; - int8_t max_fps; - isx012_modeparam_t mode_param; - FAR isx012_modeparam_t *current_param; - struct v4l2_frmivalenum frmival; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - fps = isx012_change_fraction_to_fps(&parm->parm.capture.timeperframe); - if (fps < 0) - { - return fps; - } - - frmival.buf_type = parm->type; - switch (frmival.buf_type) - { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - current_param = &priv->param.video; - break; - - case V4L2_BUF_TYPE_STILL_CAPTURE: - current_param = &priv->param.still; - break; - - default: - return -EINVAL; - } - - memcpy(&mode_param, current_param, sizeof(mode_param)); - - /* Get maximum fps settable value in current image format */ - - frmival.pixel_format = mode_param.format; - frmival.height = mode_param.vsize; - frmival.width = mode_param.hsize; - frmival.subimg_pixel_format = V4L2_PIX_FMT_UYVY; - frmival.subimg_height = mode_param.int_vsize; - frmival.subimg_width = mode_param.int_hsize; - max_fps = isx012_get_maximum_fps(&frmival); - if (max_fps < 0) - { - return fps; - } - - if (fps < max_fps) - { - return -EINVAL; - } - - mode_param.fps = fps; - - ret = isx012_set_mode_param(priv, - parm->type, - &mode_param); - if (ret != OK) - { - return ret; - } - - memcpy(current_param, &mode_param, sizeof(mode_param)); - - return OK; -} - -static int isx012_get_range_of_ctrlval(FAR struct v4l2_query_ext_ctrl *range) -{ - if (range == NULL) - { - return -EINVAL; - } - - switch (range->ctrl_class) - { - case V4L2_CTRL_CLASS_USER: - switch (range->id) - { - case V4L2_CID_BRIGHTNESS: - range->type = ISX012_TYPE_BRIGHTNESS; - range->minimum = ISX012_MIN_BRIGHTNESS; - range->maximum = ISX012_MAX_BRIGHTNESS; - range->step = ISX012_STEP_BRIGHTNESS; - range->default_value = ISX012_DEF_BRIGHTNESS; - strncpy(range->name, - ISX012_NAME_BRIGHTNESS, - sizeof(range->name)); - - break; - - case V4L2_CID_CONTRAST: - range->type = ISX012_TYPE_CONTRAST; - range->minimum = ISX012_MIN_CONTRAST; - range->maximum = ISX012_MAX_CONTRAST; - range->step = ISX012_STEP_CONTRAST; - range->default_value = ISX012_DEF_CONTRAST; - strncpy(range->name, - ISX012_NAME_CONTRAST, - sizeof(range->name)); - - break; - - case V4L2_CID_SATURATION: - range->type = ISX012_TYPE_SATURATION; - range->minimum = ISX012_MIN_SATURATION; - range->maximum = ISX012_MAX_SATURATION; - range->step = ISX012_STEP_SATURATION; - range->default_value = ISX012_DEF_SATURATION; - strncpy(range->name, - ISX012_NAME_SATURATION, - sizeof(range->name)); - - break; - - case V4L2_CID_HUE: - range->type = ISX012_TYPE_HUE; - range->minimum = ISX012_MIN_HUE; - range->maximum = ISX012_MAX_HUE; - range->step = ISX012_STEP_HUE; - range->default_value = ISX012_DEF_HUE; - strncpy(range->name, - ISX012_NAME_HUE, - sizeof(range->name)); - - break; - - case V4L2_CID_AUTO_WHITE_BALANCE: - range->type = ISX012_TYPE_AUTOWB; - range->minimum = ISX012_MIN_AUTOWB; - range->maximum = ISX012_MAX_AUTOWB; - range->step = ISX012_STEP_AUTOWB; - range->default_value = ISX012_DEF_AUTOWB; - strncpy(range->name, - ISX012_NAME_AUTOWB, - sizeof(range->name)); - - break; - case V4L2_CID_GAMMA_CURVE: - range->type = ISX012_TYPE_GAMMACURVE; - range->minimum = ISX012_MIN_GAMMACURVE; - range->maximum = ISX012_MAX_GAMMACURVE; - range->step = ISX012_STEP_GAMMACURVE; - range->default_value = ISX012_DEF_GAMMACURVE; - strncpy(range->name, - ISX012_NAME_GAMMACURVE, - sizeof(range->name)); - - break; - - case V4L2_CID_EXPOSURE: - range->type = ISX012_TYPE_EXPOSURE; - range->minimum = ISX012_MIN_EXPOSURE; - range->maximum = ISX012_MAX_EXPOSURE; - range->step = ISX012_STEP_EXPOSURE; - range->default_value = ISX012_DEF_EXPOSURE; - strncpy(range->name, - ISX012_NAME_EXPOSURE, - sizeof(range->name)); - - break; - - case V4L2_CID_HFLIP: - range->type = ISX012_TYPE_HFLIP; - range->minimum = ISX012_MIN_HFLIP; - range->maximum = ISX012_MAX_HFLIP; - range->step = ISX012_STEP_HFLIP; - range->default_value = ISX012_DEF_HFLIP; - strncpy(range->name, - ISX012_NAME_HFLIP, - sizeof(range->name)); - - break; - - case V4L2_CID_VFLIP: - range->type = ISX012_TYPE_VFLIP; - range->minimum = ISX012_MIN_VFLIP; - range->maximum = ISX012_MAX_VFLIP; - range->step = ISX012_STEP_VFLIP; - range->default_value = ISX012_DEF_VFLIP; - strncpy(range->name, - ISX012_NAME_VFLIP, - sizeof(range->name)); - - break; - - case V4L2_CID_HFLIP_STILL: - range->type = ISX012_TYPE_HFLIP_STILL; - range->minimum = ISX012_MIN_HFLIP_STILL; - range->maximum = ISX012_MAX_HFLIP_STILL; - range->step = ISX012_STEP_HFLIP_STILL; - range->default_value = ISX012_DEF_HFLIP_STILL; - strncpy(range->name, - ISX012_NAME_HFLIP_STILL, - sizeof(range->name)); - - break; - - case V4L2_CID_VFLIP_STILL: - range->type = ISX012_TYPE_VFLIP_STILL; - range->minimum = ISX012_MIN_VFLIP_STILL; - range->maximum = ISX012_MAX_VFLIP_STILL; - range->step = ISX012_STEP_VFLIP_STILL; - range->default_value = ISX012_DEF_VFLIP_STILL; - strncpy(range->name, - ISX012_NAME_VFLIP_STILL, - sizeof(range->name)); - - break; - - case V4L2_CID_SHARPNESS: - range->type = ISX012_TYPE_SHARPNESS; - range->minimum = ISX012_MIN_SHARPNESS; - range->maximum = ISX012_MAX_SHARPNESS; - range->step = ISX012_STEP_SHARPNESS; - range->default_value = ISX012_DEF_SHARPNESS; - strncpy(range->name, - ISX012_NAME_SHARPNESS, - sizeof(range->name)); - - break; - - case V4L2_CID_COLOR_KILLER: - range->type = ISX012_TYPE_COLORKILLER; - range->minimum = ISX012_MIN_COLORKILLER; - range->maximum = ISX012_MAX_COLORKILLER; - range->step = ISX012_STEP_COLORKILLER; - range->default_value = ISX012_DEF_COLORKILLER; - strncpy(range->name, - ISX012_NAME_COLORKILLER, - sizeof(range->name)); - - break; - - case V4L2_CID_COLORFX: - range->type = ISX012_TYPE_COLOREFFECT; - range->minimum = ISX012_MIN_COLOREFFECT; - range->maximum = ISX012_MAX_COLOREFFECT; - range->step = ISX012_STEP_COLOREFFECT; - range->default_value = ISX012_DEF_COLOREFFECT; - strncpy(range->name, - ISX012_NAME_COLOREFFECT, - sizeof(range->name)); - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_CAMERA: - switch (range->id) - { - case V4L2_CID_EXPOSURE_AUTO: - range->type = ISX012_TYPE_EXPOSUREAUTO; - range->minimum = ISX012_MIN_EXPOSUREAUTO; - range->maximum = ISX012_MAX_EXPOSUREAUTO; - range->step = ISX012_STEP_EXPOSUREAUTO; - range->default_value = ISX012_DEF_EXPOSUREAUTO; - strncpy(range->name, - ISX012_NAME_EXPOSUREAUTO, - sizeof(range->name)); - - break; - - case V4L2_CID_EXPOSURE_ABSOLUTE: - range->type = ISX012_TYPE_EXPOSURETIME; - range->minimum = ISX012_MIN_EXPOSURETIME; - range->maximum = ISX012_MAX_EXPOSURETIME; - range->step = ISX012_STEP_EXPOSURETIME; - range->default_value = ISX012_DEF_EXPOSURETIME; - strncpy(range->name, - ISX012_NAME_EXPOSURETIME, - sizeof(range->name)); - - break; - - case V4L2_CID_EXPOSURE_METERING: - range->type = ISX012_TYPE_PHOTOMETRY; - range->minimum = ISX012_MIN_PHOTOMETRY; - range->maximum = ISX012_MAX_PHOTOMETRY; - range->step = ISX012_STEP_PHOTOMETRY; - range->default_value = ISX012_DEF_PHOTOMETRY; - strncpy(range->name, - ISX012_NAME_PHOTOMETRY, - sizeof(range->name)); - - break; - - case V4L2_CID_ZOOM_ABSOLUTE: - range->type = ISX012_TYPE_ZOOM; - range->minimum = ISX012_MIN_ZOOM; - range->maximum = ISX012_MAX_ZOOM; - range->step = ISX012_STEP_ZOOM; - range->default_value = ISX012_DEF_ZOOM; - strncpy(range->name, - ISX012_NAME_ZOOM, - sizeof(range->name)); - - break; - - case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: - range->type = ISX012_TYPE_PRESETWB; - range->minimum = ISX012_MIN_PRESETWB; - range->maximum = ISX012_MAX_PRESETWB; - range->step = ISX012_STEP_PRESETWB; - range->default_value = ISX012_DEF_PRESETWB; - strncpy(range->name, - ISX012_NAME_PRESETWB, - sizeof(range->name)); - - break; - - case V4L2_CID_WIDE_DYNAMIC_RANGE: - range->type = ISX012_TYPE_YGAMMA; - range->minimum = ISX012_MIN_YGAMMA; - range->maximum = ISX012_MAX_YGAMMA; - range->step = ISX012_STEP_YGAMMA; - range->default_value = ISX012_DEF_YGAMMA; - strncpy(range->name, - ISX012_NAME_YGAMMA, - sizeof(range->name)); - - break; - - case V4L2_CID_ISO_SENSITIVITY: - range->type = ISX012_TYPE_ISO; - range->minimum = ISX012_MIN_ISO; - range->maximum = ISX012_MAX_ISO; - range->step = ISX012_STEP_ISO; - range->default_value = ISX012_DEF_ISO; - strncpy(range->name, - ISX012_NAME_ISO, - sizeof(range->name)); - - break; - - case V4L2_CID_ISO_SENSITIVITY_AUTO: - range->type = ISX012_TYPE_ISOAUTO; - range->minimum = ISX012_MIN_ISOAUTO; - range->maximum = ISX012_MAX_ISOAUTO; - range->step = ISX012_STEP_ISOAUTO; - range->default_value = ISX012_DEF_ISOAUTO; - strncpy(range->name, - ISX012_NAME_ISOAUTO, - sizeof(range->name)); - - break; - - case V4L2_CID_3A_LOCK: - range->type = ISX012_TYPE_3ALOCK; - range->minimum = ISX012_MIN_3ALOCK; - range->maximum = ISX012_MAX_3ALOCK; - range->step = ISX012_STEP_3ALOCK; - range->default_value = ISX012_DEF_3ALOCK; - strncpy(range->name, - ISX012_NAME_3ALOCK, - sizeof(range->name)); - - break; - - case V4L2_CID_3A_PARAMETER: - range->type = V4L2_CTRL_TYPE_U16; - range->minimum = 0; - range->maximum = 65535; - range->step = 1; - range->elems = 3; - strncpy(range->name, - "AWB/AE parameter", - sizeof(range->name)); - - break; - - case V4L2_CID_3A_STATUS: - range->type = V4L2_CTRL_TYPE_INTEGER; - range->minimum = 0; - range->maximum = 3; - range->step = 1; - strncpy(range->name, - "AWB/AE status", - sizeof(range->name)); - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_JPEG: - switch (range->id) - { - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - range->type = ISX012_TYPE_JPGQUALITY; - range->minimum = ISX012_MIN_JPGQUALITY; - range->maximum = ISX012_MAX_JPGQUALITY; - range->step = ISX012_STEP_JPGQUALITY; - range->default_value = ISX012_DEF_JPGQUALITY; - strncpy(range->name, - ISX012_NAME_JPGQUALITY, - sizeof(range->name)); - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - default: /* Unsupported control class */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_get_menu_of_ctrlval(FAR struct v4l2_querymenu *menu) -{ - if (menu == NULL) - { - return -EINVAL; - } - - switch (menu->ctrl_class) - { - case V4L2_CTRL_CLASS_USER: - switch (menu->id) - { - case V4L2_CID_COLORFX: - if (menu->index > ISX012_MAX_COLOREFFECT) - { - return -EINVAL; - } - - menu->value = g_isx012_supported_colorfx[menu->index].v4l2; - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_CAMERA: - switch (menu->id) - { - case V4L2_CID_EXPOSURE_METERING: - if (menu->index > ISX012_MAX_PHOTOMETRY) - { - return -EINVAL; - } - - menu->value = g_isx012_supported_photometry[menu->index].v4l2; - - break; - - case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: - if (menu->index > ISX012_MAX_PRESETWB) - { - return -EINVAL; - } - - menu->value = g_isx012_supported_presetwb[menu->index].v4l2; - - break; - - case V4L2_CID_ISO_SENSITIVITY: - if (menu->index > ISX012_MAX_ISO) - { - return -EINVAL; - } - - menu->value = g_isx012_supported_iso[menu->index].v4l2; - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - default: /* Unsupported control class */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_get_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - int16_t readvalue; - uint8_t cnt; - uint8_t threea_enable; - uint16_t read_src; - uint16_t *read_dst; - int ret = -EINVAL; - - if (control == NULL) - { - return -EINVAL; - } - - switch (ctrl_class) - { - case V4L2_CTRL_CLASS_USER: - switch (control->id) - { - case V4L2_CID_BRIGHTNESS: - control->value = isx012_getreg(priv, - ISX012_REG_BRIGHTNESS, - ISX012_SIZE_BRIGHTNESS); - break; - - case V4L2_CID_CONTRAST: - control->value = isx012_getreg(priv, - ISX012_REG_CONTRAST, - ISX012_SIZE_CONTRAST); - break; - - case V4L2_CID_SATURATION: - control->value = isx012_getreg(priv, - ISX012_REG_SATURATION, - ISX012_SIZE_SATURATION); - break; - - case V4L2_CID_HUE: - control->value = isx012_getreg(priv, - ISX012_REG_HUE, - ISX012_SIZE_HUE); - break; - - case V4L2_CID_AUTO_WHITE_BALANCE: - readvalue = isx012_getreg(priv, - ISX012_REG_AUTOWB, - ISX012_SIZE_AUTOWB); - - /* Convert to V4L2 value */ - - if (readvalue & REGVAL_CPUEXT_BIT_AWBSTOP) - { - control->value = false; - } - else - { - control->value = true; - } - - break; - - case V4L2_CID_GAMMA_CURVE: - if (control->p_u16 == NULL) - { - return -EINVAL; - } - - read_src = ISX012_REG_GAMMACURVE; - read_dst = control->p_u16; - - for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) - { - *read_dst = isx012_getreg(priv, - read_src, - ISX012_SIZE_GAMMACURVE); - read_src += ISX012_SIZE_GAMMACURVE; - read_dst++; - } - - break; - - case V4L2_CID_EXPOSURE: - control->value = isx012_getreg(priv, - ISX012_REG_EXPOSURE, - ISX012_SIZE_EXPOSURE); - break; - - case V4L2_CID_HFLIP: - readvalue = isx012_getreg(priv, - ISX012_REG_HFLIP, - ISX012_SIZE_HFLIP); - - if (readvalue & REGVAL_READVECT_BIT_H) - { - control->value = true; - } - else - { - control->value = false; - } - - break; - - case V4L2_CID_VFLIP: - readvalue = isx012_getreg(priv, - ISX012_REG_VFLIP, - ISX012_SIZE_VFLIP); - - if (readvalue & REGVAL_READVECT_BIT_V) - { - control->value = true; - } - else - { - control->value = false; - } - - break; - - case V4L2_CID_HFLIP_STILL: - readvalue = isx012_getreg(priv, - ISX012_REG_HFLIP_STILL, - ISX012_SIZE_HFLIP_STILL); - - if (readvalue & REGVAL_READVECT_BIT_H) - { - control->value = true; - } - else - { - control->value = false; - } - - break; - - case V4L2_CID_VFLIP_STILL: - readvalue = isx012_getreg(priv, - ISX012_REG_VFLIP_STILL, - ISX012_SIZE_VFLIP_STILL); - - if (readvalue & REGVAL_READVECT_BIT_V) - { - control->value = true; - } - else - { - control->value = false; - } - - break; - - case V4L2_CID_SHARPNESS: - control->value = isx012_getreg(priv, - ISX012_REG_SHARPNESS, - ISX012_SIZE_SHARPNESS); - break; - - case V4L2_CID_COLOR_KILLER: - readvalue = isx012_getreg(priv, - ISX012_REG_COLORKILLER, - ISX012_SIZE_COLORKILLER); - - if (readvalue == REGVAL_EFFECT_MONOTONE) - { - control->value = true; - } - else - { - control->value = false; - } - - break; - - case V4L2_CID_COLORFX: - readvalue = isx012_getreg(priv, - ISX012_REG_COLOREFFECT, - ISX012_SIZE_COLOREFFECT); - - for (cnt = 0; cnt <= ISX012_MAX_COLOREFFECT; cnt++) - { - if (g_isx012_supported_colorfx[cnt].regval == readvalue) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - control->value = g_isx012_supported_colorfx[cnt].v4l2; - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_CAMERA: - switch (control->id) - { - case V4L2_CID_EXPOSURE_AUTO: - readvalue = isx012_getreg(priv, - ISX012_REG_EXPOSURETIME, - ISX012_SIZE_EXPOSURETIME); - - if (readvalue) - { - control->value = V4L2_EXPOSURE_MANUAL; - } - else - { - control->value = V4L2_EXPOSURE_AUTO; - } - - break; - - case V4L2_CID_EXPOSURE_ABSOLUTE: - control->value = isx012_getreg(priv, - ISX012_REG_EXPOSURETIME, - ISX012_SIZE_EXPOSURETIME); - - break; - - case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: - readvalue = isx012_getreg(priv, - ISX012_REG_PRESETWB, - ISX012_SIZE_PRESETWB); - - for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) - { - if (g_isx012_supported_presetwb[cnt].regval == readvalue) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - control->value = g_isx012_supported_presetwb[cnt].v4l2; - - break; - - case V4L2_CID_WIDE_DYNAMIC_RANGE: - readvalue = isx012_getreg(priv, - ISX012_REG_YGAMMA, - ISX012_SIZE_YGAMMA); - if (readvalue) - { - control->value = false; - } - else - { - control->value = true; - } - - break; - - case V4L2_CID_ISO_SENSITIVITY: - readvalue = isx012_getreg(priv, - ISX012_REG_ISO, - ISX012_SIZE_ISO); - - for (cnt = 0; cnt <= ISX012_MAX_ISO; cnt++) - { - if (g_isx012_supported_iso[cnt].regval == readvalue) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - control->value = g_isx012_supported_iso[cnt].v4l2; - - break; - - case V4L2_CID_ISO_SENSITIVITY_AUTO: - readvalue = isx012_getreg(priv, - ISX012_REG_ISOAUTO, - ISX012_SIZE_ISOAUTO); - if (readvalue == REGVAL_ISO_AUTO) - { - control->value = V4L2_ISO_SENSITIVITY_AUTO; - } - else - { - control->value = V4L2_ISO_SENSITIVITY_MANUAL; - } - break; - - case V4L2_CID_EXPOSURE_METERING: - readvalue = isx012_getreg(priv, - ISX012_REG_PHOTOMETRY, - ISX012_SIZE_PHOTOMETRY); - - for (cnt = 0; cnt <= ISX012_MAX_PHOTOMETRY; cnt++) - { - if (g_isx012_supported_photometry[cnt].regval == readvalue) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - control->value = g_isx012_supported_photometry[cnt].v4l2; - - break; - - case V4L2_CID_3A_PARAMETER: - if (control->p_u16 == NULL) - { - return -EINVAL; - } - - /* Get AWB parameter */ - - control->p_u16[0] = isx012_getreg(priv, - RATIO_R, - 2); - control->p_u16[1] = isx012_getreg(priv, - RATIO_B, - 2); - - /* Get AE parameter */ - - control->p_u16[2] = isx012_getreg(priv, - AELEVEL, - 2); - - break; - - case V4L2_CID_3A_STATUS: - - /* Initialize returned status */ - - control->value = V4L2_3A_STATUS_STABLE; - - /* Get AWB/AE enable or not */ - - threea_enable = isx012_getreg(priv, - CPUEXT, - 1); - - /* Check AWB */ - - if ((threea_enable & REGVAL_CPUEXT_BIT_AWBSTOP) - != REGVAL_CPUEXT_BIT_AWBSTOP) - { - /* Check AWB status */ - - readvalue = isx012_getreg(priv, - AWBSTS, - 1); - if (readvalue != REGVAL_AWBSTS_STOP) /* AWB is not stopped */ - { - control->value |= V4L2_3A_STATUS_AWB_OPERATING; - } - } - - /* Check AE */ - - if ((threea_enable & REGVAL_CPUEXT_BIT_AESTOP) - != REGVAL_CPUEXT_BIT_AESTOP) - { - /* Check AE status */ - - readvalue = isx012_getreg(priv, - AESTS, - 1); - if (readvalue != REGVAL_AESTS_STOP) /* AE is not stopped */ - { - control->value |= V4L2_3A_STATUS_AE_OPERATING; - } - } - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_JPEG: - switch (control->id) - { - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - control->value = isx012_getreg(priv, - ISX012_REG_JPGQUALITY, - ISX012_SIZE_JPGQUALITY); - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - default: /* Unsupported control class */ - - return -EINVAL; - } - - return OK; -} - -static int isx012_set_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - int ret = -EINVAL; - uint8_t cnt; - uint16_t *write_src; - uint16_t write_dst; - uint16_t regval; - uint16_t exposure_time_lsb; - uint16_t exposure_time_msb; - - if (control == NULL) - { - return -EINVAL; - } - - switch (ctrl_class) - { - case V4L2_CTRL_CLASS_USER: - switch (control->id) - { - case V4L2_CID_BRIGHTNESS: - CHECK_RANGE(control->value, - ISX012_MIN_BRIGHTNESS, - ISX012_MAX_BRIGHTNESS, - ISX012_STEP_BRIGHTNESS); - - ret = isx012_putreg(priv, - ISX012_REG_BRIGHTNESS, - control->value, - ISX012_SIZE_BRIGHTNESS); - - break; - - case V4L2_CID_CONTRAST: - CHECK_RANGE(control->value, - ISX012_MIN_CONTRAST, - ISX012_MAX_CONTRAST, - ISX012_STEP_CONTRAST); - - ret = isx012_putreg(priv, - ISX012_REG_CONTRAST, - control->value, - ISX012_SIZE_CONTRAST); - - break; - - case V4L2_CID_SATURATION: - CHECK_RANGE(control->value, - ISX012_MIN_SATURATION, - ISX012_MAX_SATURATION, - ISX012_STEP_SATURATION); - - ret = isx012_putreg(priv, - ISX012_REG_SATURATION, - control->value, - ISX012_SIZE_SATURATION); - - break; - - case V4L2_CID_HUE: - CHECK_RANGE(control->value, - ISX012_MIN_HUE, - ISX012_MAX_HUE, - ISX012_STEP_HUE); - - ret = isx012_putreg(priv, - ISX012_REG_HUE, - control->value, - ISX012_SIZE_HUE); - - break; - - case V4L2_CID_AUTO_WHITE_BALANCE: - CHECK_RANGE(control->value, - ISX012_MIN_AUTOWB, - ISX012_MAX_AUTOWB, - ISX012_STEP_AUTOWB); - - regval = isx012_getreg(priv, - ISX012_REG_AUTOWB, - ISX012_SIZE_AUTOWB); - - if (control->value) - { - /* Because true means setting auto white balance - * turn off the stop bit - */ - - regval &= ~REGVAL_CPUEXT_BIT_AWBSTOP; - } - else - { - /* Because false means stopping auto white balance, - * turn on the stop bit. - */ - - regval |= REGVAL_CPUEXT_BIT_AWBSTOP; - } - - ret = isx012_putreg(priv, - ISX012_REG_AUTOWB, - regval, - ISX012_SIZE_AUTOWB); - - break; - - case V4L2_CID_GAMMA_CURVE: - if (control->p_u16 == NULL) - { - return -EINVAL; - } - - write_src = control->p_u16; - write_dst = ISX012_REG_GAMMACURVE; - - for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) - { - CHECK_RANGE(*write_src, - ISX012_MIN_GAMMACURVE, - ISX012_MAX_GAMMACURVE, - ISX012_STEP_GAMMACURVE); - - ret = isx012_putreg(priv, - write_dst, - *write_src, - ISX012_SIZE_GAMMACURVE); - - write_src++; - write_dst += ISX012_SIZE_GAMMACURVE; - } - - break; - - case V4L2_CID_EXPOSURE: - CHECK_RANGE(control->value, - ISX012_MIN_EXPOSURE, - ISX012_MAX_EXPOSURE, - ISX012_STEP_EXPOSURE); - - ret = isx012_putreg(priv, - ISX012_REG_EXPOSURE, - control->value, - ISX012_SIZE_EXPOSURE); - - break; - - case V4L2_CID_HFLIP: - CHECK_RANGE(control->value, - ISX012_MIN_HFLIP, - ISX012_MAX_HFLIP, - ISX012_STEP_HFLIP); - - regval = isx012_getreg(priv, - ISX012_REG_HFLIP, - ISX012_SIZE_HFLIP); - - if (control->value) - { - regval |= REGVAL_READVECT_BIT_H; - } - else - { - regval &= ~REGVAL_READVECT_BIT_H; - } - - ret = isx012_putreg(priv, - ISX012_REG_HFLIP, - regval, - ISX012_SIZE_HFLIP); - - break; - - case V4L2_CID_VFLIP: - CHECK_RANGE(control->value, - ISX012_MIN_VFLIP, - ISX012_MAX_VFLIP, - ISX012_STEP_VFLIP); - - regval = isx012_getreg(priv, - ISX012_REG_VFLIP, - ISX012_SIZE_VFLIP); - - if (control->value) - { - regval |= REGVAL_READVECT_BIT_V; - } - else - { - regval &= ~REGVAL_READVECT_BIT_V; - } - - ret = isx012_putreg(priv, - ISX012_REG_VFLIP, - regval, - ISX012_SIZE_VFLIP); - - break; - - case V4L2_CID_HFLIP_STILL: - CHECK_RANGE(control->value, - ISX012_MIN_HFLIP_STILL, - ISX012_MAX_HFLIP_STILL, - ISX012_STEP_HFLIP_STILL); - - regval = isx012_getreg(priv, - ISX012_REG_HFLIP_STILL, - ISX012_SIZE_HFLIP_STILL); - - if (control->value) - { - regval |= REGVAL_READVECT_BIT_H; - } - else - { - regval &= ~REGVAL_READVECT_BIT_H; - } - - ret = isx012_putreg(priv, - ISX012_REG_HFLIP_STILL, - regval, - ISX012_SIZE_HFLIP_STILL); - - break; - - case V4L2_CID_VFLIP_STILL: - CHECK_RANGE(control->value, - ISX012_MIN_VFLIP_STILL, - ISX012_MAX_VFLIP_STILL, - ISX012_STEP_VFLIP_STILL); - - regval = isx012_getreg(priv, - ISX012_REG_VFLIP_STILL, - ISX012_SIZE_VFLIP_STILL); - - if (control->value) - { - regval |= REGVAL_READVECT_BIT_V; - } - else - { - regval &= ~REGVAL_READVECT_BIT_V; - } - - ret = isx012_putreg(priv, - ISX012_REG_VFLIP_STILL, - regval, - ISX012_SIZE_VFLIP_STILL); - - break; - - case V4L2_CID_SHARPNESS: - CHECK_RANGE(control->value, - ISX012_MIN_SHARPNESS, - ISX012_MAX_SHARPNESS, - ISX012_STEP_SHARPNESS); - - ret = isx012_putreg(priv, - ISX012_REG_SHARPNESS, - control->value, - ISX012_SIZE_SHARPNESS); - - break; - - case V4L2_CID_COLOR_KILLER: - CHECK_RANGE(control->value, - ISX012_MIN_COLORKILLER, - ISX012_MAX_COLORKILLER, - ISX012_STEP_COLORKILLER); - - if (control->value) - { - regval = REGVAL_EFFECT_MONOTONE; - } - else - { - regval = REGVAL_EFFECT_NONE; - } - - ret = isx012_putreg(priv, - ISX012_REG_COLORKILLER, - regval, - ISX012_SIZE_COLORKILLER); - - break; - - case V4L2_CID_COLORFX: - for (cnt = 0; cnt <= ISX012_MAX_COLOREFFECT; cnt++) - { - if (g_isx012_supported_colorfx[cnt].v4l2 == control->value) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - ret = isx012_putreg(priv, - ISX012_REG_COLOREFFECT, - g_isx012_supported_colorfx[cnt].regval, - ISX012_SIZE_COLOREFFECT); - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_CAMERA: - switch (control->id) - { - case V4L2_CID_EXPOSURE_AUTO: - CHECK_RANGE(control->value, - ISX012_MIN_EXPOSUREAUTO, - ISX012_MAX_EXPOSUREAUTO, - ISX012_STEP_EXPOSUREAUTO); - - if (control->value == V4L2_EXPOSURE_AUTO) - { - /* Register is the same as V4L2_CID_EXPOSURE_ABSOLUTE. - * If this register value = REGVAL_EXPOSURETIME_AUTO(=0), - * it means auto. Otherwise, it means manual. - */ - - ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, - REGVAL_EXPOSURETIME_AUTO, - ISX012_SIZE_EXPOSURETIME); - } - else - { - /* In manual case, read current value of register which - * value adjusted automatically by ISX012 HW is set to. - * It has 32bits length which is composed of LSB 16bits - * and MSB 16bits. - */ - - exposure_time_lsb = isx012_getreg - (priv, - ISX012_REG_EXPOSUREAUTOVALUE_LSB, - ISX012_SIZE_EXPOSUREAUTOVALUE); - exposure_time_msb = isx012_getreg - (priv, - ISX012_REG_EXPOSUREAUTOVALUE_MSB, - ISX012_SIZE_EXPOSUREAUTOVALUE); - - /* Register value adjusted automatically by ISX012 HW - * has the different unit from manual value register. - * automatic value register : 1 microsec unit - * manual value register : 100 microsec unit - */ - - regval = (uint16_t)(((exposure_time_msb << 16) - | exposure_time_lsb) - / ISX012_UNIT_EXPOSURETIME_US); - ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, - regval, - ISX012_SIZE_EXPOSURETIME); - } - - break; - - case V4L2_CID_EXPOSURE_ABSOLUTE: - CHECK_RANGE(control->value, - ISX012_MIN_EXPOSURETIME, - ISX012_MAX_EXPOSURETIME, - ISX012_STEP_EXPOSURETIME); - - ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, - control->value, - ISX012_SIZE_EXPOSURETIME); - break; - - case V4L2_CID_WIDE_DYNAMIC_RANGE: - CHECK_RANGE(control->value, - ISX012_MIN_YGAMMA, - ISX012_MAX_YGAMMA, - ISX012_STEP_YGAMMA); - - if (control->value) - { - regval = REGVAL_YGAMMA_AUTO; - } - else - { - regval = REGVAL_YGAMMA_OFF; - } - - ret = isx012_putreg(priv, - ISX012_REG_YGAMMA, - regval, - ISX012_SIZE_YGAMMA); - - break; - - case V4L2_CID_ISO_SENSITIVITY: - for (cnt = 0; cnt <= ISX012_MAX_ISO; cnt++) - { - if (g_isx012_supported_iso[cnt].v4l2 - == control->value) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - ret = isx012_putreg(priv, - ISX012_REG_ISO, - g_isx012_supported_iso[cnt].regval, - ISX012_SIZE_ISO); - - break; - - case V4L2_CID_ISO_SENSITIVITY_AUTO: - CHECK_RANGE(control->value, - ISX012_MIN_ISOAUTO, - ISX012_MAX_ISOAUTO, - ISX012_STEP_ISOAUTO); - - if (control->value == V4L2_ISO_SENSITIVITY_AUTO) - { - ret = isx012_putreg(priv, - ISX012_REG_ISOAUTO, - REGVAL_ISO_AUTO, - ISX012_SIZE_ISOAUTO); - } - else - { - /* In manual case, read auto adjust value and set it */ - - regval = isx012_getreg(priv, - ISX012_REG_ISOAUTOVALUE, - ISX012_SIZE_ISOAUTOVALUE); - ret = isx012_putreg(priv, - ISX012_REG_ISO, - regval, - ISX012_SIZE_ISO); - } - - break; - - case V4L2_CID_EXPOSURE_METERING: - for (cnt = 0; cnt <= ISX012_MAX_PHOTOMETRY; cnt++) - { - if (g_isx012_supported_photometry[cnt].v4l2 - == control->value) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - ret = isx012_putreg(priv, - ISX012_REG_PHOTOMETRY, - g_isx012_supported_photometry[cnt].regval, - ISX012_SIZE_PHOTOMETRY); - - break; - - case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: - for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) - { - if (g_isx012_supported_presetwb[cnt].v4l2 - == control->value) - { - ret = OK; - break; - } - } - - if (ret != OK) - { - return ret; - } - - ret = isx012_putreg(priv, - ISX012_REG_PRESETWB, - g_isx012_supported_presetwb[cnt].regval, - ISX012_SIZE_PRESETWB); - - break; - - case V4L2_CID_3A_LOCK: - CHECK_RANGE(control->value, - ISX012_MIN_3ALOCK, - ISX012_MAX_3ALOCK, - ISX012_STEP_3ALOCK); - - regval = 0; - - if ((control->value & V4L2_LOCK_EXPOSURE) - == V4L2_LOCK_EXPOSURE) - { - regval |= REGVAL_CPUEXT_BIT_AESTOP; - } - - if ((control->value & V4L2_LOCK_WHITE_BALANCE) - == V4L2_LOCK_WHITE_BALANCE) - { - regval |= REGVAL_CPUEXT_BIT_AWBSTOP; - } - - ret = isx012_putreg(priv, - ISX012_REG_3ALOCK, - regval, - ISX012_SIZE_3ALOCK); - - break; - - case V4L2_CID_3A_PARAMETER: - - /* AWB parameter : red */ - - ret = isx012_putreg(priv, - INIT_CONT_INR, - control->p_u16[0], - 2); - ret = isx012_putreg(priv, - INIT_CONT_OUTR, - control->p_u16[0], - 2); - - /* AWB parameter : blue */ - - ret = isx012_putreg(priv, - INIT_CONT_INB, - control->p_u16[1], - 2); - ret = isx012_putreg(priv, - INIT_CONT_OUTB, - control->p_u16[1], - 2); - - /* AE parameter */ - - ret = isx012_putreg(priv, - AE_START_LEVEL, - control->p_u16[2], - 2); - - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - case V4L2_CTRL_CLASS_JPEG: - switch (control->id) - { - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - CHECK_RANGE(control->value, - ISX012_MIN_JPGQUALITY, - ISX012_MAX_JPGQUALITY, - ISX012_STEP_JPGQUALITY); - - ret = isx012_putreg(priv, - ISX012_REG_JPGQUALITY, - control->value, - ISX012_SIZE_JPGQUALITY); - break; - - default: /* Unsupported control id */ - - return -EINVAL; - } - - break; - - default: /* Unsupported control class */ - - return -EINVAL; - } - - return ret; -} - -static int isx012_refresh(void) -{ - int ret = 0; - uint8_t mask_num; - int i; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - if (priv->state != STATE_ISX012_ACTIVE) - { - /* In inactive state, setting is reflected in activated timing */ - - return OK; - } - - if (priv->mode != REGVAL_MODESEL_MON) - { - return -EPERM; - } - - /* Set MONI_REFRESH */ - - isx012_putreg(priv, INTCLR0, CM_CHANGED_STS, 1); - ret = isx012_putreg(priv, MONI_REFRESH, 1, 1); - if (ret < 0) - { - return ret; - } - - /* Wait CM_CHANGED */ - - ret = isx012_chk_int_state(priv, CM_CHANGED_STS, - CAMERA_MODE_DELAY_TIME, - CAMERA_MODE_WAIT_TIME, - CAMERA_MODE_TIMEOUT); - if (ret != 0) - { - return ret; - } - - /* Invalid frame skip */ - - isx012_putreg(priv, INTCLR0, VINT_STS, 1); - mask_num = isx012_getreg(priv, RO_MASK_NUM, sizeof(mask_num)); - for (i = 0; i < mask_num; i++) - { - /* Wait Next VINT */ - - ret = isx012_chk_int_state(priv, VINT_STS, VINT_DELAY_TIME, - VINT_WAIT_TIME, VINT_TIMEOUT); - if (ret != 0) - { - return ret; - } - } - - return OK; -} - -static int isx012_set_shd(FAR isx012_dev_t *priv) -{ - int ret; - int unit_cnt; - int size_cnt; - - /* At first, disable CXC and SHD */ - - ret = isx012_putreg(priv, SHD_EN, 0x50, 1); - if (ret < 0) - { - imagererr("isx012_putreg(disable CXC/SHD) failed: %d\n", ret); - return ret; - } - - /* Set CXC Validity */ - - ret = isx012_putreg(priv, CXC_VALID, 0x8282, 2); - if (ret < 0) - { - imagererr("isx012_putreg(CXC_VALID) failed: %d\n", ret); - return ret; - } - - /* Set CXC R Gb data */ - - for (unit_cnt = 0; unit_cnt < CXC_RGB_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < CXC_RGB_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - CXC_RGB_UNIT(unit_cnt, size_cnt), - g_isx012_cxc_rgb_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(CXC R Gb) failed: %d\n", ret); - return ret; - } - } - } - - /* Set CXC G Rb data */ - - for (unit_cnt = 0; unit_cnt < CXC_GRB_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < CXC_GRB_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - CXC_GRB_UNIT(unit_cnt, size_cnt), - g_isx012_cxc_grb_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(CXC G Rb) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD Validity */ - - ret = isx012_putreg(priv, SHD_VALID, 0x9191, 2); - if (ret < 0) - { - imagererr("isx012_putreg(SHD_VALID) failed: %d\n", ret); - return ret; - } - - /* Set SHD R Gb data */ - - for (unit_cnt = 0; unit_cnt < SHD_RGB_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < SHD_RGB_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - SHD_RGB_UNIT(unit_cnt, size_cnt), - g_isx012_shd_rgb_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(SHD R Gb) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD G Rb data */ - - for (unit_cnt = 0; unit_cnt < SHD_GRB_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < SHD_GRB_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - SHD_GRB_UNIT(unit_cnt, size_cnt), - g_isx012_shd_grb_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(SHD G Rb) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD R1 data */ - - for (unit_cnt = 0; unit_cnt < SHD_R1_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < SHD_R1_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - SHD_R1_UNIT(unit_cnt, size_cnt), - g_isx012_shd_r1_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(SHD R1) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD R2 data */ - - for (unit_cnt = 0; unit_cnt < SHD_R2_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < SHD_R2_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - SHD_R2_UNIT(unit_cnt, size_cnt), - g_isx012_shd_r2_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(SHD R2) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD B2 data */ - - for (unit_cnt = 0; unit_cnt < SHD_B2_DATA_UNIT_NUM; unit_cnt++) - { - for (size_cnt = 0; size_cnt < SHD_B2_DATA_UNIT_SIZE; size_cnt++) - { - ret = isx012_putreg(priv, - SHD_B2_UNIT(unit_cnt, size_cnt), - g_isx012_shd_b2_data[unit_cnt][size_cnt], - 1); - if (ret < 0) - { - imagererr("isx012_putreg(SHD B2) failed: %d\n", ret); - return ret; - } - } - } - - /* Set SHD thresholds data */ - - ret = isx012_putreglist(priv, g_isx012_shd_thresholds, - ISX012_SHD_THRESHOLDS_NENTRIES); - if (ret < 0) - { - imagererr("isx012_putreglist failed(SHD thresholds): %d\n", ret); - board_isx012_set_reset(); - return ret; - } - - /* Set SHD white balance data */ - - ret = isx012_putreglist(priv, g_isx012_shd_wb, ISX012_SHD_WB_NENTRIES); - if (ret < 0) - { - imagererr("isx012_putreglist(SHD white balance) failed: %d\n", ret); - board_isx012_set_reset(); - return ret; - } - - /* Enable CXC and SHD */ - - ret = isx012_putreg(priv, SHD_EN, 0x57, 1); - if (ret < 0) - { - imagererr("isx012_putreg(enable CXC/SHD) failed: %d\n", ret); - return ret; - } - - return OK; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -int isx012_register(FAR struct i2c_master_s *i2c) -{ - FAR struct isx012_dev_s *priv = &g_isx012_private; - - /* Save i2c information */ - - priv->i2c = i2c; - priv->i2c_addr = ISX012_I2C_SLV_ADDR; - priv->i2c_freq = I2CFREQ_STANDARD; - - /* Initialize other information */ - - priv->state = STATE_ISX012_POWEROFF; - - return OK; -} - -int isx012_unregister(void) -{ - /* no procedure */ - - return OK; -} - -FAR struct video_devops_s *isx012_initialize(void) -{ - /* return address of video operations variable */ - - return &g_isx012_video_devops; -} - -int isx012_uninitialize(void) -{ - /* No procedure */ - - return OK; -} diff --git a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c index b9a81a5a7b..4c78f6ec78 100644 --- a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c +++ b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c @@ -109,6 +109,10 @@ # include #endif +#ifdef CONFIG_CXD56_CISIF +# include +#endif + #include "spresense.h" /**************************************************************************** @@ -191,9 +195,6 @@ int cxd56_bringup(void) { struct pm_cpu_wakelock_s wlock; int ret; -#ifdef CONFIG_VIDEO_ISX012 - FAR const struct video_devops_s *devops; -#endif ret = nsh_cpucom_initialize(); if (ret < 0) @@ -375,17 +376,19 @@ int cxd56_bringup(void) ret = board_isx012_initialize(IMAGER_I2C); if (ret < 0) { - _err("ERROR: Failed to initialize ISX012 board. %d\n", ret); - } - - devops = isx012_initialize(); - if (devops == NULL) - { - _err("ERROR: Failed to populate ISX012 devops. %d\n", ret); - ret = ERROR; + _err("ERROR: Failed to initialize ISX012 board. %d\n", errno); } #endif /* CONFIG_VIDEO_ISX012 */ +#ifdef CONFIG_CXD56_CISIF + ret = cxd56_cisif_initialize(); + if (ret < 0) + { + _err("ERROR: Failed to initialize CISIF. %d\n", errno); + ret = ERROR; + } +#endif /* CONFIG_CXD56_CISIF */ + #if defined(CONFIG_CXD56_SDIO) /* In order to prevent Hi-Z from being input to the SD Card controller, * Initialize SDIO pins to GPIO low output with internal pull-down. diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5da6fd2e7f..fb3265bca4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -56,6 +56,87 @@ config VIDEO_STREAM ---help--- Enable video Stream support +if VIDEO_STREAM + +config VIDEO_SCENE_BACKLIGHT + bool "Enable backlight scene" + default y + ---help--- + Enable backlight scene + +config VIDEO_SCENE_BEACHSNOW + bool "Enable beach snow scene" + default y + ---help--- + Enable beach snow scene + +config VIDEO_SCENE_CANDLELIGHT + bool "Enable candle light scene" + default y + ---help--- + Enable candle light scene + +config VIDEO_SCENE_DAWNDUSK + bool "Enable dawn dusk scene" + default y + ---help--- + Enable dawn dusk scene + +config VIDEO_SCENE_FALLCOLORS + bool "Enable fall colors scene" + default y + ---help--- + Enable fall colors scene + +config VIDEO_SCENE_FIREWORKS + bool "Enable fireworks scene" + default y + ---help--- + Enable fireworks scene + +config VIDEO_SCENE_LANDSCAPE + bool "Enable landscape scene" + default y + ---help--- + Enable landscape scene + +config VIDEO_SCENE_NIGHT + bool "Enable night scene" + default y + ---help--- + Enable night scene + +config VIDEO_SCENE_PARTYINDOOR + bool "Enable party and indoor scene" + default y + ---help--- + Enable party and indoor scene + +config VIDEO_SCENE_PORTRAIT + bool "Enable portrait scene" + default y + ---help--- + Enable portrait scene + +config VIDEO_SCENE_SPORTS + bool "Enable sports scene" + default y + ---help--- + Enable sports scene + +config VIDEO_SCENE_SUNSET + bool "Enable sunset scene" + default y + ---help--- + Enable sunset scene + +config VIDEO_SCENE_TEXT + bool "Enable text scene" + default y + ---help--- + Enable text scene +endif + config VIDEO_MAX7456 bool "Maxim 7456 Monochrome OSD" default n @@ -64,6 +145,11 @@ config VIDEO_MAX7456 Support for the Maxim 7456 monochrome on-screen display multiplexer. +config VIDEO_ISX012 + bool "ISX012 Image sensor" + default n + select I2C + config VIDEO_OV2640 bool "OV2640 camera chip" default n diff --git a/drivers/video/Make.defs b/drivers/video/Make.defs index 545e02af28..58036805c5 100644 --- a/drivers/video/Make.defs +++ b/drivers/video/Make.defs @@ -34,6 +34,10 @@ endif ifeq ($(CONFIG_I2C),y) +ifeq ($(CONFIG_VIDEO_ISX012),y) + CSRCS += isx012.c +endif + ifeq ($(CONFIG_VIDEO_OV2640),y) CSRCS += ov2640.c endif diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c new file mode 100644 index 0000000000..62630e6889 --- /dev/null +++ b/drivers/video/isx012.c @@ -0,0 +1,2917 @@ +/**************************************************************************** + * drivers/video/isx012.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "isx012_reg.h" +#include "isx012_range.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The following macro is enabled because + * it is to make stable startup. (other case) + */ + +/* #define ISX012_NOT_USE_NSTBY */ + +/* The following macro is disabled because it is to see detailed control. */ + +/* #define ISX012_CHECK_IN_DETAIL */ + +/* Skip invalid frame because it occurs first due to the spec of isx012. */ + +#define ISX012_FRAME_SKIP_EN + +#define OUT_HSIZE_QVGA (320) +#define OUT_VSIZE_QVGA (240) +#define OUT_HSIZE_VGA (640) +#define OUT_VSIZE_VGA (480) +#define OUT_HSIZE_HD (1280) +#define OUT_VSIZE_HD (720) +#define OUT_HSIZE_QUADVGA (1280) +#define OUT_VSIZE_QUADVGA (960) +#define OUT_HSIZE_FULLHD (1920) +#define OUT_VSIZE_FULLHD (1080) +#define OUT_HSIZE_3M (2048) +#define OUT_VSIZE_3M (1536) +#define OUT_HSIZE_5M (2560) +#define OUT_VSIZE_5M (1920) + +#define OUT_YUV_VSIZE_MIN (64) +#define OUT_YUV_HSIZE_MIN (96) +#define OUT_JPG_VSIZE_MIN (64) +#define OUT_JPG_HSIZE_MIN (96) +#define OUT_YUV_15FPS_VSIZE_MAX (600) +#define OUT_YUV_15FPS_HSIZE_MAX (800) +#define OUT_YUV_30FPS_VSIZE_MAX (600) +#define OUT_YUV_30FPS_HSIZE_MAX (800) +#define OUT_YUV_60FPS_VSIZE_MAX (480) +#define OUT_YUV_60FPS_HSIZE_MAX (640) +#define OUT_YUV_120FPS_VSIZE_MAX (240) +#define OUT_YUV_120FPS_HSIZE_MAX (320) +#define OUT_JPG_15FPS_VSIZE_MAX (1944) +#define OUT_JPG_15FPS_HSIZE_MAX (2592) +#define OUT_JPG_30FPS_VSIZE_MAX (960) +#define OUT_JPG_30FPS_HSIZE_MAX (1280) +#define OUT_JPG_60FPS_VSIZE_MAX (480) +#define OUT_JPG_60FPS_HSIZE_MAX (640) +#define OUT_JPG_120FPS_VSIZE_MAX (240) +#define OUT_JPG_120FPS_HSIZE_MAX (320) + +#define OUT_YUVINT_30FPS_VSIZE_MAX (240) +#define OUT_YUVINT_30FPS_HSIZE_MAX (400) +#define OUT_JPGINT_30FPS_VSIZE_MAX (960) +#define OUT_JPGINT_30FPS_HSIZE_MAX (1280) +#define OUT_JPGINT_15FPS_VSIZE_MAX (1224) +#define OUT_JPGINT_15FPS_HSIZE_MAX (1632) + +#define VINT_TIMEOUT (400) /* ms */ +#define VINT_WAIT_TIME (5) /* ms */ +#define VINT_DELAY_TIME (0) /* ms */ +#define CAMERA_MODE_TIMEOUT (800) /* ms */ +#define CAMERA_MODE_WAIT_TIME (10) /* ms */ +#define CAMERA_MODE_DELAY_TIME (0) /* ms */ +#define DEVICE_STATE_TIMEOUT (100) /* ms */ +#define DEVICE_STATE_WAIT_TIME (1) /* ms */ +#define DEVICE_STATE_DELAY_TIME (2) /* ms */ + +#define I2CFREQ_STANDARD (100000) /* Standard mode : 100kHz */ +#define I2CFREQ_FAST (400000) /* Fast mode : 400kHz */ + +#define ISX012_SIZE_STEP (2) + +#define CXC_RGB_DATA_UNIT_NUM (27) +#define CXC_RGB_DATA_UNIT_SIZE (7) +#define CXC_GRB_DATA_UNIT_NUM (27) +#define CXC_GRB_DATA_UNIT_SIZE (7) +#define SHD_RGB_DATA_UNIT_NUM (27) +#define SHD_RGB_DATA_UNIT_SIZE (11) +#define SHD_GRB_DATA_UNIT_NUM (27) +#define SHD_GRB_DATA_UNIT_SIZE (11) +#define SHD_R1_DATA_UNIT_NUM (14) +#define SHD_R1_DATA_UNIT_SIZE (11) +#define SHD_R2_DATA_UNIT_NUM (14) +#define SHD_R2_DATA_UNIT_SIZE (11) +#define SHD_B2_DATA_UNIT_NUM (14) +#define SHD_B2_DATA_UNIT_SIZE (11) + +#define ISX012_ELEMS_3APARAM (3) + +#ifdef CONFIG_DEBUG_IMAGER_ERROR +#define imagererr(format, ...) _err(format, ##__VA_ARGS__) +#else +#define imagererr(x...) +#endif + +#ifdef CONFIG_DEBUG_IMAGER_WARN +#define imagerwarn(format, ...) _warn(format, ##__VA_ARGS__) +#else +#define imagerwarn(x...) +#endif + +#ifdef CONFIG_DEBUG_IMAGER_INFO +#define imagerinfo(format, ...) _info(format, ##__VA_ARGS__) +#else +#define imagerinfo(x...) +#endif + +#define VALIDATE_VALUE(val, min, max, step) (((val >= min) && \ + (val <= max) && \ + (((val - min) % step) == 0) ? \ + OK : -EINVAL)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum isx012_state_e +{ + STATE_ISX012_PRESLEEP, + STATE_ISX012_SLEEP, + STATE_ISX012_ACTIVE, + STATE_ISX012_POWEROFF, +}; + +typedef enum isx012_state_e isx012_state_t; + +struct isx012_reg_s +{ + uint16_t regaddr; + uint16_t regval; + uint8_t regsize; +}; + +typedef struct isx012_reg_s isx012_reg_t; + +struct isx012_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t i2c_addr; /* I2C address */ + int i2c_freq; /* Frequency */ + isx012_state_t state; /* ISX012 status */ + uint8_t mode; /* ISX012 mode */ +}; + +typedef struct isx012_dev_s isx012_dev_t; + +#define ARRAY_NENTRIES(a) (sizeof(a)/sizeof(a[0])) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* register operations */ + +static uint16_t isx012_getreg(isx012_dev_t *priv, + uint16_t regaddr, uint16_t regsize); +static int isx012_putreg(isx012_dev_t *priv, uint16_t regaddr, + uint16_t regval, uint16_t regsize); +static int isx012_putreglist(isx012_dev_t *priv, + FAR const isx012_reg_t *reglist, size_t nentries); +#ifdef ISX012_CHECK_IN_DETAIL +static int isx012_putregs(isx012_dev_t *priv, uint16_t regaddr, + uint8_t *regvals, uint8_t regsize); +static int isx012_chipid(FAR struct i2c_master_s *i2c); +#endif + +static int isx012_chk_int_state(isx012_dev_t *priv, + uint8_t sts, uint32_t delay_time, + uint32_t wait_time, uint32_t timeout); +static int isx012_set_mode_param(isx012_dev_t *priv, + imgsensor_stream_type_t type, + uint8_t nr_fmt, + imgsensor_format_t *fmt, + imgsensor_interval_t *interval); +static int isx012_change_camera_mode(isx012_dev_t *priv, uint8_t mode); +static int isx012_change_device_state(isx012_dev_t *priv, + isx012_state_t state); +static int isx012_replace_frameinterval_to_regval + (FAR imgsensor_interval_t *interval); +static int8_t isx012_get_maximum_fps + (uint8_t nr_datafmt, + FAR imgsensor_format_t *datafmt); +static int isx012_set_shd(FAR isx012_dev_t *priv); +static bool is_movie_needed(uint8_t fmt, uint8_t fps); + +/* image sensor device operations interface */ + +static int isx012_init(void); +static int isx012_uninit(void); +static int isx012_validate_frame_setting(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); +static int isx012_start_capture(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); +static int isx012_stop_capture(imgsensor_stream_type_t type); +static int isx012_get_supported_value + (uint32_t id, FAR imgsensor_supported_value_t *value); +static int isx012_get_value + (uint32_t id, uint32_t size, FAR imgsensor_value_t *value); +static int isx012_set_value + (uint32_t id, uint32_t size, imgsensor_value_t value); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static isx012_dev_t g_isx012_private; + +#ifndef ISX012_NOT_USE_NSTBY +static const isx012_reg_t g_isx012_presleep[] = +{ + {PLL_CKSEL, 0x00, 0x01}, /* PLL_CKSEL */ + {SRCCK_DIV, 0x00, 0x01}, /* SRCCK_DIV */ + {INCK_SET, 0x17, 0x01}, /* INCK_SET */ +}; +#define ISX012_PRESLEEP_NENTRIES ARRAY_NENTRIES(g_isx012_presleep) +#endif + +static const isx012_reg_t g_isx012_def_init[] = +{ +#ifdef ISX012_NOT_USE_NSTBY + {PLL_CKSEL, 0x00, 0x01}, + {SRCCK_DIV, 0x00, 0x01}, +#endif + {DRIVABILITY, 0xaa, 0x01}, + {VIFCONFIG, 0x0200, 0x02}, + {YUVCONFIG_TN, 0xff0a, 0x02}, + {ILCODELEN, 0x00, 0x01}, + {AFMODE_MONI, 0x01, 0x01}, + {YUVCONFIG, 0xff6a, 0x02}, + {VIF_REC601_Y, 0x10fe, 0x02}, + {VIF_REC601_C, 0x10f0, 0x02}, + {HSENS_MODE_SEL, 0x11, 0x01}, + {VIF_CLKCONFIG1, 0x30, 0x01}, + {VIF_CLKCONFIG2, 0x30, 0x01}, + {VIF_CLKCONFIG3, 0x30, 0x01}, + {VIF_CLKCONFIG4, 0x30, 0x01}, + {VIF_CLKCONFIG5, 0x30, 0x01}, + {VIF_CLKCONFIG6, 0x30, 0x01}, + {VIF_CLKCONFIG7, 0x30, 0x01}, + {VIF_CLKCONFIG8, 0x30, 0x01}, + {VIF_CLKCONFIG9, 0x30, 0x01}, + {VIF_CLKCONFIG10, 0x30, 0x01}, + {VIF_CLKCONFIG11, 0x30, 0x01}, + {VIF_CLKCONFIG12, 0x30, 0x01}, + {VIF_CLKCONFIG13, 0x11, 0x01}, + {VIF_CLKCONFIG14, 0x11, 0x01}, + {VIF_CLKCONFIG15, 0x11, 0x01}, + {VIF_CLKCONFIG16, 0x11, 0x01}, +#ifdef ISX012_NOT_USE_NSTBY + {INCK_SET, 0x17, 0x01}, /* INCK_SET */ +#endif + {FRM_FIX_SN1_2, 0xff, 0x01}, /* Fix framerate */ + {FAST_MODECHG_EN, 0x01, 0x01}, + {FAST_SHT_MODE_SEL, 0x01, 0x01}, + {CAP_HALF_AE_CTRL, 0x07, 0x01}, /* HAFREL=HIGHSPEED, CAP=Auto */ + {HALF_AWB_CTRL, 0x01, 0x01}, + {AESPEED_FAST, 0x0f, 0x01}, + {FASTMOVE_TIMEOUT, 0x2d, 0x01}, + {YGAMMA_MODE, 0x01, 0x01}, + {INT_QLTY2, 0x50, 0x01}, +}; + +#define ISX012_RESET_NENTRIES ARRAY_NENTRIES(g_isx012_def_init) + +static const uint8_t g_isx012_cxc_rgb_data[CXC_RGB_DATA_UNIT_NUM] + [CXC_RGB_DATA_UNIT_SIZE] = +{ + {0x01, 0x43, 0xc0, 0xf0, 0x4f, 0xfc, 0x13}, /* CXC_RGB_UNIT0 */ + {0x80, 0x44, 0x20, 0x21, 0x48, 0x04, 0x0e}, /* CXC_RGB_UNIT1 */ + {0x81, 0x43, 0xc0, 0x10, 0x30, 0xfc, 0x13}, /* CXC_RGB_UNIT2 */ + {0xff, 0x04, 0x20, 0x11, 0x48, 0x08, 0x12}, /* CXC_RGB_UNIT3 */ + {0x81, 0x43, 0xe0, 0x20, 0x48, 0x08, 0x12}, /* CXC_RGB_UNIT4 */ + {0x80, 0x03, 0xe0, 0x00, 0x38, 0x04, 0x10}, /* CXC_RGB_UNIT5 */ + {0x01, 0x84, 0x20, 0x21, 0x48, 0x04, 0x10}, /* CXC_RGB_UNIT6 */ + {0x01, 0x04, 0xc0, 0x10, 0x20, 0x00, 0x08}, /* CXC_RGB_UNIT7 */ + {0x81, 0x82, 0xc0, 0x20, 0x38, 0x08, 0x0e}, /* CXC_RGB_UNIT8 */ + {0x01, 0x43, 0xc0, 0x10, 0x20, 0x04, 0x04}, /* CXC_RGB_UNIT9 */ + {0x01, 0x41, 0x40, 0x10, 0x20, 0x08, 0x0a}, /* CXC_RGB_UNIT10 */ + {0x82, 0x82, 0x80, 0x20, 0x20, 0x04, 0x04}, /* CXC_RGB_UNIT11 */ + {0x82, 0x80, 0x20, 0x20, 0x08, 0x04, 0x06}, /* CXC_RGB_UNIT12 */ + {0x81, 0x42, 0xa0, 0x10, 0x20, 0x04, 0x08}, /* CXC_RGB_UNIT13 */ + {0x81, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00}, /* CXC_RGB_UNIT14 */ + {0x01, 0x41, 0x80, 0x10, 0x20, 0x00, 0x08}, /* CXC_RGB_UNIT15 */ + {0x00, 0x42, 0x20, 0x20, 0x08, 0x08, 0x00}, /* CXC_RGB_UNIT16 */ + {0x82, 0xc0, 0x40, 0x20, 0x20, 0x08, 0x08}, /* CXC_RGB_UNIT17 */ + {0x80, 0x02, 0xa0, 0x10, 0x20, 0x08, 0x04}, /* CXC_RGB_UNIT18 */ + {0x02, 0x81, 0x60, 0x30, 0x20, 0x08, 0x0a}, /* CXC_RGB_UNIT19 */ + {0x82, 0x42, 0xc0, 0x10, 0x30, 0x04, 0x0a}, /* CXC_RGB_UNIT20 */ + {0x03, 0xc3, 0xa0, 0x40, 0x28, 0x0c, 0x0a}, /* CXC_RGB_UNIT21 */ + {0x03, 0xc3, 0xc0, 0x20, 0x20, 0x08, 0x08}, /* CXC_RGB_UNIT22 */ + {0x82, 0xc2, 0xc0, 0x30, 0x40, 0x10, 0x0e}, /* CXC_RGB_UNIT23 */ + {0x84, 0x03, 0xa1, 0x40, 0x28, 0x08, 0x08}, /* CXC_RGB_UNIT24 */ + {0x02, 0x82, 0xa0, 0x30, 0x30, 0x0c, 0x10}, /* CXC_RGB_UNIT25 */ + {0x84, 0x03, 0xe1, 0x40, 0x28, 0x10, 0x0a}, /* CXC_RGB_UNIT26 */ +}; + +static const uint8_t g_isx012_cxc_grb_data[CXC_GRB_DATA_UNIT_NUM] + [CXC_GRB_DATA_UNIT_SIZE] = +{ + {0x00, 0x3d, 0x40, 0x0f, 0xc0, 0x03, 0xf2}, /* CXC_GRB_UNIT0 */ + {0x80, 0x7c, 0x80, 0x1f, 0xd8, 0x03, 0xf0}, /* CXC_GRB_UNIT1 */ + {0x00, 0x3c, 0x40, 0x0f, 0xd0, 0x03, 0xf0}, /* CXC_GRB_UNIT2 */ + {0x80, 0x3c, 0x20, 0x1f, 0xe0, 0x07, 0xf6}, /* CXC_GRB_UNIT3 */ + {0x00, 0x3c, 0x00, 0x1f, 0xd0, 0x07, 0xf4}, /* CXC_GRB_UNIT4 */ + {0x00, 0x3d, 0x40, 0x0f, 0xc8, 0x03, 0xf2}, /* CXC_GRB_UNIT5 */ + {0x80, 0xfc, 0x5f, 0xff, 0xd7, 0x07, 0xf4}, /* CXC_GRB_UNIT6 */ + {0x01, 0x7d, 0x40, 0x0f, 0xd0, 0xff, 0xf3}, /* CXC_GRB_UNIT7 */ + {0x7f, 0xfd, 0x3f, 0x0f, 0xc8, 0x03, 0xf2}, /* CXC_GRB_UNIT8 */ + {0x81, 0x7c, 0x20, 0x0f, 0xd0, 0xff, 0xf7}, /* CXC_GRB_UNIT9 */ + {0x7e, 0xfe, 0x5f, 0x0f, 0xd8, 0x03, 0xf6}, /* CXC_GRB_UNIT10 */ + {0x80, 0xbd, 0xa0, 0x2f, 0xe8, 0x07, 0xfa}, /* CXC_GRB_UNIT11 */ + {0x80, 0xfe, 0xbf, 0x0f, 0xe8, 0xff, 0xf9}, /* CXC_GRB_UNIT12 */ + {0x00, 0x3e, 0x80, 0x3f, 0xe8, 0x0f, 0xfa}, /* CXC_GRB_UNIT13 */ + {0x02, 0x40, 0xe0, 0x0f, 0xf8, 0x03, 0xfe}, /* CXC_GRB_UNIT14 */ + {0x80, 0x7f, 0xe0, 0x1f, 0xf8, 0x17, 0xfe}, /* CXC_GRB_UNIT15 */ + {0x85, 0xff, 0xe0, 0x2f, 0x08, 0x04, 0x04}, /* CXC_GRB_UNIT16 */ + {0x81, 0x40, 0x20, 0x20, 0x00, 0x08, 0x00}, /* CXC_GRB_UNIT17 */ + {0x84, 0x00, 0x21, 0x30, 0x10, 0x0c, 0x06}, /* CXC_GRB_UNIT18 */ + {0x02, 0x82, 0x40, 0x20, 0x10, 0x0c, 0x02}, /* CXC_GRB_UNIT19 */ + {0x83, 0x00, 0x21, 0x40, 0x08, 0x10, 0x06}, /* CXC_GRB_UNIT20 */ + {0x83, 0x82, 0xa0, 0x20, 0x20, 0x08, 0x08}, /* CXC_GRB_UNIT21 */ + {0x02, 0x81, 0x40, 0x30, 0x18, 0x0c, 0x06}, /* CXC_GRB_UNIT22 */ + {0x03, 0x81, 0x80, 0x10, 0x20, 0x04, 0x08}, /* CXC_GRB_UNIT23 */ + {0x82, 0x82, 0x80, 0x20, 0x20, 0x0c, 0x06}, /* CXC_GRB_UNIT24 */ + {0x83, 0xc1, 0x40, 0x20, 0x20, 0x04, 0x08}, /* CXC_GRB_UNIT25 */ + {0x01, 0x82, 0xa0, 0x20, 0x20, 0x08, 0x08}, /* CXC_GRB_UNIT26 */ +}; + +static const uint8_t g_isx012_shd_rgb_data[SHD_RGB_DATA_UNIT_NUM] + [SHD_RGB_DATA_UNIT_SIZE] = +{ + {0xf1, 0x59, 0x52, 0x7b, 0x98, 0xc4, 0x9d, 0x23, 0x29, 0x87, 0x46}, /* SHD_RGB_UNIT0 */ + {0xc6, 0x81, 0xd1, 0x70, 0x56, 0xe4, 0x9c, 0x1b, 0x6d, 0x07, 0x48}, /* SHD_RGB_UNIT1 */ + {0xdd, 0xf1, 0x51, 0x7d, 0xa8, 0xb4, 0x1e, 0x25, 0x49, 0xc7, 0x46}, /* SHD_RGB_UNIT2 */ + {0xbd, 0xf1, 0x50, 0x6d, 0x2a, 0x44, 0x1b, 0x0a, 0x01, 0x87, 0x44}, /* SHD_RGB_UNIT3 */ + {0xd0, 0xa9, 0x51, 0x77, 0x84, 0xd4, 0x9d, 0x1f, 0x2d, 0xc7, 0x44}, /* SHD_RGB_UNIT4 */ + {0xa8, 0xa9, 0xcf, 0x62, 0x98, 0xa3, 0x17, 0xdb, 0xfc, 0x05, 0x38}, /* SHD_RGB_UNIT5 */ + {0x90, 0xe1, 0x8e, 0x6a, 0x08, 0xc4, 0x9b, 0x0e, 0x11, 0x07, 0x43}, /* SHD_RGB_UNIT6 */ + {0xac, 0xa9, 0x4f, 0x5d, 0x4e, 0x13, 0x15, 0xb9, 0xf8, 0x44, 0x2b}, /* SHD_RGB_UNIT7 */ + {0x44, 0x21, 0xcb, 0x56, 0x0e, 0x63, 0x98, 0xe3, 0x78, 0x86, 0x3d}, /* SHD_RGB_UNIT8 */ + {0xab, 0x81, 0x4f, 0x62, 0x7c, 0xc3, 0x94, 0xb4, 0x98, 0x84, 0x26}, /* SHD_RGB_UNIT9 */ + {0x14, 0xe9, 0x48, 0x46, 0x4a, 0x12, 0x93, 0xa4, 0x84, 0xc5, 0x31}, /* SHD_RGB_UNIT10 */ + {0x81, 0xe9, 0x4d, 0x67, 0xac, 0x73, 0x17, 0xd0, 0xdc, 0x24, 0x29}, /* SHD_RGB_UNIT11 */ + {0x12, 0xb9, 0x08, 0x40, 0x02, 0x52, 0x10, 0x84, 0x6c, 0x64, 0x25}, /* SHD_RGB_UNIT12 */ + {0x4c, 0x91, 0xcb, 0x5b, 0x4c, 0xe3, 0x19, 0xec, 0xdc, 0x05, 0x34}, /* SHD_RGB_UNIT13 */ + {0x37, 0x39, 0x8a, 0x44, 0x2a, 0x02, 0x10, 0x80, 0x14, 0xe4, 0x20}, /* SHD_RGB_UNIT14 */ + {0x1c, 0x51, 0x49, 0x53, 0xe4, 0x02, 0x17, 0xd3, 0xb8, 0xe6, 0x3d}, /* SHD_RGB_UNIT15 */ + {0x8b, 0xd9, 0x8d, 0x53, 0xc8, 0x72, 0x12, 0x98, 0x50, 0x24, 0x23}, /* SHD_RGB_UNIT16 */ + {0x19, 0x11, 0x89, 0x4c, 0x8c, 0x32, 0x16, 0xc7, 0x14, 0x06, 0x38}, /* SHD_RGB_UNIT17 */ + {0xca, 0xc1, 0x10, 0x6c, 0xe0, 0x83, 0x97, 0xd0, 0x4c, 0xa5, 0x2d}, /* SHD_RGB_UNIT18 */ + {0x3e, 0x99, 0x0a, 0x51, 0xbc, 0xc2, 0x15, 0xc2, 0x28, 0x26, 0x39}, /* SHD_RGB_UNIT19 */ + {0xa5, 0x89, 0x0f, 0x7b, 0x8c, 0x64, 0x9d, 0x14, 0xb9, 0x46, 0x3e}, /* SHD_RGB_UNIT20 */ + {0x8f, 0x41, 0xce, 0x5e, 0x5e, 0x03, 0x98, 0xdc, 0x50, 0xe6, 0x3a}, /* SHD_RGB_UNIT21 */ + {0xb4, 0x49, 0x90, 0x72, 0x50, 0x74, 0xa1, 0x3a, 0x05, 0x88, 0x4b}, /* SHD_RGB_UNIT22 */ + {0xe1, 0xd1, 0x91, 0x71, 0x38, 0xc4, 0x1b, 0x0a, 0xed, 0x86, 0x42}, /* SHD_RGB_UNIT23 */ + {0xcb, 0x49, 0xd1, 0x78, 0x86, 0x74, 0x9f, 0x2d, 0xb9, 0x88, 0x51}, /* SHD_RGB_UNIT24 */ + {0x11, 0x62, 0x93, 0x7c, 0x9c, 0x94, 0x1d, 0x1b, 0x41, 0x67, 0x46}, /* SHD_RGB_UNIT25 */ + {0xcf, 0x81, 0x91, 0x77, 0x82, 0x54, 0x9f, 0x2a, 0x21, 0xa8, 0x4d}, /* SHD_RGB_UNIT26 */ +}; + +static const uint8_t g_isx012_shd_grb_data[SHD_GRB_DATA_UNIT_NUM] + [SHD_GRB_DATA_UNIT_SIZE] = +{ + {0xe8, 0xa9, 0x0f, 0x78, 0xe4, 0x13, 0x9d, 0xf0, 0x04, 0xe7, 0x39}, /* SHD_GRB_UNIT0 */ + {0xbd, 0x51, 0x0e, 0x6f, 0x94, 0x63, 0x1c, 0xea, 0x4c, 0x27, 0x3c}, /* SHD_GRB_UNIT1 */ + {0xd7, 0x19, 0x4f, 0x7a, 0xf4, 0xd3, 0x1d, 0xf7, 0x20, 0xe7, 0x3a}, /* SHD_GRB_UNIT2 */ + {0xb6, 0x11, 0x0e, 0x6c, 0x76, 0x03, 0x9b, 0xdd, 0xf0, 0x06, 0x39}, /* SHD_GRB_UNIT3 */ + {0xc9, 0xc1, 0x8e, 0x75, 0xc8, 0xe3, 0x9c, 0xef, 0xf8, 0xa6, 0x39}, /* SHD_GRB_UNIT4 */ + {0xa0, 0x69, 0x0d, 0x62, 0x20, 0x93, 0x97, 0xbf, 0xf4, 0xa5, 0x30}, /* SHD_GRB_UNIT5 */ + {0x8c, 0xb1, 0x8c, 0x68, 0x60, 0x13, 0x9b, 0xe0, 0xcc, 0xa6, 0x38}, /* SHD_GRB_UNIT6 */ + {0x9f, 0x71, 0x0d, 0x5c, 0xf4, 0x12, 0x15, 0xab, 0x00, 0x65, 0x28}, /* SHD_GRB_UNIT7 */ + {0x44, 0x41, 0x0a, 0x56, 0xbc, 0x02, 0x98, 0xc4, 0x50, 0x26, 0x34}, /* SHD_GRB_UNIT8 */ + {0x9a, 0x59, 0x4d, 0x5f, 0x16, 0x83, 0x14, 0xa8, 0x9c, 0x64, 0x25}, /* SHD_GRB_UNIT9 */ + {0x15, 0xc1, 0xc8, 0x46, 0x38, 0x22, 0x13, 0x9a, 0x74, 0x65, 0x2c}, /* SHD_GRB_UNIT10 */ + {0x78, 0x11, 0x4c, 0x63, 0x36, 0xb3, 0x96, 0xbb, 0xcc, 0x44, 0x27}, /* SHD_GRB_UNIT11 */ + {0x11, 0xa1, 0x48, 0x40, 0x04, 0x72, 0x10, 0x83, 0x70, 0x84, 0x23}, /* SHD_GRB_UNIT12 */ + {0x4a, 0x69, 0xca, 0x59, 0xe0, 0xf2, 0x98, 0xcc, 0xb0, 0xa5, 0x2e}, /* SHD_GRB_UNIT13 */ + {0x33, 0xc1, 0x09, 0x44, 0x24, 0x02, 0x10, 0x80, 0x14, 0x84, 0x20}, /* SHD_GRB_UNIT14 */ + {0x1b, 0xd1, 0x48, 0x52, 0x98, 0x72, 0x96, 0xb7, 0x8c, 0x06, 0x35}, /* SHD_GRB_UNIT15 */ + {0x81, 0x39, 0xcc, 0x51, 0x96, 0x32, 0x92, 0x92, 0x48, 0x44, 0x22}, /* SHD_GRB_UNIT16 */ + {0x17, 0xb9, 0x48, 0x4b, 0x5e, 0xa2, 0x15, 0xb0, 0xd8, 0x45, 0x30}, /* SHD_GRB_UNIT17 */ + {0xc0, 0x19, 0xce, 0x69, 0x56, 0x23, 0x97, 0xba, 0x38, 0x05, 0x2a}, /* SHD_GRB_UNIT18 */ + {0x3b, 0xe1, 0x09, 0x50, 0x82, 0x42, 0x95, 0xac, 0xf8, 0x05, 0x31}, /* SHD_GRB_UNIT19 */ + {0x94, 0x19, 0x4d, 0x78, 0xca, 0xe3, 0x9c, 0xe8, 0xa8, 0xa6, 0x35}, /* SHD_GRB_UNIT20 */ + {0x8b, 0x71, 0xcc, 0x5d, 0xf8, 0xa2, 0x97, 0xc0, 0x24, 0xa6, 0x32}, /* SHD_GRB_UNIT21 */ + {0xa4, 0xb1, 0x8d, 0x6d, 0x96, 0xd3, 0xa0, 0x09, 0xe1, 0xa7, 0x3f}, /* SHD_GRB_UNIT22 */ + {0xde, 0x09, 0xcf, 0x70, 0x92, 0x73, 0x9b, 0xe0, 0xcc, 0x06, 0x38}, /* SHD_GRB_UNIT23 */ + {0xc0, 0x89, 0x4e, 0x74, 0xcc, 0x13, 0x1e, 0xfc, 0x84, 0x48, 0x45}, /* SHD_GRB_UNIT24 */ + {0x06, 0x7a, 0xd0, 0x7a, 0xe6, 0x33, 0x1d, 0xef, 0x24, 0x07, 0x3b}, /* SHD_GRB_UNIT25 */ + {0xc4, 0xb1, 0x0e, 0x74, 0xca, 0x33, 0x1e, 0xfc, 0xc4, 0x07, 0x41}, /* SHD_GRB_UNIT26 */ +}; + +static const uint8_t g_isx012_shd_r1_data[SHD_R1_DATA_UNIT_NUM] + [SHD_R1_DATA_UNIT_SIZE] = +{ + {0x10, 0x92, 0x10, 0x82, 0xf8, 0x43, 0x1f, 0xfb, 0xf0, 0xe7, 0x40}, /* SHD_R1_UNIT0 */ + {0x07, 0x92, 0xd0, 0x82, 0xec, 0x33, 0x9e, 0xed, 0x68, 0xe7, 0x3c}, /* SHD_R1_UNIT1 */ + {0xfa, 0x21, 0xd0, 0x7e, 0xce, 0xa3, 0x1b, 0xcd, 0x20, 0xe6, 0x31}, /* SHD_R1_UNIT2 */ + {0xa6, 0x69, 0xce, 0x78, 0xbc, 0xa3, 0x1b, 0xbe, 0x44, 0x25, 0x28}, /* SHD_R1_UNIT3 */ + {0x45, 0x19, 0xcb, 0x65, 0x78, 0xe3, 0x1b, 0xc8, 0x3c, 0xa5, 0x24}, /* SHD_R1_UNIT4 */ + {0x15, 0xc1, 0x48, 0x4d, 0xd6, 0x72, 0x99, 0xd3, 0xdc, 0x25, 0x27}, /* SHD_R1_UNIT5 */ + {0x11, 0x01, 0x08, 0x41, 0x42, 0x42, 0x15, 0xc1, 0xa4, 0x06, 0x2f}, /* SHD_R1_UNIT6 */ + {0x39, 0x89, 0x08, 0x40, 0x0a, 0x22, 0x12, 0xab, 0x0c, 0x26, 0x38}, /* SHD_R1_UNIT7 */ + {0x91, 0x71, 0x4a, 0x49, 0x2c, 0xa2, 0x11, 0x9c, 0xc4, 0xa5, 0x33}, /* SHD_R1_UNIT8 */ + {0xe2, 0xe1, 0x4d, 0x5f, 0xa4, 0x22, 0x94, 0xa3, 0xa0, 0x05, 0x34}, /* SHD_R1_UNIT9 */ + {0xc7, 0x41, 0x50, 0x7c, 0x7e, 0xd3, 0x19, 0xc5, 0x48, 0x86, 0x35}, /* SHD_R1_UNIT10 */ + {0xda, 0xa9, 0xcf, 0x8c, 0x42, 0x24, 0x20, 0xf5, 0x8c, 0x67, 0x3c}, /* SHD_R1_UNIT11 */ + {0xf6, 0x89, 0xd0, 0x88, 0x90, 0x34, 0x23, 0x0b, 0x15, 0xa8, 0x3f}, /* SHD_R1_UNIT12 */ + {0x00, 0x72, 0x10, 0x89, 0x68, 0x04, 0x69, 0x00, 0x00, 0x19, 0x26}, /* SHD_R1_UNIT13 */ +}; + +static const uint8_t g_isx012_shd_r2_data[SHD_R2_DATA_UNIT_NUM] + [SHD_R2_DATA_UNIT_SIZE] = +{ + {0x3a, 0xe2, 0x11, 0x8c, 0x42, 0x74, 0xa1, 0x0c, 0x89, 0x08, 0x46}, /* SHD_R2_UNIT0 */ + {0x30, 0xe2, 0xd1, 0x8c, 0x36, 0x54, 0x20, 0xfe, 0xec, 0x47, 0x41}, /* SHD_R2_UNIT1 */ + {0x20, 0x5a, 0x91, 0x88, 0x16, 0x94, 0x1d, 0xda, 0x80, 0x26, 0x35}, /* SHD_R2_UNIT2 */ + {0xc2, 0x69, 0x0f, 0x81, 0x00, 0x94, 0x9d, 0xc9, 0x84, 0xe5, 0x29}, /* SHD_R2_UNIT3 */ + {0x54, 0xb1, 0x0b, 0x6c, 0xb2, 0xb3, 0x9d, 0xd4, 0x74, 0x85, 0x25}, /* SHD_R2_UNIT4 */ + {0x1a, 0xf1, 0x08, 0x50, 0xfc, 0xe2, 0x1a, 0xe0, 0x2c, 0x66, 0x28}, /* SHD_R2_UNIT5 */ + {0x14, 0x01, 0x88, 0x41, 0x4e, 0x32, 0x16, 0xcb, 0x08, 0x87, 0x31}, /* SHD_R2_UNIT6 */ + {0x42, 0x99, 0x08, 0x40, 0x0c, 0x72, 0x92, 0xb1, 0x58, 0x86, 0x3b}, /* SHD_R2_UNIT7 */ + {0xa8, 0xd9, 0xca, 0x4a, 0x32, 0xe2, 0x91, 0xa0, 0x04, 0x66, 0x36}, /* SHD_R2_UNIT8 */ + {0x02, 0xc2, 0x4e, 0x64, 0xbe, 0xd2, 0x94, 0xa9, 0xe0, 0xc5, 0x36}, /* SHD_R2_UNIT9 */ + {0xe1, 0x61, 0x91, 0x84, 0xb6, 0x43, 0x9b, 0xcf, 0x9c, 0x66, 0x38}, /* SHD_R2_UNIT10 */ + {0xf6, 0xa1, 0x50, 0x97, 0x8e, 0x34, 0x22, 0x04, 0x01, 0x08, 0x40}, /* SHD_R2_UNIT11 */ + {0x15, 0x9a, 0x51, 0x92, 0xf2, 0xd4, 0xa5, 0x1d, 0x99, 0xa8, 0x43}, /* SHD_R2_UNIT12 */ + {0x21, 0x82, 0x91, 0x92, 0xbe, 0xf4, 0x9e, 0xf3, 0x4c, 0x87, 0x38}, /* SHD_R2_UNIT13 */ +}; + +static const uint8_t g_isx012_shd_b2_data[SHD_B2_DATA_UNIT_NUM] + [SHD_B2_DATA_UNIT_SIZE] = +{ + {0xef, 0x39, 0xcf, 0x74, 0x88, 0xb3, 0x1b, 0xdf, 0x20, 0x47, 0x3b}, /* SHD_B2_UNIT0 */ + {0xdf, 0x59, 0xcf, 0x77, 0x8c, 0x43, 0x1b, 0xd7, 0xb8, 0x46, 0x37}, /* SHD_B2_UNIT1 */ + {0xcc, 0xc1, 0x0e, 0x73, 0x78, 0xa3, 0x99, 0xc1, 0xd0, 0x25, 0x2f}, /* SHD_B2_UNIT2 */ + {0x87, 0x09, 0x0d, 0x6c, 0x64, 0x93, 0x99, 0xb6, 0x30, 0xc5, 0x27}, /* SHD_B2_UNIT3 */ + {0x3f, 0xb1, 0x0a, 0x5f, 0x2a, 0x93, 0x99, 0xbc, 0x1c, 0x85, 0x24}, /* SHD_B2_UNIT4 */ + {0x16, 0xc9, 0x48, 0x4c, 0xb6, 0x92, 0x17, 0xc4, 0x94, 0x85, 0x26}, /* SHD_B2_UNIT5 */ + {0x10, 0x09, 0x88, 0x41, 0x3a, 0x52, 0x94, 0xb2, 0x2c, 0xc6, 0x2c}, /* SHD_B2_UNIT6 */ + {0x33, 0x79, 0x08, 0x40, 0x08, 0xc2, 0x11, 0xa2, 0x94, 0x65, 0x34}, /* SHD_B2_UNIT7 */ + {0x7e, 0x39, 0x4a, 0x48, 0x26, 0x52, 0x91, 0x96, 0x64, 0x05, 0x2f}, /* SHD_B2_UNIT8 */ + {0xbf, 0x09, 0x8d, 0x5b, 0x92, 0xa2, 0x93, 0x9d, 0x4c, 0x65, 0x2f}, /* SHD_B2_UNIT9 */ + {0x95, 0xf9, 0x0e, 0x73, 0x48, 0x63, 0x98, 0xb9, 0xd8, 0xa5, 0x30}, /* SHD_B2_UNIT10 */ + {0xa5, 0xb1, 0x8d, 0x83, 0xf4, 0xa3, 0x1d, 0xe0, 0xd0, 0x06, 0x36}, /* SHD_B2_UNIT11 */ + {0xbe, 0xa9, 0x4e, 0x79, 0x50, 0xd4, 0x20, 0xf6, 0x54, 0xa7, 0x38}, /* SHD_B2_UNIT12 */ + {0xc5, 0x91, 0xce, 0x7a, 0xf4, 0x03, 0x44, 0x00, 0x60, 0x60, 0x00}, /* SHD_B2_UNIT13 */ +}; + +static const isx012_reg_t g_isx012_shd_thresholds[] = +{ + {SHD_INP_TH_HB_H_R2, 0x1478, 2}, + {SHD_INP_TH_HB_L_R2, 0x1380, 2}, + {SHD_INP_TH_LB_H_R2, 0x10cc, 2}, + {SHD_INP_TH_LB_L_R2, 0x1004, 2}, + {SHD_INP_TH_HB_H_RB, 0x10cc, 2}, + {SHD_INP_TH_HB_L_RB, 0x1004, 2}, + {SHD_INP_TH_LB_H_RB, 0x0000, 2}, + {SHD_INP_TH_LB_L_RB, 0x0000, 2}, +}; + +#define ISX012_SHD_THRESHOLDS_NENTRIES ARRAY_NENTRIES(g_isx012_shd_thresholds) + +static const isx012_reg_t g_isx012_shd_wb[] = +{ + {NORMR, 0x1101, 2}, + {NORMB, 0x0f7b, 2}, + {AWBPRER, 0x0147, 2}, + {AWBPREB, 0x022a, 2}, + {SHD_PRER_OFFSET_R2, 0x001b, 2}, + {SHD_PRER_OFFSET_RB, 0x000b, 2}, + {SHD_PREB_OFFSET_RB, 0x0003, 2}, +}; + +#define ISX012_SHD_WB_NENTRIES ARRAY_NENTRIES(g_isx012_shd_wb) + +static int32_t g_isx012_colorfx_actual[] = +{ + IMGSENSOR_COLORFX_NONE, + IMGSENSOR_COLORFX_BW, + IMGSENSOR_COLORFX_SEPIA, + IMGSENSOR_COLORFX_NEGATIVE, + IMGSENSOR_COLORFX_SKETCH, + IMGSENSOR_COLORFX_SOLARIZATION, + IMGSENSOR_COLORFX_PASTEL +}; + +static uint8_t g_isx012_colorfx_regval[] = +{ + REGVAL_EFFECT_NONE, + REGVAL_EFFECT_MONOTONE, + REGVAL_EFFECT_SEPIA, + REGVAL_EFFECT_NEGPOS, + REGVAL_EFFECT_SKETCH, + REGVAL_EFFECT_SOLARIZATION, + REGVAL_EFFECT_PASTEL +}; + +static int32_t g_isx012_presetwb_actual[] = +{ + IMGSENSOR_WHITE_BALANCE_AUTO, + IMGSENSOR_WHITE_BALANCE_INCANDESCENT, + IMGSENSOR_WHITE_BALANCE_FLUORESCENT, + IMGSENSOR_WHITE_BALANCE_DAYLIGHT, + IMGSENSOR_WHITE_BALANCE_CLOUDY, + IMGSENSOR_WHITE_BALANCE_SHADE +}; + +static uint8_t g_isx012_presetwb_regval[] = +{ + REGVAL_AWB_ATM, + REGVAL_AWB_LIGHTBULB, + REGVAL_AWB_FLUORESCENTLIGHT, + REGVAL_AWB_CLEARWEATHER, + REGVAL_AWB_CLOUDYWEATHER, + REGVAL_AWB_SHADE +}; + +static int32_t g_isx012_photometry_actual[] = +{ + IMGSENSOR_EXPOSURE_METERING_AVERAGE, + IMGSENSOR_EXPOSURE_METERING_CENTER_WEIGHTED, + IMGSENSOR_EXPOSURE_METERING_SPOT, + IMGSENSOR_EXPOSURE_METERING_MATRIX +}; + +static uint8_t g_isx012_photometry_regval[] = +{ + REGVAL_PHOTOMETRY_AVERAGE, + REGVAL_PHOTOMETRY_CENTERWEIGHT, + REGVAL_PHOTOMETRY_SPOT, + REGVAL_PHOTOMETRY_MULTIPATTERN +}; + +static int32_t g_isx012_iso_actual[] = +{ + 25 * 1000, + 32 * 1000, + 40 * 1000, + 50 * 1000, + 64 * 1000, + 80 * 1000, + 100 * 1000, + 125 * 1000, + 160 * 1000, + 200 * 1000, + 250 * 1000, + 320 * 1000, + 400 * 1000, + 500 * 1000, + 640 * 1000, + 800 * 1000, + 1000 * 1000, + 1250 * 1000, + 1600 * 1000 +}; + +static uint8_t g_isx012_iso_regval[] = +{ + REGVAL_ISO_25, + REGVAL_ISO_32, + REGVAL_ISO_40, + REGVAL_ISO_50, + REGVAL_ISO_64, + REGVAL_ISO_80, + REGVAL_ISO_100, + REGVAL_ISO_125, + REGVAL_ISO_160, + REGVAL_ISO_200, + REGVAL_ISO_250, + REGVAL_ISO_320, + REGVAL_ISO_400, + REGVAL_ISO_500, + REGVAL_ISO_640, + REGVAL_ISO_800, + REGVAL_ISO_1000, + REGVAL_ISO_1250, + REGVAL_ISO_1600 +}; + +static struct imgsensor_ops_s g_isx012_ops = +{ + .init = isx012_init, + .uninit = isx012_uninit, + .validate_frame_setting = isx012_validate_frame_setting, + .start_capture = isx012_start_capture, + .stop_capture = isx012_stop_capture, + .get_supported_value = isx012_get_supported_value, + .get_value = isx012_get_value, + .set_value = isx012_set_value, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint16_t isx012_getreg(isx012_dev_t *priv, + uint16_t regaddr, uint16_t regsize) +{ + struct i2c_config_s config; + volatile uint16_t regval = 0; + volatile uint8_t buffer[2]; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->i2c_freq; + config.address = priv->i2c_addr; + config.addrlen = 7; + buffer[0] = regaddr >> 8; + buffer[1] = regaddr & 0xff; + + /* Write the register address */ + + ret = i2c_write(priv->i2c, &config, (uint8_t *)buffer, 2); + if (ret < 0) + { + imagererr("i2c_write failed: %d\n", ret); + return 0; + } + + /* Restart and read 16bits from the register */ + + ret = i2c_read(priv->i2c, &config, (uint8_t *)buffer, regsize); + if (ret < 0) + { + imagererr("i2c_read failed: %d\n", ret); + return 0; + } + + memcpy((uint8_t *)®val, (uint8_t *)buffer, regsize); + + return regval; +} + +static int isx012_putreg(isx012_dev_t *priv, + uint16_t regaddr, uint16_t regval, uint16_t regsize) +{ + struct i2c_config_s config; + volatile uint8_t buffer[4]; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->i2c_freq; + config.address = priv->i2c_addr; + config.addrlen = 7; + + /* Set up for the transfer */ + + buffer[0] = regaddr >> 8; /* RegAddr Hi */ + buffer[1] = regaddr & 0xff; /* RegAddr Low */ + + memcpy((uint8_t *)&buffer[2], (uint8_t *)®val, regsize); + + /* And do it */ + + ret = i2c_write(priv->i2c, &config, + (uint8_t *)buffer, regsize + 2); + if (ret < 0) + { + imagererr("i2c_write failed: %d\n", ret); + } + + return ret; +} + +static int isx012_putreglist(isx012_dev_t *priv, + FAR const isx012_reg_t *reglist, + size_t nentries) +{ + FAR const isx012_reg_t *entry; + int ret = OK; + + for (entry = reglist; nentries > 0; nentries--, entry++) + { + ret = isx012_putreg(priv, entry->regaddr, + entry->regval, entry->regsize); + if (ret < 0) + { + imagererr("isx012_putreg failed: %d\n", ret); + return ret; + } + } + + return ret; +} + +static int isx012_chk_int_state(isx012_dev_t *priv, + uint8_t sts, uint32_t delay_time, + uint32_t wait_time, uint32_t timeout) +{ + int ret = 0; + volatile uint8_t data; + uint32_t time = 0; + + nxsig_usleep(delay_time * 1000); + while (time < timeout) + { + data = isx012_getreg(priv, INTSTS0, sizeof(data)); + data = data & sts; + if (data != 0) + { + ret = isx012_putreg(priv, INTCLR0, data, sizeof(data)); + return ret; + } + + nxsig_usleep(wait_time * 1000); + time += wait_time; + } + + return ERROR; +} + +static int isx012_replace_fmt_to_regval(uint8_t nr_fmt, + imgsensor_format_t *fmt) +{ + int ret; + + if (fmt == NULL) + { + return -EINVAL; + } + + switch (fmt[IMGSENSOR_FMT_MAIN].pixelformat) + { + case IMGSENSOR_PIX_FMT_UYVY: + ret = REGVAL_OUTFMT_YUV; + break; + + case IMGSENSOR_PIX_FMT_RGB565: + ret = REGVAL_OUTFMT_RGB; + break; + + case IMGSENSOR_PIX_FMT_JPEG: + ret = REGVAL_OUTFMT_JPEG; + break; + + case IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG: + if (nr_fmt == 1) + { + ret = REGVAL_OUTFMT_JPEG; + } + else + { + ret = REGVAL_OUTFMT_INTERLEAVE; + } + + break; + + default: /* Unsupported format */ + + ret = -EINVAL; + } + + return ret; +} + +static bool is_movie_needed(uint8_t fmt, uint8_t fps) +{ + bool need = true; + + if ((fmt == IMGSENSOR_PIX_FMT_UYVY) || + (fmt == IMGSENSOR_PIX_FMT_RGB565)) + { + if (fps >= REGVAL_FPSTYPE_30FPS) /* This means fps <= 30 */ + { + need = false; + } + } + + return need; +} + +static int isx012_set_mode_param(isx012_dev_t *priv, + imgsensor_stream_type_t type, + uint8_t nr_fmt, + imgsensor_format_t *fmt, + imgsensor_interval_t *interval) +{ + int ret = 0; + int fmt_val = isx012_replace_fmt_to_regval(nr_fmt, fmt); + int fps_val = isx012_replace_frameinterval_to_regval(interval); + uint16_t fps_addr; + uint16_t fmt_addr; + uint16_t smode_addr; + uint16_t hsize_addr; + uint16_t vsize_addr; + uint8_t smode; + uint8_t mode; + + /* Get register address for type */ + + if (type == IMGSENSOR_STREAM_TYPE_VIDEO) + { + if (is_movie_needed(fmt_val, fps_val)) + { + if (priv->mode == REGVAL_MODESEL_HREL) + { + /* In Half release state, + * the setting which need movie mode is prohibited. + */ + + return -EPERM; + } + + fps_addr = FPSTYPE_MOVIE; + fmt_addr = OUTFMT_MOVIE; + smode_addr = SENSMODE_MOVIE; + hsize_addr = HSIZE_MOVIE; + vsize_addr = VSIZE_MOVIE; + mode = REGVAL_MODESEL_MOV; + } + else + { + fps_addr = FPSTYPE_MONI; + fmt_addr = OUTFMT_MONI; + smode_addr = SENSMODE_MONI; + hsize_addr = HSIZE_MONI; + vsize_addr = VSIZE_MONI; + mode = REGVAL_MODESEL_MON; + } + } + else + { + fps_addr = FPSTYPE_CAP; + fmt_addr = OUTFMT_CAP; + smode_addr = SENSMODE_CAP; + hsize_addr = HSIZE_CAP; + vsize_addr = VSIZE_CAP; + mode = REGVAL_MODESEL_CAP; + } + + ret = isx012_putreg(priv, fps_addr, fps_val, sizeof(uint8_t)); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, fmt_addr, fmt_val, sizeof(uint8_t)); + if (ret < 0) + { + return ret; + } + + switch (fps_val) + { + case REGVAL_FPSTYPE_120FPS: + smode = REGVAL_SENSMODE_1_8; + break; + + case REGVAL_FPSTYPE_60FPS: + smode = REGVAL_SENSMODE_1_4; + break; + + case REGVAL_FPSTYPE_30FPS: + smode = REGVAL_SENSMODE_1_2; + break; + + default: + smode = REGVAL_SENSMODE_ALLPIX; + break; + } + + ret = isx012_putreg(priv, smode_addr, smode, sizeof(uint8_t)); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, + hsize_addr, + fmt[IMGSENSOR_FMT_MAIN].width, + sizeof(uint16_t)); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, + vsize_addr, + fmt[IMGSENSOR_FMT_MAIN].height, + sizeof(uint16_t)); + if (ret < 0) + { + return ret; + } + + if (fmt_val == REGVAL_OUTFMT_INTERLEAVE) + { + ret = isx012_putreg(priv, + HSIZE_TN, + fmt[IMGSENSOR_FMT_SUB].width, + sizeof(uint16_t)); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, + VSIZE_TN, + fmt[IMGSENSOR_FMT_SUB].height, + sizeof(uint16_t)); + if (ret < 0) + { + return ret; + } + } + + if (priv->state != STATE_ISX012_ACTIVE) + { + isx012_change_device_state(priv, STATE_ISX012_ACTIVE); + } + + ret = isx012_change_camera_mode(priv, mode); + if (ret == OK) + { + priv->mode = mode; + } + + return ret; +} + +/**************************************************************************** + * isx012_change_camera_mode + ****************************************************************************/ + +static int isx012_change_camera_mode(isx012_dev_t *priv, uint8_t mode) +{ + int ret = 0; + uint16_t fmt_addr; + uint8_t fmt; + uint32_t vifmode; +#ifdef ISX012_FRAME_SKIP_EN + uint8_t mask_num; + int i; +#endif /* ISX012_FRAME_SKIP_EN */ + + if (priv->state != STATE_ISX012_ACTIVE) + { + return -EPERM; + } + + switch (mode) + { + case REGVAL_MODESEL_MON: + case REGVAL_MODESEL_HREL: + fmt_addr = OUTFMT_MONI; + break; + + case REGVAL_MODESEL_MOV: + fmt_addr = OUTFMT_MOVIE; + break; + + case REGVAL_MODESEL_CAP: + fmt_addr = OUTFMT_CAP; + break; + + default: + return -EPERM; + } + + fmt = isx012_getreg(priv, fmt_addr, 1); + + switch (fmt) /* mode parallel */ + { + case REGVAL_OUTFMT_YUV: + vifmode = REGVAL_VIFMODE_YUV_PARALLEL; + break; + case REGVAL_OUTFMT_JPEG: + vifmode = REGVAL_VIFMODE_JPEG_PARALLEL; + break; + case REGVAL_OUTFMT_INTERLEAVE: + vifmode = REGVAL_VIFMODE_INTERLEAVE_PARALLEL; + break; + case REGVAL_OUTFMT_RGB: + vifmode = REGVAL_VIFMODE_RGB_PARALLEL; + break; + default: + vifmode = REGVAL_VIFMODE_YUV_PARALLEL; + break; + } + + ret = isx012_putreg(priv, VIFMODE, vifmode, sizeof(vifmode)); + if (ret < 0) + { + return ret; + } + + if (mode != isx012_getreg(priv, MODESEL, sizeof(mode))) + { + isx012_putreg(priv, INTCLR0, CM_CHANGED_STS, 1); + + ret = isx012_putreg(priv, MODESEL, mode, sizeof(mode)); + if (ret < 0) + { + return ret; + } + + /* Wait CM_CHANGED */ + + ret = isx012_chk_int_state(priv, + CM_CHANGED_STS, + CAMERA_MODE_DELAY_TIME, + CAMERA_MODE_WAIT_TIME, + CAMERA_MODE_TIMEOUT); + if (ret != 0) + { + return ret; + } + } + +#ifdef ISX012_FRAME_SKIP_EN + if (mode != REGVAL_MODESEL_HREL) + { + isx012_putreg(priv, INTCLR0, VINT_STS, 1); + mask_num = isx012_getreg(priv, RO_MASK_NUM, sizeof(mask_num)); + for (i = 0; i < mask_num; i++) + { + /* Wait Next VINT */ + + ret = isx012_chk_int_state(priv, VINT_STS, VINT_DELAY_TIME, + VINT_WAIT_TIME, VINT_TIMEOUT); + if (ret != 0) + { + return ret; + } + } + } +#endif /* ISX012_FRAME_SKIP_EN */ + + return OK; +} + +/**************************************************************************** + * isx012_change_device_state + ****************************************************************************/ + +static int isx012_change_device_state(isx012_dev_t *priv, + isx012_state_t state) +{ + int ret = 0; +#ifdef ISX012_FRAME_SKIP_EN + int i; + uint8_t mute_cnt; +#endif /* ISX012_FRAME_SKIP_EN */ + + if (priv->state == STATE_ISX012_PRESLEEP || priv->state == state) + { + return -EPERM; + } + + switch (state) + { + case STATE_ISX012_SLEEP: + isx012_putreg(priv, INTCLR0, OM_CHANGED_STS, 1); + board_isx012_set_sleep(1); + break; + case STATE_ISX012_ACTIVE: + isx012_putreg(priv, INTCLR0, OM_CHANGED_STS | CM_CHANGED_STS, 1); + board_isx012_release_sleep(); + break; + case STATE_ISX012_PRESLEEP: + return -EPERM; + default: + return -EPERM; + } + + /* Wait OM_CHANGED */ + + ret = isx012_chk_int_state(priv, OM_CHANGED_STS, + DEVICE_STATE_DELAY_TIME, + DEVICE_STATE_WAIT_TIME, + DEVICE_STATE_TIMEOUT); + if (ret != 0) + { + return ret; + } + + priv->state = state; + + if (state == STATE_ISX012_ACTIVE) + { + /* Wait CM_CHANGED -> Monitoring */ + + ret = isx012_chk_int_state(priv, CM_CHANGED_STS, + CAMERA_MODE_DELAY_TIME, + CAMERA_MODE_WAIT_TIME, + CAMERA_MODE_TIMEOUT); + if (ret != 0) + { + return ret; + } + +#ifdef ISX012_FRAME_SKIP_EN + mute_cnt = isx012_getreg(priv, MUTECNT, sizeof(mute_cnt)); + isx012_putreg(priv, INTCLR0, VINT_STS, 1); + for (i = 0; i < mute_cnt; i++) + { + /* Wait Next VINT */ + + ret = isx012_chk_int_state(priv, VINT_STS, VINT_DELAY_TIME, + VINT_WAIT_TIME, VINT_TIMEOUT); + if (ret != 0) + { + return ret; + } + } +#endif /* ISX012_FRAME_SKIP_EN */ + } + + priv->mode = REGVAL_MODESEL_MON; + + return OK; +} + +int init_isx012(FAR struct isx012_dev_s *priv) +{ + int ret; + +#ifdef ISX012_NOT_USE_NSTBY + board_isx012_release_sleep(); + board_isx012_release_reset(); + nxsig_usleep(6000); +#else + board_isx012_release_reset(); + nxsig_usleep(6000); +#endif + +#ifdef ISX012_CHECK_IN_DETAIL + /* check the chip id */ + + ret = isx012_chipid(priv); + if (ret < 0) + { + imagererr("isx012_chipid failed: %d\n", ret); + board_isx012_set_reset(); + return ret; + } +#endif + + /* Wait OM_CHANGED Power OFF -> PreSleep */ + + ret = isx012_chk_int_state(priv, OM_CHANGED_STS, DEVICE_STATE_DELAY_TIME, + DEVICE_STATE_WAIT_TIME, DEVICE_STATE_TIMEOUT); + if (ret != OK) + { + imagererr("OM_CHANGED_STS(PreSleep) is Not occurred: %d\n", ret); + return ret; + } + + priv->state = STATE_ISX012_PRESLEEP; + +#ifndef ISX012_NOT_USE_NSTBY + /* set the isx012 clock */ + + /* Write INCK_SET register ISX012 change state PreSleep -> Sleep */ + + ret = isx012_putreglist(priv, g_isx012_presleep, ISX012_PRESLEEP_NENTRIES); + if (ret != OK) + { + imagererr("isx012_putreglist(INCK_SET) failed: %d\n", ret); + return ret; + } + + /* Wait OM_CHANGED PreSleep -> Sleep */ + + ret = isx012_chk_int_state(priv, OM_CHANGED_STS, DEVICE_STATE_DELAY_TIME, + DEVICE_STATE_WAIT_TIME, DEVICE_STATE_TIMEOUT); + if (ret != OK) + { + imagererr("OM_CHANGED_STS(Sleep) is Not occurred: %d\n", ret); + return ret; + } +#endif + + priv->state = STATE_ISX012_SLEEP; + priv->i2c_freq = I2CFREQ_FAST; + + /* initialize the isx012 hardware */ + + ret = isx012_putreglist(priv, g_isx012_def_init, ISX012_RESET_NENTRIES); + if (ret < 0) + { + imagererr("isx012_putreglist failed: %d\n", ret); + board_isx012_set_reset(); + return ret; + } + + /* Set shading adjustment */ + + ret = isx012_set_shd(priv); + if (ret < 0) + { + imagererr("isx012_set_shd failed: %d\n", ret); + board_isx012_set_reset(); + return ret; + } + + return ret; +} + +static int isx012_init(void) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + int ret = 0; + + ret = board_isx012_power_on(); + if (ret < 0) + { + imagererr("Failed to power on %d\n", ret); + return ret; + } + + ret = init_isx012(priv); + if (ret < 0) + { + imagererr("Failed to init_isx012 %d\n", ret); + board_isx012_set_reset(); + board_isx012_power_off(); + return ret; + } + + return ret; +} + +static int isx012_uninit(void) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + + int ret = 0; + + if (priv->state == STATE_ISX012_ACTIVE) + { + board_isx012_set_sleep(1); + } + + board_isx012_set_reset(); + + ret = board_isx012_power_off(); + if (ret < 0) + { + imagererr("Failed to power off %d\n", ret); + return ret; + } + + priv->i2c_freq = I2CFREQ_STANDARD; + priv->state = STATE_ISX012_POWEROFF; + + return ret; +} + +static int8_t isx012_get_maximum_fps(uint8_t nr_fmt, + FAR imgsensor_format_t *fmt) +{ + int8_t max_fps = REGVAL_FPSTYPE_120FPS; + uint16_t main_w; + uint16_t main_h; + uint16_t sub_w; + uint16_t sub_h; + + main_w = fmt[IMGSENSOR_FMT_MAIN].width; + main_h = fmt[IMGSENSOR_FMT_MAIN].height; + + switch (fmt[IMGSENSOR_FMT_MAIN].pixelformat) + { + case IMGSENSOR_PIX_FMT_UYVY: /* YUV 4:2:2 */ + case IMGSENSOR_PIX_FMT_RGB565: /* RGB565 */ + + if ((main_w < OUT_YUV_HSIZE_MIN) || + (main_h < OUT_YUV_VSIZE_MIN) || + (main_w > OUT_YUV_15FPS_HSIZE_MAX) || + (main_h > OUT_YUV_15FPS_VSIZE_MAX)) + { + /* IN frame size is out of range */ + + return -EINVAL; + } + else if ((main_w <= OUT_YUV_120FPS_HSIZE_MAX) && + (main_h <= OUT_YUV_120FPS_VSIZE_MAX)) + { + max_fps = REGVAL_FPSTYPE_120FPS; + } + else + { + max_fps = REGVAL_FPSTYPE_60FPS; + } + + break; + + case IMGSENSOR_PIX_FMT_JPEG: /* JPEG */ + + if ((main_w < OUT_JPG_HSIZE_MIN) || + (main_h < OUT_JPG_VSIZE_MIN) || + (main_w > OUT_JPG_15FPS_HSIZE_MAX) || + (main_h > OUT_JPG_15FPS_VSIZE_MAX)) + { + /* IN frame size is out of range */ + + return -EINVAL; + } + else if ((main_w <= OUT_JPG_120FPS_HSIZE_MAX) && + (main_h <= OUT_JPG_120FPS_VSIZE_MAX)) + { + max_fps = REGVAL_FPSTYPE_120FPS; + } + else if ((main_w <= OUT_JPG_60FPS_HSIZE_MAX) && + (main_h <= OUT_JPG_60FPS_VSIZE_MAX)) + { + max_fps = REGVAL_FPSTYPE_60FPS; + } + else if ((main_w <= OUT_JPG_30FPS_HSIZE_MAX) && + (main_h <= OUT_JPG_30FPS_VSIZE_MAX)) + { + max_fps = REGVAL_FPSTYPE_30FPS; + } + else + { + max_fps = REGVAL_FPSTYPE_15FPS; + } + + break; + + case IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + sub image */ + + if (nr_fmt == 1) + { + sub_w = OUT_YUV_HSIZE_MIN; + sub_h = OUT_YUV_VSIZE_MIN; + } + else + { + if (fmt[IMGSENSOR_FMT_SUB].pixelformat + != IMGSENSOR_PIX_FMT_UYVY) + { + /* Unsupported pixel format */ + + return -EINVAL; + } + + sub_w = fmt[IMGSENSOR_FMT_SUB].width; + sub_h = fmt[IMGSENSOR_FMT_SUB].height; + } + + if ((main_w < OUT_JPG_HSIZE_MIN) || + (main_h < OUT_JPG_VSIZE_MIN) || + (main_w > OUT_JPGINT_15FPS_HSIZE_MAX) || + (main_h > OUT_JPGINT_15FPS_VSIZE_MAX) || + (sub_w < OUT_YUV_HSIZE_MIN) || + (sub_h < OUT_YUV_VSIZE_MIN) || + (sub_w > OUT_YUVINT_30FPS_HSIZE_MAX) || + (sub_h > OUT_YUVINT_30FPS_VSIZE_MAX)) + { + /* IN frame size is out of range */ + + return -EINVAL; + } + else if ((main_w <= OUT_JPGINT_30FPS_HSIZE_MAX) && + (main_h <= OUT_JPGINT_30FPS_VSIZE_MAX)) + { + max_fps = REGVAL_FPSTYPE_30FPS; + } + else + { + max_fps = REGVAL_FPSTYPE_15FPS; + } + + break; + + default: + return -EINVAL; + } + + return max_fps; +} + +static int isx012_replace_frameinterval_to_regval + (FAR imgsensor_interval_t *interval) +{ + /* Avoid multiplication overflow */ + + if ((interval->denominator * 2) / 2 != interval->denominator) + { + return -EINVAL; + } + + /* Avoid division by zero */ + + if (interval->numerator == 0) + { + return -EINVAL; + } + + /* Support only 1/x or 2/x. */ + + if (((interval->denominator * 2) % interval->numerator) != 0) + { + return -EINVAL; + } + + /* Switch by FPS * 2 */ + + switch ((interval->denominator * 2) / interval->numerator) + { + case 240 : /* 120FPS */ + return REGVAL_FPSTYPE_120FPS; + + case 120 : /* 60FPS */ + return REGVAL_FPSTYPE_60FPS; + + case 60 : /* 30FPS */ + return REGVAL_FPSTYPE_30FPS; + + case 30 : /* 15FPS */ + return REGVAL_FPSTYPE_15FPS; + + case 20 : /* 10FPS */ + return REGVAL_FPSTYPE_10FPS; + + case 15 : /* 7.5FPS */ + return REGVAL_FPSTYPE_7_5FPS; + + case 12 : /* 6FPS */ + return REGVAL_FPSTYPE_6FPS; + + case 10 : /* 5FPS */ + return REGVAL_FPSTYPE_5FPS; + + default : + return -EINVAL; + } +} + +static int isx012_validate_frame_setting(imgsensor_stream_type_t type, + uint8_t nr_fmt, + FAR imgsensor_format_t *fmt, + FAR imgsensor_interval_t *interval) +{ + int max_fps; + int arg_fps; + + if ((fmt == NULL) || + (interval == NULL)) + { + return -EINVAL; + } + + if ((nr_fmt < 1) || (nr_fmt > 2)) + { + return -EINVAL; + } + + max_fps = isx012_get_maximum_fps(nr_fmt, fmt); + if (max_fps == -EINVAL) + { + return -EINVAL; + } + + arg_fps = isx012_replace_frameinterval_to_regval(interval); + if (arg_fps == -EINVAL) + { + return -EINVAL; + } + + if (max_fps > arg_fps) + { + return -EINVAL; + } + + return OK; +} + +static int isx012_start_capture(imgsensor_stream_type_t type, + uint8_t nr_fmt, + FAR imgsensor_format_t *fmt, + FAR imgsensor_interval_t *interval) +{ + int ret; + + FAR struct isx012_dev_s *priv = &g_isx012_private; + + ret = isx012_validate_frame_setting(type, nr_fmt, fmt, interval); + if (ret != OK) + { + return ret; + } + + return isx012_set_mode_param(priv, type, nr_fmt, fmt, interval); +} + +static int isx012_stop_capture(imgsensor_stream_type_t type) +{ + return OK; +} + +static int isx012_get_supported_value + (uint32_t id, FAR imgsensor_supported_value_t *value) +{ + int ret = OK; + imgsensor_capability_range_t *range = &value->u.range; + imgsensor_capability_discrete_t *discrete = &value->u.discrete; + imgsensor_capability_elems_t *elems = &value->u.elems; + + ASSERT(value); + + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_BRIGHTNESS; + range->maximum = ISX012_MAX_BRIGHTNESS; + range->step = ISX012_STEP_BRIGHTNESS; + range->default_value = ISX012_DEF_BRIGHTNESS; + + break; + + case IMGSENSOR_ID_CONTRAST: + value->type = IMGSENSOR_CTRL_TYPE_U8FIXEDPOINT_Q7; + range->minimum = ISX012_MIN_CONTRAST; + range->maximum = ISX012_MAX_CONTRAST; + range->step = ISX012_STEP_CONTRAST; + range->default_value = ISX012_DEF_CONTRAST; + + break; + + case IMGSENSOR_ID_SATURATION: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_SATURATION; + range->maximum = ISX012_MAX_SATURATION; + range->step = ISX012_STEP_SATURATION; + range->default_value = ISX012_DEF_SATURATION; + + break; + + case IMGSENSOR_ID_HUE: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_HUE; + range->maximum = ISX012_MAX_HUE; + range->step = ISX012_STEP_HUE; + range->default_value = ISX012_DEF_HUE; + + break; + + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_AUTOWB; + range->maximum = ISX012_MAX_AUTOWB; + range->step = ISX012_STEP_AUTOWB; + range->default_value = ISX012_DEF_AUTOWB; + + break; + case IMGSENSOR_ID_GAMMA_CURVE: + value->type = IMGSENSOR_CTRL_TYPE_U16; + elems->minimum = ISX012_MIN_GAMMACURVE; + elems->maximum = ISX012_MAX_GAMMACURVE; + elems->step = ISX012_STEP_GAMMACURVE; + elems->nr_elems = ISX012_ELEMS_GAMMACURVE; + + break; + + case IMGSENSOR_ID_EXPOSURE: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER_TIMES_3; + range->minimum = ISX012_MIN_EXPOSURE; + range->maximum = ISX012_MAX_EXPOSURE; + range->step = ISX012_STEP_EXPOSURE; + range->default_value = ISX012_DEF_EXPOSURE; + + break; + + case IMGSENSOR_ID_HFLIP_VIDEO: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_HFLIP; + range->maximum = ISX012_MAX_HFLIP; + range->step = ISX012_STEP_HFLIP; + range->default_value = ISX012_DEF_HFLIP; + + break; + + case IMGSENSOR_ID_VFLIP_VIDEO: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_VFLIP; + range->maximum = ISX012_MAX_VFLIP; + range->step = ISX012_STEP_VFLIP; + range->default_value = ISX012_DEF_VFLIP; + + break; + + case IMGSENSOR_ID_HFLIP_STILL: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_HFLIP_STILL; + range->maximum = ISX012_MAX_HFLIP_STILL; + range->step = ISX012_STEP_HFLIP_STILL; + range->default_value = ISX012_DEF_HFLIP_STILL; + + break; + + case IMGSENSOR_ID_VFLIP_STILL: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_VFLIP_STILL; + range->maximum = ISX012_MAX_VFLIP_STILL; + range->step = ISX012_STEP_VFLIP_STILL; + range->default_value = ISX012_DEF_VFLIP_STILL; + + break; + + case IMGSENSOR_ID_SHARPNESS: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_SHARPNESS; + range->maximum = ISX012_MAX_SHARPNESS; + range->step = ISX012_STEP_SHARPNESS; + range->default_value = ISX012_DEF_SHARPNESS; + + break; + + case IMGSENSOR_ID_COLOR_KILLER: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_COLORKILLER; + range->maximum = ISX012_MAX_COLORKILLER; + range->step = ISX012_STEP_COLORKILLER; + range->default_value = ISX012_DEF_COLORKILLER; + + break; + + case IMGSENSOR_ID_COLORFX: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU; + discrete->nr_values + = ARRAY_NENTRIES(g_isx012_colorfx_actual); + discrete->values = g_isx012_colorfx_actual; + discrete->default_value = IMGSENSOR_COLORFX_NONE; + + break; + + case IMGSENSOR_ID_EXPOSURE_AUTO: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_EXPOSUREAUTO; + range->maximum = ISX012_MAX_EXPOSUREAUTO; + range->step = ISX012_STEP_EXPOSUREAUTO; + range->default_value = ISX012_DEF_EXPOSUREAUTO; + + break; + + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_EXPOSURETIME; + range->maximum = ISX012_MAX_EXPOSURETIME; + range->step = ISX012_STEP_EXPOSURETIME; + range->default_value = ISX012_DEF_EXPOSURETIME; + + break; + + case IMGSENSOR_ID_EXPOSURE_METERING: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU; + discrete->nr_values + = ARRAY_NENTRIES(g_isx012_photometry_actual); + discrete->values = g_isx012_photometry_actual; + discrete->default_value + = IMGSENSOR_EXPOSURE_METERING_AVERAGE; + + break; + + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU; + discrete->nr_values = ARRAY_NENTRIES(g_isx012_presetwb_actual); + discrete->values = g_isx012_presetwb_actual; + discrete->default_value = IMGSENSOR_WHITE_BALANCE_AUTO; + + break; + + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + value->type = IMGSENSOR_CTRL_TYPE_BOOLEAN; + range->minimum = ISX012_MIN_YGAMMA; + range->maximum = ISX012_MAX_YGAMMA; + range->step = ISX012_STEP_YGAMMA; + range->default_value = ISX012_DEF_YGAMMA; + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU; + discrete->nr_values = ARRAY_NENTRIES(g_isx012_iso_actual); + discrete->values = g_isx012_iso_actual; + discrete->default_value = 0; + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_ISOAUTO; + range->maximum = ISX012_MAX_ISOAUTO; + range->step = ISX012_STEP_ISOAUTO; + range->default_value = ISX012_DEF_ISOAUTO; + + break; + + case IMGSENSOR_ID_3A_LOCK: + value->type = IMGSENSOR_CTRL_TYPE_BITMASK; + range->minimum = ISX012_MIN_3ALOCK; + range->maximum = ISX012_MAX_3ALOCK; + range->step = ISX012_STEP_3ALOCK; + range->default_value = ISX012_DEF_3ALOCK; + + break; + + case IMGSENSOR_ID_3A_PARAMETER: + value->type = IMGSENSOR_CTRL_TYPE_U16; + elems->minimum = 0; + elems->maximum = 65535; + elems->step = 1; + elems->nr_elems = ISX012_ELEMS_3APARAM; + + break; + + case IMGSENSOR_ID_3A_STATUS: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = 0; + range->maximum = 3; + range->step = 1; + range->default_value = 3; + + break; + + case IMGSENSOR_ID_JPEG_QUALITY: + value->type = IMGSENSOR_CTRL_TYPE_INTEGER; + range->minimum = ISX012_MIN_JPGQUALITY; + range->maximum = ISX012_MAX_JPGQUALITY; + range->step = ISX012_STEP_JPGQUALITY; + range->default_value = ISX012_DEF_JPGQUALITY; + + break; + + default: /* Unsupported parameter */ + ret = -EINVAL; + + break; + } + + return ret; +} + +static int isx012_get_value(uint32_t id, + uint32_t size, + FAR imgsensor_value_t *value) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + uint16_t readvalue; + uint8_t cnt; + uint8_t threea_enable; + uint16_t read_src; + uint16_t *read_dst; + int ret = OK; + + ASSERT(value); + + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + readvalue = isx012_getreg(priv, + ISX012_REG_BRIGHTNESS, + ISX012_SIZE_BRIGHTNESS); + + value->value32 = (int32_t)(int8_t)(0x00ff & readvalue); + break; + + case IMGSENSOR_ID_CONTRAST: + value->value32 = isx012_getreg(priv, + ISX012_REG_CONTRAST, + ISX012_SIZE_CONTRAST); + break; + + case IMGSENSOR_ID_SATURATION: + value->value32 = isx012_getreg(priv, + ISX012_REG_SATURATION, + ISX012_SIZE_SATURATION); + break; + + case IMGSENSOR_ID_HUE: + value->value32 = isx012_getreg(priv, + ISX012_REG_HUE, + ISX012_SIZE_HUE); + break; + + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + readvalue = isx012_getreg(priv, + ISX012_REG_AUTOWB, + ISX012_SIZE_AUTOWB); + + /* Convert to video driver's value */ + + value->value32 = (readvalue & REGVAL_CPUEXT_BIT_AWBSTOP) ? 0 : 1; + + break; + + case IMGSENSOR_ID_GAMMA_CURVE: + if (value->p_u16 == NULL) + { + return -EINVAL; + } + + if (size != ISX012_ELEMS_GAMMACURVE * sizeof(uint16_t)) + { + return -EINVAL; + } + + read_src = ISX012_REG_GAMMACURVE; + read_dst = value->p_u16; + + for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) + { + *read_dst = isx012_getreg(priv, + read_src, + ISX012_SIZE_GAMMACURVE); + read_src += ISX012_SIZE_GAMMACURVE; + read_dst++; + } + + break; + + case IMGSENSOR_ID_EXPOSURE: + readvalue = isx012_getreg(priv, + ISX012_REG_EXPOSURE, + ISX012_SIZE_EXPOSURE); + + value->value32 = (int32_t)(int8_t)(0x00ff & readvalue); + + break; + + case IMGSENSOR_ID_HFLIP_VIDEO: + readvalue = isx012_getreg(priv, + ISX012_REG_HFLIP, + ISX012_SIZE_HFLIP); + + value->value32 = (readvalue & REGVAL_READVECT_BIT_H) ? 1 : 0; + + break; + + case IMGSENSOR_ID_VFLIP_VIDEO: + readvalue = isx012_getreg(priv, + ISX012_REG_VFLIP, + ISX012_SIZE_VFLIP); + + value->value32 = (readvalue & REGVAL_READVECT_BIT_V) ? 1 : 0; + + break; + + case IMGSENSOR_ID_HFLIP_STILL: + readvalue = isx012_getreg(priv, + ISX012_REG_HFLIP_STILL, + ISX012_SIZE_HFLIP_STILL); + + value->value32 = (readvalue & REGVAL_READVECT_BIT_H) ? 1 : 0; + + break; + + case IMGSENSOR_ID_VFLIP_STILL: + readvalue = isx012_getreg(priv, + ISX012_REG_VFLIP_STILL, + ISX012_SIZE_VFLIP_STILL); + + value->value32 = (readvalue & REGVAL_READVECT_BIT_V) ? 1 : 0; + + break; + + case IMGSENSOR_ID_SHARPNESS: + value->value32 = isx012_getreg(priv, + ISX012_REG_SHARPNESS, + ISX012_SIZE_SHARPNESS); + break; + + case IMGSENSOR_ID_COLOR_KILLER: + readvalue = isx012_getreg(priv, + ISX012_REG_COLORKILLER, + ISX012_SIZE_COLORKILLER); + + value->value32 = (readvalue == REGVAL_EFFECT_MONOTONE) ? 1 : 0; + + break; + + case IMGSENSOR_ID_COLORFX: + readvalue = isx012_getreg(priv, + ISX012_REG_COLOREFFECT, + ISX012_SIZE_COLOREFFECT); + + ret = -EINVAL; + for (cnt = 0; cnt < ARRAY_NENTRIES(g_isx012_colorfx_regval); cnt++) + { + if (g_isx012_colorfx_regval[cnt] == readvalue) + { + value->value32 = g_isx012_colorfx_actual[cnt]; + ret = OK; + break; + } + } + + break; + + case IMGSENSOR_ID_EXPOSURE_AUTO: + readvalue = isx012_getreg(priv, + ISX012_REG_EXPOSURETIME, + ISX012_SIZE_EXPOSURETIME); + + value->value32 = readvalue ? + IMGSENSOR_EXPOSURE_MANUAL : IMGSENSOR_EXPOSURE_AUTO; + + break; + + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + value->value32 = isx012_getreg(priv, + ISX012_REG_EXPOSURETIME, + ISX012_SIZE_EXPOSURETIME); + + break; + + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + readvalue = isx012_getreg(priv, + ISX012_REG_PRESETWB, + ISX012_SIZE_PRESETWB); + + for (cnt = 0; cnt < ARRAY_NENTRIES(g_isx012_presetwb_regval); cnt++) + { + if (g_isx012_presetwb_regval[cnt] == readvalue) + { + value->value32 = g_isx012_presetwb_actual[cnt]; + ret = OK; + break; + } + } + + break; + + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + readvalue = isx012_getreg(priv, + ISX012_REG_YGAMMA, + ISX012_SIZE_YGAMMA); + value->value32 = readvalue ? 0 : 1; + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY: + readvalue = isx012_getreg(priv, ISX012_REG_ISO, ISX012_SIZE_ISO); + + ret = -EINVAL; + for (cnt = 0; cnt < ARRAY_NENTRIES(g_isx012_presetwb_regval); cnt++) + { + if (g_isx012_iso_regval[cnt] == readvalue) + { + value->value32 = g_isx012_iso_actual[cnt]; + ret = OK; + break; + } + } + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + readvalue = isx012_getreg(priv, + ISX012_REG_ISOAUTO, + ISX012_SIZE_ISOAUTO); + + value->value32 = (readvalue == REGVAL_ISO_AUTO) ? + IMGSENSOR_ISO_SENSITIVITY_AUTO : + IMGSENSOR_ISO_SENSITIVITY_MANUAL; + + break; + + case IMGSENSOR_ID_EXPOSURE_METERING: + readvalue = isx012_getreg(priv, + ISX012_REG_PHOTOMETRY, + ISX012_SIZE_PHOTOMETRY); + + ret = -EINVAL; + for (cnt = 0; + cnt < ARRAY_NENTRIES(g_isx012_photometry_regval); + cnt++) + { + if (g_isx012_photometry_regval[cnt] == readvalue) + { + value->value32 = g_isx012_photometry_actual[cnt]; + ret = OK; + break; + } + } + + break; + + case IMGSENSOR_ID_3A_PARAMETER: + if (value->p_u16 == NULL) + { + return -EINVAL; + } + + if (size != ISX012_ELEMS_3APARAM * sizeof(uint16_t)) + { + return -EINVAL; + } + + /* Get AWB parameter */ + + value->p_u16[0] = isx012_getreg(priv, RATIO_R, 2); + value->p_u16[1] = isx012_getreg(priv, RATIO_B, 2); + + /* Get AE parameter */ + + value->p_u16[2] = isx012_getreg(priv, AELEVEL, 2); + + break; + + case IMGSENSOR_ID_3A_STATUS: + + /* Initialize returned status */ + + value->value32 = IMGSENSOR_3A_STATUS_STABLE; + + /* Get AWB/AE enable or not */ + + threea_enable = isx012_getreg(priv, CPUEXT, 1); + + if ((threea_enable & REGVAL_CPUEXT_BIT_AWBSTOP) + != REGVAL_CPUEXT_BIT_AWBSTOP) + { + readvalue = isx012_getreg(priv, AWBSTS, 1); + if (readvalue != REGVAL_AWBSTS_STOP) /* AWB is not stopped */ + { + value->value32 |= IMGSENSOR_3A_STATUS_AWB_OPERATING; + } + } + + if ((threea_enable & REGVAL_CPUEXT_BIT_AESTOP) + != REGVAL_CPUEXT_BIT_AESTOP) + { + readvalue = isx012_getreg(priv, AESTS, 1); + if (readvalue != REGVAL_AESTS_STOP) /* AE is not stopped */ + { + value->value32 |= IMGSENSOR_3A_STATUS_AE_OPERATING; + } + } + break; + + case IMGSENSOR_ID_JPEG_QUALITY: + value->value32 = isx012_getreg(priv, + ISX012_REG_JPGQUALITY, + ISX012_SIZE_JPGQUALITY); + break; + + default: /* Unsupported id */ + + ret = -EINVAL; + break; + } + + return ret; +} + +static int isx012_set_value(uint32_t id, + uint32_t size, + FAR imgsensor_value_t value) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + int ret = -EINVAL; + uint8_t cnt; + uint16_t *write_src; + uint16_t write_dst; + uint16_t regval; + uint16_t exposure_time_lsb; + uint16_t exposure_time_msb; + + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_BRIGHTNESS, + ISX012_MAX_BRIGHTNESS, + ISX012_STEP_BRIGHTNESS); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_BRIGHTNESS, + value.value32, + ISX012_SIZE_BRIGHTNESS); + break; + + case IMGSENSOR_ID_CONTRAST: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_CONTRAST, + ISX012_MAX_CONTRAST, + ISX012_STEP_CONTRAST); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_CONTRAST, + value.value32, + ISX012_SIZE_CONTRAST); + break; + + case IMGSENSOR_ID_SATURATION: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_SATURATION, + ISX012_MAX_SATURATION, + ISX012_STEP_SATURATION); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_SATURATION, + value.value32, + ISX012_SIZE_SATURATION); + break; + + case IMGSENSOR_ID_HUE: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_HUE, + ISX012_MAX_HUE, + ISX012_STEP_HUE); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_HUE, + value.value32, + ISX012_SIZE_HUE); + break; + + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_AUTOWB, + ISX012_MAX_AUTOWB, + ISX012_STEP_AUTOWB); + if (ret != OK) + { + break; + } + + regval = isx012_getreg(priv, + ISX012_REG_AUTOWB, + ISX012_SIZE_AUTOWB); + + if (value.value32) + { + /* Because true means setting auto white balance + * turn off the stop bit + */ + + regval &= ~REGVAL_CPUEXT_BIT_AWBSTOP; + } + else + { + /* Because false means stopping auto white balance, + * turn on the stop bit. + */ + + regval |= REGVAL_CPUEXT_BIT_AWBSTOP; + } + + ret = isx012_putreg(priv, + ISX012_REG_AUTOWB, + regval, + ISX012_SIZE_AUTOWB); + break; + + case IMGSENSOR_ID_GAMMA_CURVE: + if (value.p_u16 == NULL) + { + return -EINVAL; + } + + if (size != ISX012_ELEMS_GAMMACURVE * 2) + { + return -EINVAL; + } + + write_src = value.p_u16; + write_dst = ISX012_REG_GAMMACURVE; + + for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) + { + ret = VALIDATE_VALUE(*write_src, + ISX012_MIN_GAMMACURVE, + ISX012_MAX_GAMMACURVE, + ISX012_STEP_GAMMACURVE); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + write_dst, + *write_src, + ISX012_SIZE_GAMMACURVE); + + write_src++; + write_dst += ISX012_SIZE_GAMMACURVE; + } + + break; + + case IMGSENSOR_ID_EXPOSURE: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_EXPOSURE, + ISX012_MAX_EXPOSURE, + ISX012_STEP_EXPOSURE); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_EXPOSURE, + value.value32, + ISX012_SIZE_EXPOSURE); + + break; + + case IMGSENSOR_ID_HFLIP_VIDEO: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_HFLIP, + ISX012_MAX_HFLIP, + ISX012_STEP_HFLIP); + if (ret != OK) + { + break; + } + + regval = isx012_getreg(priv, + ISX012_REG_HFLIP, + ISX012_SIZE_HFLIP); + + if (value.value32) + { + regval |= REGVAL_READVECT_BIT_H; + } + else + { + regval &= ~REGVAL_READVECT_BIT_H; + } + + ret = isx012_putreg(priv, + ISX012_REG_HFLIP, + regval, + ISX012_SIZE_HFLIP); + break; + + case IMGSENSOR_ID_VFLIP_VIDEO: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_VFLIP, + ISX012_MAX_VFLIP, + ISX012_STEP_VFLIP); + if (ret != OK) + { + break; + } + + regval = isx012_getreg(priv, + ISX012_REG_VFLIP, + ISX012_SIZE_VFLIP); + + if (value.value32) + { + regval |= REGVAL_READVECT_BIT_V; + } + else + { + regval &= ~REGVAL_READVECT_BIT_V; + } + + ret = isx012_putreg(priv, + ISX012_REG_VFLIP, + regval, + ISX012_SIZE_VFLIP); + break; + + case IMGSENSOR_ID_HFLIP_STILL: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_HFLIP_STILL, + ISX012_MAX_HFLIP_STILL, + ISX012_STEP_HFLIP_STILL); + if (ret != OK) + { + break; + } + + regval = isx012_getreg(priv, + ISX012_REG_HFLIP_STILL, + ISX012_SIZE_HFLIP_STILL); + + if (value.value32) + { + regval |= REGVAL_READVECT_BIT_H; + } + else + { + regval &= ~REGVAL_READVECT_BIT_H; + } + + ret = isx012_putreg(priv, + ISX012_REG_HFLIP_STILL, + regval, + ISX012_SIZE_HFLIP_STILL); + + break; + + case IMGSENSOR_ID_VFLIP_STILL: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_VFLIP_STILL, + ISX012_MAX_VFLIP_STILL, + ISX012_STEP_VFLIP_STILL); + if (ret != OK) + { + break; + } + + regval = isx012_getreg(priv, + ISX012_REG_VFLIP_STILL, + ISX012_SIZE_VFLIP_STILL); + + if (value.value32) + { + regval |= REGVAL_READVECT_BIT_V; + } + else + { + regval &= ~REGVAL_READVECT_BIT_V; + } + + ret = isx012_putreg(priv, + ISX012_REG_VFLIP_STILL, + regval, + ISX012_SIZE_VFLIP_STILL); + break; + + case IMGSENSOR_ID_SHARPNESS: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_SHARPNESS, + ISX012_MAX_SHARPNESS, + ISX012_STEP_SHARPNESS); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_SHARPNESS, + value.value32, + ISX012_SIZE_SHARPNESS); + break; + + case IMGSENSOR_ID_COLOR_KILLER: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_COLORKILLER, + ISX012_MAX_COLORKILLER, + ISX012_STEP_COLORKILLER); + if (ret != OK) + { + break; + } + + ret = isx012_putreg + (priv, + ISX012_REG_COLORKILLER, + value.value32 ? REGVAL_EFFECT_MONOTONE : REGVAL_EFFECT_NONE, + ISX012_SIZE_COLORKILLER); + + break; + + case IMGSENSOR_ID_COLORFX: + for (cnt = 0; cnt < ARRAY_NENTRIES(g_isx012_colorfx_actual); cnt++) + { + if (g_isx012_colorfx_actual[cnt] == value.value32) + { + ret = isx012_putreg(priv, + ISX012_REG_COLOREFFECT, + g_isx012_colorfx_regval[cnt], + ISX012_SIZE_COLOREFFECT); + break; + } + } + + break; + + case IMGSENSOR_ID_EXPOSURE_AUTO: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_EXPOSUREAUTO, + ISX012_MAX_EXPOSUREAUTO, + ISX012_STEP_EXPOSUREAUTO); + if (ret != OK) + { + break; + } + + if (value.value32 == IMGSENSOR_EXPOSURE_AUTO) + { + /* Register is the same as IMGSENSOR_ID_EXPOSURE_ABSOLUTE. + * If this register value = REGVAL_EXPOSURETIME_AUTO(=0), + * it means auto. Otherwise, it means manual. + */ + + ret = isx012_putreg(priv, + ISX012_REG_EXPOSURETIME, + REGVAL_EXPOSURETIME_AUTO, + ISX012_SIZE_EXPOSURETIME); + } + else + { + /* In manual case, read current value of register which + * value adjusted automatically by ISX012 HW is set to. + * It has 32bits length which is composed of LSB 16bits + * and MSB 16bits. + */ + + exposure_time_lsb = isx012_getreg + (priv, + ISX012_REG_EXPOSUREAUTOVALUE_LSB, + ISX012_SIZE_EXPOSUREAUTOVALUE); + exposure_time_msb = isx012_getreg + (priv, + ISX012_REG_EXPOSUREAUTOVALUE_MSB, + ISX012_SIZE_EXPOSUREAUTOVALUE); + + /* Register value adjusted automatically by ISX012 HW + * has the different unit from manual value register. + * automatic value register : 1 microsec unit + * manual value register : 100 microsec unit + */ + + regval = (uint16_t)(((exposure_time_msb << 16) + | exposure_time_lsb) + / ISX012_UNIT_EXPOSURETIME_US); + ret = isx012_putreg(priv, + ISX012_REG_EXPOSURETIME, + regval, + ISX012_SIZE_EXPOSURETIME); + } + + break; + + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_EXPOSURETIME, + ISX012_MAX_EXPOSURETIME, + ISX012_STEP_EXPOSURETIME); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_EXPOSURETIME, + value.value32, + ISX012_SIZE_EXPOSURETIME); + break; + + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_YGAMMA, + ISX012_MAX_YGAMMA, + ISX012_STEP_YGAMMA); + if (ret != OK) + { + break; + } + + if (value.value32) + { + regval = REGVAL_YGAMMA_AUTO; + } + else + { + regval = REGVAL_YGAMMA_OFF; + } + + ret = isx012_putreg + (priv, + ISX012_REG_YGAMMA, + value.value32 ? REGVAL_YGAMMA_AUTO : REGVAL_YGAMMA_OFF, + ISX012_SIZE_YGAMMA); + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY: + for (cnt = 0; cnt < ARRAY_NENTRIES(g_isx012_iso_actual); cnt++) + { + if (g_isx012_iso_actual[cnt] + == value.value32) + { + ret = isx012_putreg(priv, + ISX012_REG_ISO, + g_isx012_iso_regval[cnt], + ISX012_SIZE_ISO); + break; + } + } + + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_ISOAUTO, + ISX012_MAX_ISOAUTO, + ISX012_STEP_ISOAUTO); + if (ret != OK) + { + break; + } + + if (value.value32 == IMGSENSOR_ISO_SENSITIVITY_AUTO) + { + ret = isx012_putreg(priv, + ISX012_REG_ISOAUTO, + REGVAL_ISO_AUTO, + ISX012_SIZE_ISOAUTO); + } + else + { + /* In manual case, read auto adjust value and set it */ + + regval = isx012_getreg(priv, + ISX012_REG_ISOAUTOVALUE, + ISX012_SIZE_ISOAUTOVALUE); + ret = isx012_putreg(priv, + ISX012_REG_ISO, + regval, + ISX012_SIZE_ISO); + } + + break; + + case IMGSENSOR_ID_EXPOSURE_METERING: + for (cnt = 0; + cnt < ARRAY_NENTRIES(g_isx012_photometry_actual); + cnt++) + { + if (g_isx012_photometry_actual[cnt] + == value.value32) + { + ret = isx012_putreg(priv, + ISX012_REG_PHOTOMETRY, + g_isx012_photometry_regval[cnt], + ISX012_SIZE_PHOTOMETRY); + break; + } + } + + break; + + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + for (cnt = 0; + cnt < ARRAY_NENTRIES(g_isx012_presetwb_actual); + cnt++) + { + if (g_isx012_presetwb_actual[cnt] == value.value32) + { + ret = isx012_putreg(priv, + ISX012_REG_PRESETWB, + g_isx012_presetwb_regval[cnt], + ISX012_SIZE_PRESETWB); + break; + } + } + + break; + + case IMGSENSOR_ID_3A_LOCK: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_3ALOCK, + ISX012_MAX_3ALOCK, + ISX012_STEP_3ALOCK); + if (ret != OK) + { + break; + } + + regval = 0; + + if ((value.value32 & IMGSENSOR_LOCK_EXPOSURE) + == IMGSENSOR_LOCK_EXPOSURE) + { + regval |= REGVAL_CPUEXT_BIT_AESTOP; + } + + if ((value.value32 & IMGSENSOR_LOCK_WHITE_BALANCE) + == IMGSENSOR_LOCK_WHITE_BALANCE) + { + regval |= REGVAL_CPUEXT_BIT_AWBSTOP; + } + + ret = isx012_putreg(priv, + ISX012_REG_3ALOCK, + regval, + ISX012_SIZE_3ALOCK); + + break; + + case IMGSENSOR_ID_3A_PARAMETER: + + /* AWB parameter : red */ + + ret = isx012_putreg(priv, INIT_CONT_INR, value.p_u16[0], 2); + ret = isx012_putreg(priv, INIT_CONT_OUTR, value.p_u16[0], 2); + + /* AWB parameter : blue */ + + ret = isx012_putreg(priv, INIT_CONT_INB, value.p_u16[1], 2); + ret = isx012_putreg(priv, INIT_CONT_OUTB, value.p_u16[1], 2); + + /* AE parameter */ + + ret = isx012_putreg(priv, AE_START_LEVEL, value.p_u16[2], 2); + + break; + + case IMGSENSOR_ID_JPEG_QUALITY: + ret = VALIDATE_VALUE(value.value32, + ISX012_MIN_JPGQUALITY, + ISX012_MAX_JPGQUALITY, + ISX012_STEP_JPGQUALITY); + if (ret != OK) + { + break; + } + + ret = isx012_putreg(priv, + ISX012_REG_JPGQUALITY, + value.value32, + ISX012_SIZE_JPGQUALITY); + break; + + default: /* Unsupported control id */ + + break; + } + + return ret; +} + +static int isx012_set_shd(FAR isx012_dev_t *priv) +{ + int ret; + int unit_cnt; + int size_cnt; + + /* At first, disable CXC and SHD */ + + ret = isx012_putreg(priv, SHD_EN, 0x50, 1); + if (ret < 0) + { + imagererr("isx012_putreg(disable CXC/SHD) failed: %d\n", ret); + return ret; + } + + /* Set CXC Validity */ + + ret = isx012_putreg(priv, CXC_VALID, 0x8282, 2); + if (ret < 0) + { + imagererr("isx012_putreg(CXC_VALID) failed: %d\n", ret); + return ret; + } + + /* Set CXC R Gb data */ + + for (unit_cnt = 0; unit_cnt < CXC_RGB_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < CXC_RGB_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + CXC_RGB_UNIT(unit_cnt, size_cnt), + g_isx012_cxc_rgb_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(CXC R Gb) failed: %d\n", ret); + return ret; + } + } + } + + /* Set CXC G Rb data */ + + for (unit_cnt = 0; unit_cnt < CXC_GRB_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < CXC_GRB_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + CXC_GRB_UNIT(unit_cnt, size_cnt), + g_isx012_cxc_grb_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(CXC G Rb) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD Validity */ + + ret = isx012_putreg(priv, SHD_VALID, 0x9191, 2); + if (ret < 0) + { + imagererr("isx012_putreg(SHD_VALID) failed: %d\n", ret); + return ret; + } + + /* Set SHD R Gb data */ + + for (unit_cnt = 0; unit_cnt < SHD_RGB_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < SHD_RGB_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + SHD_RGB_UNIT(unit_cnt, size_cnt), + g_isx012_shd_rgb_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(SHD R Gb) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD G Rb data */ + + for (unit_cnt = 0; unit_cnt < SHD_GRB_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < SHD_GRB_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + SHD_GRB_UNIT(unit_cnt, size_cnt), + g_isx012_shd_grb_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(SHD G Rb) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD R1 data */ + + for (unit_cnt = 0; unit_cnt < SHD_R1_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < SHD_R1_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + SHD_R1_UNIT(unit_cnt, size_cnt), + g_isx012_shd_r1_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(SHD R1) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD R2 data */ + + for (unit_cnt = 0; unit_cnt < SHD_R2_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < SHD_R2_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + SHD_R2_UNIT(unit_cnt, size_cnt), + g_isx012_shd_r2_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(SHD R2) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD B2 data */ + + for (unit_cnt = 0; unit_cnt < SHD_B2_DATA_UNIT_NUM; unit_cnt++) + { + for (size_cnt = 0; size_cnt < SHD_B2_DATA_UNIT_SIZE; size_cnt++) + { + ret = isx012_putreg(priv, + SHD_B2_UNIT(unit_cnt, size_cnt), + g_isx012_shd_b2_data[unit_cnt][size_cnt], + 1); + if (ret < 0) + { + imagererr("isx012_putreg(SHD B2) failed: %d\n", ret); + return ret; + } + } + } + + /* Set SHD thresholds data */ + + ret = isx012_putreglist(priv, g_isx012_shd_thresholds, + ISX012_SHD_THRESHOLDS_NENTRIES); + if (ret < 0) + { + imagererr("isx012_putreglist failed(SHD thresholds): %d\n", ret); + board_isx012_set_reset(); + return ret; + } + + /* Set SHD white balance data */ + + ret = isx012_putreglist(priv, g_isx012_shd_wb, ISX012_SHD_WB_NENTRIES); + if (ret < 0) + { + imagererr("isx012_putreglist(SHD white balance) failed: %d\n", ret); + board_isx012_set_reset(); + return ret; + } + + /* Enable CXC and SHD */ + + ret = isx012_putreg(priv, SHD_EN, 0x57, 1); + if (ret < 0) + { + imagererr("isx012_putreg(enable CXC/SHD) failed: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int isx012_initialize(FAR struct i2c_master_s *i2c) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + + /* Save i2c information */ + + priv->i2c = i2c; + priv->i2c_addr = ISX012_I2C_SLV_ADDR; + priv->i2c_freq = I2CFREQ_STANDARD; + + /* Regiser image sensor operations variable */ + + imgsensor_register(&g_isx012_ops); + + /* Initialize other information */ + + priv->state = STATE_ISX012_POWEROFF; + + return OK; +} + +int isx012_uninitialize(void) +{ + /* No procedure */ + + return OK; +} diff --git a/include/nuttx/video/isx012_range.h b/drivers/video/isx012_range.h similarity index 87% rename from include/nuttx/video/isx012_range.h rename to drivers/video/isx012_range.h index 22534fd636..698ba9d8d2 100644 --- a/include/nuttx/video/isx012_range.h +++ b/drivers/video/isx012_range.h @@ -1,5 +1,5 @@ /**************************************************************************** - * include/nuttx/video/isx012_range.h + * drivers/video/isx012_range.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -29,7 +29,6 @@ /* Definition for control brightness */ #define ISX012_TYPE_BRIGHTNESS V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_BRIGHTNESS "Brightness" #define ISX012_DEF_BRIGHTNESS (0) #define ISX012_MIN_BRIGHTNESS (-128) #define ISX012_MAX_BRIGHTNESS (127) @@ -40,7 +39,6 @@ /* Definition for control contrast */ #define ISX012_TYPE_CONTRAST V4L2_CTRL_TYPE_U8FIXEDPOINT_Q7 -#define ISX012_NAME_CONTRAST "Contrast" #define ISX012_DEF_CONTRAST (0x80) #define ISX012_MIN_CONTRAST (0x00) #define ISX012_MAX_CONTRAST (0xFF) @@ -51,7 +49,6 @@ /* Definition for control saturation */ #define ISX012_TYPE_SATURATION V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_SATURATION "Saturation" #define ISX012_DEF_SATURATION (0) #define ISX012_MIN_SATURATION (0) #define ISX012_MAX_SATURATION (255) @@ -62,7 +59,6 @@ /* Definition for control hue */ #define ISX012_TYPE_HUE V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_HUE "Hue" #define ISX012_DEF_HUE (0) #define ISX012_MIN_HUE (0) #define ISX012_MAX_HUE (255) @@ -73,7 +69,6 @@ /* Definition for control auto white balance */ #define ISX012_TYPE_AUTOWB V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_AUTOWB "Automatic white balance" #define ISX012_DEF_AUTOWB true #define ISX012_MIN_AUTOWB false #define ISX012_MAX_AUTOWB true @@ -84,7 +79,6 @@ /* Definition for control red balance */ #define ISX012_TYPE_REDBALANCE V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_REDBALANCE "Red balance" #define ISX012_DEF_REDBALANCE (0) #define ISX012_MIN_REDBALANCE (0) #define ISX012_MAX_REDBALANCE (65535) @@ -95,7 +89,6 @@ /* Definition for control blue balance */ #define ISX012_TYPE_BLUEBALANCE V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_BLUEBALANCE "Red balance" #define ISX012_DEF_BLUEBALANCE (0) #define ISX012_MIN_BLUEBALANCE (0) #define ISX012_MAX_BLUEBALANCE (65535) @@ -106,7 +99,6 @@ /* Definition for control gamma curve */ #define ISX012_TYPE_GAMMACURVE V4L2_CTRL_TYPE_U16 -#define ISX012_NAME_GAMMACURVE "Gamma adjustment(curve)" #define ISX012_DEF_GAMMACURVE (0) #define ISX012_MIN_GAMMACURVE (0) #define ISX012_MAX_GAMMACURVE (511) @@ -119,7 +111,6 @@ /* Definition for control exposure value */ #define ISX012_TYPE_EXPOSURE V4L2_CTRL_TYPE_INTEGER_TIMES_3 -#define ISX012_NAME_EXPOSURE "Exposure value" #define ISX012_DEF_EXPOSURE (0) #define ISX012_MIN_EXPOSURE (-6) #define ISX012_MAX_EXPOSURE (6) @@ -130,7 +121,6 @@ /* Definition for control horizontal mirroring(V4L2_BUF_TYPE_VIDEO_CAPTURE) */ #define ISX012_TYPE_HFLIP V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_HFLIP "Mirror horizontally(VIDEO)" #define ISX012_DEF_HFLIP false #define ISX012_MIN_HFLIP false #define ISX012_MAX_HFLIP true @@ -141,7 +131,6 @@ /* Definition for control vertical mirroring(V4L2_BUF_TYPE_VIDEO_CAPTURE) */ #define ISX012_TYPE_VFLIP V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_VFLIP "Mirror vertically(VIDEO)" #define ISX012_DEF_VFLIP false #define ISX012_MIN_VFLIP false #define ISX012_MAX_VFLIP true @@ -152,7 +141,6 @@ /* Definition for control horizontal mirroring(V4L2_BUF_TYPE_STILL_CAPTURE) */ #define ISX012_TYPE_HFLIP_STILL V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_HFLIP_STILL "Mirror horizontally(STILL)" #define ISX012_DEF_HFLIP_STILL false #define ISX012_MIN_HFLIP_STILL false #define ISX012_MAX_HFLIP_STILL true @@ -163,7 +151,6 @@ /* Definition for control vertical mirroring(V4L2_BUF_TYPE_STILL_CAPTURE) */ #define ISX012_TYPE_VFLIP_STILL V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_VFLIP_STILL "Mirror vertically(STILL)" #define ISX012_DEF_VFLIP_STILL false #define ISX012_MIN_VFLIP_STILL false #define ISX012_MAX_VFLIP_STILL true @@ -174,7 +161,6 @@ /* Definition for control sharpness */ #define ISX012_TYPE_SHARPNESS V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_SHARPNESS "Sharpness" #define ISX012_DEF_SHARPNESS (0) #define ISX012_MIN_SHARPNESS (0) #define ISX012_MAX_SHARPNESS (255) @@ -185,7 +171,6 @@ /* Definition for control color killer */ #define ISX012_TYPE_COLORKILLER V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_COLORKILLER "Color killer" #define ISX012_DEF_COLORKILLER false #define ISX012_MIN_COLORKILLER false #define ISX012_MAX_COLORKILLER true @@ -196,7 +181,6 @@ /* Definition for control color effect */ #define ISX012_TYPE_COLOREFFECT V4L2_CTRL_TYPE_INTEGER_MENU -#define ISX012_NAME_COLOREFFECT "Color effect" #define ISX012_DEF_COLOREFFECT V4L2_COLORFX_NONE #define ISX012_MIN_COLOREFFECT (0) #define ISX012_MAX_COLOREFFECT (6) @@ -207,7 +191,6 @@ /* Definition for control auto exposure */ #define ISX012_TYPE_EXPOSUREAUTO V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_EXPOSUREAUTO "Auto Exposure" #define ISX012_DEF_EXPOSUREAUTO (0) #define ISX012_MIN_EXPOSUREAUTO (0) #define ISX012_MAX_EXPOSUREAUTO (1) @@ -220,10 +203,9 @@ /* Definition for control exposure time */ #define ISX012_TYPE_EXPOSURETIME V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_EXPOSURETIME "Exposure time(usec)" #define ISX012_DEF_EXPOSURETIME (0) #define ISX012_MIN_EXPOSURETIME (1) -#define ISX012_MAX_EXPOSURETIME (10000) +#define ISX012_MAX_EXPOSURETIME (21000) #define ISX012_STEP_EXPOSURETIME (1) #define ISX012_REG_EXPOSURETIME SHT_PREMODE_TYPE1 #define ISX012_SIZE_EXPOSURETIME (2) @@ -233,7 +215,6 @@ /* Definition for control photometry */ #define ISX012_TYPE_PHOTOMETRY V4L2_CTRL_TYPE_INTEGER_MENU -#define ISX012_NAME_PHOTOMETRY "Photometry" #define ISX012_DEF_PHOTOMETRY V4L2_EXPOSURE_METERING_AVERAGE #define ISX012_MIN_PHOTOMETRY (0) #define ISX012_MAX_PHOTOMETRY (3) @@ -244,7 +225,6 @@ /* Definition for control zoom */ #define ISX012_TYPE_ZOOM V4L2_CTRL_TYPE_U16FIXEDPOINT_Q8 -#define ISX012_NAME_ZOOM "Zoom" #define ISX012_DEF_ZOOM (0x0100) #define ISX012_MIN_ZOOM (0x0100) #define ISX012_MAX_ZOOM (0x1000) @@ -255,7 +235,6 @@ /* Definition for control preset white balance */ #define ISX012_TYPE_PRESETWB V4L2_CTRL_TYPE_INTEGER_MENU -#define ISX012_NAME_PRESETWB "Preset white balance" #define ISX012_DEF_PRESETWB V4L2_WHITE_BALANCE_AUTO #define ISX012_MIN_PRESETWB (0) #define ISX012_MAX_PRESETWB (5) @@ -266,7 +245,6 @@ /* Definition for control YGAMMA adujust */ #define ISX012_TYPE_YGAMMA V4L2_CTRL_TYPE_BOOLEAN -#define ISX012_NAME_YGAMMA "Wide dynamic range" #define ISX012_DEF_YGAMMA (false) #define ISX012_MIN_YGAMMA (false) #define ISX012_MAX_YGAMMA (true) @@ -277,7 +255,6 @@ /* Definition for control ISO sensitivity */ #define ISX012_TYPE_ISO V4L2_CTRL_TYPE_INTEGER_MENU -#define ISX012_NAME_ISO "ISO sensitivity" #define ISX012_DEF_ISO (0) #define ISX012_MIN_ISO (0) #define ISX012_MAX_ISO (18) @@ -288,7 +265,6 @@ /* Definition for control ISO automatic */ #define ISX012_TYPE_ISOAUTO V4L2_CTRL_TYPE_INTEGER_MENU -#define ISX012_NAME_ISOAUTO "Automatic ISO sensitivity" #define ISX012_DEF_ISOAUTO (false) #define ISX012_MIN_ISOAUTO (0) #define ISX012_MAX_ISOAUTO (1) @@ -301,7 +277,6 @@ /* Definition for control 3A lock */ #define ISX012_TYPE_3ALOCK V4L2_CTRL_TYPE_BITMASK -#define ISX012_NAME_3ALOCK "Lock AWB/AE" #define ISX012_DEF_3ALOCK (0) #define ISX012_MIN_3ALOCK (0) #define ISX012_MAX_3ALOCK (3) @@ -312,8 +287,7 @@ /* Definition for control JPEG compression quality */ #define ISX012_TYPE_JPGQUALITY V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_JPGQUALITY "JPEG compression quality" -#define ISX012_DEF_JPGQUALITY (75) +#define ISX012_DEF_JPGQUALITY (80) #define ISX012_MIN_JPGQUALITY (1) #define ISX012_MAX_JPGQUALITY (100) #define ISX012_STEP_JPGQUALITY (1) diff --git a/include/nuttx/video/isx012_reg.h b/drivers/video/isx012_reg.h similarity index 98% rename from include/nuttx/video/isx012_reg.h rename to drivers/video/isx012_reg.h index 35976eb136..143d8f1d53 100644 --- a/include/nuttx/video/isx012_reg.h +++ b/drivers/video/isx012_reg.h @@ -1,5 +1,5 @@ /**************************************************************************** - * include/nuttx/video/isx012_reg.h + * drivers/video/isx012_reg.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -41,6 +41,8 @@ #define MODE_BASE (0x6A00) #define PICT_BASE (0x6C00) #define GAMMA_BASE (0x7000) +#define GAMMA1_BASE (0x7200) +#define GAMMA2_BASE (0x7400) #define JPEG_BASE (0x7800) #define AUTOCOM_BASE (0x7C00) #define VFRMPARA_BASE (0x8800) @@ -777,6 +779,18 @@ #define G0_0CLIP_B (GAMMA_BASE+0x0044) #define G0_KNOT_GAINCTRL_TH_L (GAMMA_BASE+0x0046) #define G0_KNOT_GAINCTRL_TH_H (GAMMA_BASE+0x0047) +#define G1_LOWGM_ON_R (GAMMA1_BASE+0x003A) +#define G1_0CLIP_R (GAMMA1_BASE+0x003C) +#define G1_LOWGM_ON_G (GAMMA1_BASE+0x003E) +#define G1_0CLIP_G (GAMMA1_BASE+0x0040) +#define G1_LOWGM_ON_B (GAMMA1_BASE+0x0042) +#define G1_0CLIP_B (GAMMA1_BASE+0x0044) +#define G2_LOWGM_ON_R (GAMMA2_BASE+0x003A) +#define G2_0CLIP_R (GAMMA2_BASE+0x003C) +#define G2_LOWGM_ON_G (GAMMA2_BASE+0x003E) +#define G2_0CLIP_G (GAMMA2_BASE+0x0040) +#define G2_LOWGM_ON_B (GAMMA2_BASE+0x0042) +#define G2_0CLIP_B (GAMMA2_BASE+0x0044) /* JPEG OFFSET */ diff --git a/drivers/video/video.c b/drivers/video/video.c index 33b3b5da5c..6b9c1e92d1 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,8 @@ #include -#include +#include +#include #include "video_framebuff.h" @@ -46,12 +48,10 @@ * Pre-processor Definitions ****************************************************************************/ -#define video_printf(format, ...) _info(format, ##__VA_ARGS__) - #define MAX_VIDEO_FILE_PATH (32) - -#define VIDEO_TRUE (1) -#define VIDEO_FALSE (0) +#define MAX_VIDEO_FMT (2) +#define VIDEO_FMT_MAIN (0) +#define VIDEO_FMT_SUB (1) #define VIDEO_REMAINING_CAPNUM_INFINITY (-1) @@ -75,50 +75,70 @@ #define videoinfo(x...) #endif +#define VIDEO_SCENE_MAX (sizeof(g_video_scene_parameter) / \ + sizeof(video_scene_params_t)) + +#define VIDEO_ID(x, y) (((x) << 16) | y) + /**************************************************************************** * Private Types ****************************************************************************/ enum video_state_e { - VIDEO_STATE_STREAMOFF = 0, /* DMA trigger event is not received */ - VIDEO_STATE_STREAMON = 1, /* DMA trigger event is received, - * but DMA is not operated. + VIDEO_STATE_STREAMOFF = 0, /* capture trigger event is not received */ + VIDEO_STATE_STREAMON = 1, /* capture trigger event is received, + * but capture is not operated. */ - VIDEO_STATE_DMA = 2, /* On DMA */ + VIDEO_STATE_CAPTURE = 2, /* On capture */ }; enum video_state_transition_cause { - CAUSE_VIDEO_STOP = 0, /* Stop DMA event for video stream */ - CAUSE_VIDEO_START = 1, /* Start DMA event for video stream */ + CAUSE_VIDEO_STOP = 0, /* Stop capture event for video stream */ + CAUSE_VIDEO_START = 1, /* Start capture event for video stream */ CAUSE_VIDEO_DQBUF = 2, /* DQBUF timing for video stream */ - CAUSE_STILL_STOP = 3, /* Stop DMA event for still stream */ - CAUSE_STILL_START = 4, /* Start DMA event for still stream */ + CAUSE_STILL_STOP = 3, /* Stop capture event for still stream */ + CAUSE_STILL_START = 4, /* Start capture event for still stream */ }; enum video_waitend_cause_e { - VIDEO_WAITEND_CAUSE_DMADONE = 0, + VIDEO_WAITEND_CAUSE_CAPTUREDONE = 0, VIDEO_WAITEND_CAUSE_DQCANCEL = 1, VIDEO_WAITEND_CAUSE_STILLSTOP = 2, }; -struct video_wait_dma_s +struct video_wait_capture_s { FAR sem_t dqbuf_wait_flg; - FAR vbuf_container_t *done_container; /* Save container which dma done */ + + /* Save container which capture is done */ + + FAR vbuf_container_t *done_container; enum video_waitend_cause_e waitend_cause; }; -typedef struct video_wait_dma_s video_wait_dma_t; +typedef struct video_wait_capture_s video_wait_capture_t; + +struct video_format_s +{ + uint16_t width; + uint16_t height; + uint32_t pixelformat; +}; + +typedef struct video_format_s video_format_t; struct video_type_inf_s { sem_t lock_state; enum video_state_e state; int32_t remaining_capnum; - video_wait_dma_t wait_dma; + video_wait_capture_t wait_capture; + uint8_t nr_fmt; + video_format_t fmt[MAX_VIDEO_FMT]; + struct v4l2_fract frame_interval; video_framebuff_t bufinf; }; @@ -129,13 +149,62 @@ struct video_mng_s FAR char *devpath; /* parameter of video_initialize() */ sem_t lock_open_num; uint8_t open_num; - FAR struct pollfd *poll_wait; /* poll(setup) information */ video_type_inf_t video_inf; video_type_inf_t still_inf; }; typedef struct video_mng_s video_mng_t; +struct video_scene_params_s +{ + uint8_t mode; /* enum v4l2_scene_mode */ + + int32_t brightness; + int32_t contrast; + int32_t saturation; + int32_t hue; + bool awb; + int32_t red; + int32_t blue; + int32_t gamma; + uint32_t gamma_curve_sz; + uint8_t *gamma_curve; + int32_t ev; + bool hflip_video; + bool vflip_video; + bool hflip_still; + bool vflip_still; + int32_t sharpness; + enum v4l2_colorfx colorfx; + bool auto_brightness; + int32_t rotate; + enum v4l2_exposure_auto_type ae; + int32_t exposure_time; + int32_t focus; + bool af; + int32_t zoom; + int32_t iris; + enum v4l2_auto_n_preset_white_balance wb; + int32_t wdr; + bool stabilization; + enum v4l2_iso_sensitivity_auto_type iso_auto; + int32_t iso; + enum v4l2_exposure_metering meter; + int32_t threea_lock; + enum v4l2_flash_led_mode led; + int32_t jpeg_quality; +}; + +typedef struct video_scene_params_s video_scene_params_t; + +struct video_parameter_name_s +{ + uint32_t id; + char *name; +}; + +typedef struct video_parameter_name_s video_parameter_name_t; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -145,9 +214,6 @@ typedef struct video_mng_s video_mng_t; static int video_open(FAR struct file *filep); static int video_close(FAR struct file *filep); static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static int video_poll(FAR struct file *filep, - FAR struct pollfd *fds, - bool setup); /* Common function */ @@ -164,6 +230,10 @@ static bool is_taking_still_picture(FAR video_mng_t *vmng); static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize); static void cleanup_resources(FAR video_mng_t *vmng); static bool is_sem_waited(FAR sem_t *sem); +static int save_scene_param(enum v4l2_scene_mode mode, + uint32_t id, + struct v4l2_ext_control *control); +static int video_complete_capture(uint8_t err_code, uint32_t datasize); /* internal function for each cmds of ioctl */ @@ -175,18 +245,16 @@ static int video_dqbuf(FAR struct video_mng_s *vmng, FAR struct v4l2_buffer *buf); static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, enum v4l2_buf_type type); -static int video_enum_fmt(FAR struct v4l2_fmtdesc *fmt); -static int video_enum_framesizes(FAR struct v4l2_frmsizeenum *frmsize); static int video_s_fmt(FAR struct video_mng_s *priv, FAR struct v4l2_format *fmt); -static int video_enum_frameintervals(FAR struct v4l2_frmivalenum *frmival); static int video_s_parm(FAR struct video_mng_s *priv, FAR struct v4l2_streamparm *parm); static int video_streamon(FAR struct video_mng_s *vmng, FAR enum v4l2_buf_type *type); static int video_streamoff(FAR struct video_mng_s *vmng, FAR enum v4l2_buf_type *type); -static int video_do_halfpush(bool enable); +static int video_do_halfpush(FAR struct video_mng_s *priv, + bool enable); static int video_takepict_start(FAR struct video_mng_s *vmng, int32_t capture_num); static int video_takepict_stop(FAR struct video_mng_s *vmng, @@ -202,12 +270,11 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, FAR struct v4l2_ext_controls *ctrls); static int video_s_ext_ctrls(FAR struct video_mng_s *priv, FAR struct v4l2_ext_controls *ctrls); - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -static const struct video_devops_s *g_video_devops; +static int video_query_ext_ctrl_scene(FAR struct v4s_query_ext_ctrl_scene + *ctrl); +static int video_querymenu_scene(FAR struct v4s_querymenu_scene *menu); +static int video_g_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls); +static int video_s_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls); /**************************************************************************** * Private Data @@ -222,17 +289,135 @@ static const struct file_operations g_video_fops = 0, /* seek */ video_ioctl, /* ioctl */ #ifndef CONFIG_DISABLE_POLL - video_poll, /* poll */ + 0, /* poll */ #endif 0 /* unlink */ }; static bool is_initialized = false; -static FAR void *video_handler; -/**************************************************************************** - * Public Data - ****************************************************************************/ +enum v4l2_scene_mode g_video_scene_mode = V4L2_SCENE_MODE_NONE; +video_scene_params_t g_video_scene_parameter[] = +{ + { + .mode = V4L2_SCENE_MODE_NONE, + }, +#ifdef CONFIG_VIDEO_SCENE_BACKLIGHT + { + .mode = V4L2_SCENE_MODE_BACKLIGHT, + }, +#endif /* CONFIG_VIDEO_SCENE_BACKLIGHT */ +#ifdef CONFIG_VIDEO_SCENE_BEACHSNOW + { + .mode = V4L2_SCENE_MODE_BEACH_SNOW, + }, +#endif /* CONFIG_VIDEO_SCENE_BEACHSNOW */ +#ifdef CONFIG_VIDEO_SCENE_CANDLELIGHT + { + .mode = V4L2_SCENE_MODE_CANDLE_LIGHT, + }, +#endif /* CONFIG_VIDEO_SCENE_CANDLELIGHT */ +#ifdef CONFIG_VIDEO_SCENE_DAWNDUSK + { + .mode = V4L2_SCENE_MODE_DAWN_DUSK, + }, +#endif /* CONFIG_VIDEO_SCENE_DAWNDUSK */ +#ifdef CONFIG_VIDEO_SCENE_FALLCOLORS + { + .mode = V4L2_SCENE_MODE_FALL_COLORS, + }, +#endif /* CONFIG_VIDEO_SCENE_FALLCOLORS */ +#ifdef CONFIG_VIDEO_SCENE_FIREWORKS + { + .mode = V4L2_SCENE_MODE_FIREWORKS, + }, +#endif /* CONFIG_VIDEO_SCENE_FIREWORKS */ +#ifdef CONFIG_VIDEO_SCENE_LANDSCAPE + { + .mode = V4L2_SCENE_MODE_LANDSCAPE, + }, +#endif /* CONFIG_VIDEO_SCENE_LANDSCAPE */ +#ifdef CONFIG_VIDEO_SCENE_NIGHT + { + .mode = V4L2_SCENE_MODE_NIGHT, + }, +#endif /* CONFIG_VIDEO_SCENE_NIGHT */ +#ifdef CONFIG_VIDEO_SCENE_PARTYINDOOR + { + .mode = V4L2_SCENE_MODE_PARTY_INDOOR, + }, +#endif /* CONFIG_VIDEO_SCENE_PARTYINDOOR */ +#ifdef CONFIG_VIDEO_SCENE_PORTRAIT + { + .mode = V4L2_SCENE_MODE_PORTRAIT, + }, +#endif /* CONFIG_VIDEO_SCENE_PORTRAIT */ +#ifdef CONFIG_VIDEO_SCENE_SPORTS + { + .mode = V4L2_SCENE_MODE_SPORTS, + }, +#endif /* CONFIG_VIDEO_SCENE_SPORTS */ +#ifdef CONFIG_VIDEO_SCENE_SUNSET + { + .mode = V4L2_SCENE_MODE_SUNSET, + }, +#endif /* CONFIG_VIDEO_SCENE_SUNSET */ +#ifdef CONFIG_VIDEO_SCENE_TEXT + { + .mode = V4L2_SCENE_MODE_TEXT, + }, +#endif /* CONFIG_VIDEO_SCENE_TEXT */ +}; + +static video_parameter_name_t g_video_parameter_name[] = +{ + {IMGSENSOR_ID_BRIGHTNESS, "Brightness"}, + {IMGSENSOR_ID_CONTRAST, "Contrast"}, + {IMGSENSOR_ID_SATURATION, "Saturation"}, + {IMGSENSOR_ID_HUE, "Hue"}, + {IMGSENSOR_ID_AUTO_WHITE_BALANCE, "Automatic white balance"}, + {IMGSENSOR_ID_RED_BALANCE, "Red balance"}, + {IMGSENSOR_ID_BLUE_BALANCE, "Blue balance"}, + {IMGSENSOR_ID_GAMMA, "Gamma value"}, + {IMGSENSOR_ID_GAMMA_CURVE, "Gamma adjustment(curve)"}, + {IMGSENSOR_ID_EXPOSURE, "Exposure value"}, + {IMGSENSOR_ID_HFLIP_VIDEO, "Mirror horizontally(VIDEO)"}, + {IMGSENSOR_ID_VFLIP_VIDEO, "Mirror vertically(VIDEO)"}, + {IMGSENSOR_ID_HFLIP_STILL, "Mirror horizontally(STILL)"}, + {IMGSENSOR_ID_VFLIP_STILL, "Mirror vertically(STILL)"}, + {IMGSENSOR_ID_SHARPNESS, "Sharpness"}, + {IMGSENSOR_ID_COLOR_KILLER, "Color killer"}, + {IMGSENSOR_ID_COLORFX, "Color effect"}, + {IMGSENSOR_ID_AUTOBRIGHTNESS, "Auto brightness"}, + {IMGSENSOR_ID_ROTATE, "Rotate"}, + {IMGSENSOR_ID_EXPOSURE_AUTO, "Auto Exposure"}, + {IMGSENSOR_ID_EXPOSURE_ABSOLUTE, "Exposure time(100 usec)"}, + {IMGSENSOR_ID_FOCUS_ABSOLUTE, "Focus(absolute value)"}, + {IMGSENSOR_ID_FOCUS_RELATIVE, "Focus(relative value)"}, + {IMGSENSOR_ID_FOCUS_AUTO, "Continuous Auto Focus"}, + {IMGSENSOR_ID_ZOOM_ABSOLUTE, "Zoom(absolute value)"}, + {IMGSENSOR_ID_ZOOM_RELATIVE, "Zoom(relative value)"}, + {IMGSENSOR_ID_ZOOM_CONTINUOUS, "Continuous zoom"}, + {IMGSENSOR_ID_IRIS_ABSOLUTE, "Iris(absolute value)"}, + {IMGSENSOR_ID_IRIS_RELATIVE, "Iris(relative value)"}, + {IMGSENSOR_ID_AUTO_N_PRESET_WB, "Preset white balance"}, + {IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, "Wide dynamic range"}, + {IMGSENSOR_ID_IMG_STABILIZATION, "Image stabilization"}, + {IMGSENSOR_ID_ISO_SENSITIVITY, "ISO sensitivity"}, + {IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, "Automatic ISO sensitivity"}, + {IMGSENSOR_ID_EXPOSURE_METERING, "Photometry"}, + {IMGSENSOR_ID_3A_LOCK, "Lock AWB/AE"}, + {IMGSENSOR_ID_AUTO_FOCUS_START, "Start single Auto Focus"}, + {IMGSENSOR_ID_AUTO_FOCUS_STOP, "Stop single Auto Focus"}, + {IMGSENSOR_ID_3A_PARAMETER, "3A parameter"}, + {IMGSENSOR_ID_3A_STATUS, "3A status"}, + {IMGSENSOR_ID_FLASH_LED_MODE, "LED mode"}, + {IMGSENSOR_ID_JPEG_QUALITY, "JPEG compression quality"} +}; + +static FAR void *video_handler; +static FAR const struct imgsensor_ops_s *g_video_sensor_ops; +static FAR const struct imgdata_ops_s *g_video_data_ops; /**************************************************************************** * Private Functions @@ -299,13 +484,13 @@ static enum video_state_e estimate_next_video_state } else { - return VIDEO_STATE_DMA; + return VIDEO_STATE_CAPTURE; } case CAUSE_STILL_STOP: if (current_state == VIDEO_STATE_STREAMON) { - return VIDEO_STATE_DMA; + return VIDEO_STATE_CAPTURE; } else { @@ -313,7 +498,7 @@ static enum video_state_e estimate_next_video_state } case CAUSE_STILL_START: - if (current_state == VIDEO_STATE_DMA) + if (current_state == VIDEO_STATE_CAPTURE) { return VIDEO_STATE_STREAMON; } @@ -326,7 +511,7 @@ static enum video_state_e estimate_next_video_state if ((current_state == VIDEO_STATE_STREAMON) && !is_taking_still_picture(vmng)) { - return VIDEO_STATE_DMA; + return VIDEO_STATE_CAPTURE; } else { @@ -338,23 +523,137 @@ static enum video_state_e estimate_next_video_state } } +static void convert_to_imgdatafmt(FAR video_format_t *video, + FAR imgdata_format_t *data) +{ + ASSERT(video && data); + + data->width = video->width; + data->height = video->height; + switch (video->pixelformat) + { + case V4L2_PIX_FMT_UYVY : + data->pixelformat = IMGDATA_PIX_FMT_UYVY; + break; + + case V4L2_PIX_FMT_RGB565 : + data->pixelformat = IMGDATA_PIX_FMT_RGB565; + break; + + case V4L2_PIX_FMT_JPEG : + data->pixelformat = IMGDATA_PIX_FMT_JPEG; + break; + + default : /* V4L2_PIX_FMT_JPEG_WITH_SUBIMG */ + data->pixelformat = IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG; + break; + } +} + +static void convert_to_imgsensorfmt(FAR video_format_t *video, + FAR imgsensor_format_t *sensor) +{ + ASSERT(video && sensor); + + sensor->width = video->width; + sensor->height = video->height; + switch (video->pixelformat) + { + case V4L2_PIX_FMT_UYVY : + sensor->pixelformat = IMGSENSOR_PIX_FMT_UYVY; + break; + + case V4L2_PIX_FMT_RGB565 : + sensor->pixelformat = IMGSENSOR_PIX_FMT_RGB565; + break; + + case V4L2_PIX_FMT_JPEG : + sensor->pixelformat = IMGSENSOR_PIX_FMT_JPEG; + break; + + default : /* V4L2_PIX_FMT_JPEG_WITH_SUBIMG */ + sensor->pixelformat = IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG; + break; + } +} + +static void convert_to_imgdatainterval(FAR struct v4l2_fract *video, + FAR imgdata_interval_t *data) +{ + ASSERT(video && data); + + data->numerator = video->numerator; + data->denominator = video->denominator; +} + +static void convert_to_imgsensorinterval(FAR struct v4l2_fract *video, + FAR imgsensor_interval_t *sensor) +{ + ASSERT(video && sensor); + + sensor->numerator = video->numerator; + sensor->denominator = video->denominator; +} + +static int start_capture(enum v4l2_buf_type type, + uint8_t nr_fmt, + FAR video_format_t *fmt, + FAR struct v4l2_fract *interval, + uint32_t bufaddr, uint32_t bufsize) +{ + imgdata_format_t df[MAX_VIDEO_FMT]; + imgsensor_format_t sf[MAX_VIDEO_FMT]; + imgdata_interval_t di; + imgsensor_interval_t si; + + ASSERT(fmt && interval && g_video_sensor_ops && g_video_data_ops); + + if ((g_video_sensor_ops->start_capture == NULL) || + (g_video_data_ops->start_capture == NULL) || + (g_video_data_ops->set_buf == NULL)) + { + return -ENOTTY; + } + + convert_to_imgdatafmt(&fmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); + convert_to_imgdatafmt(&fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]); + convert_to_imgdatainterval(interval, &di); + convert_to_imgsensorfmt(&fmt[VIDEO_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); + convert_to_imgsensorfmt(&fmt[VIDEO_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); + convert_to_imgsensorinterval(interval, &si); + + g_video_sensor_ops->start_capture + ((type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? + IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL, + nr_fmt, + sf, + &si); + g_video_data_ops->start_capture(nr_fmt, df, &di, video_complete_capture); + g_video_data_ops->set_buf((uint8_t *)bufaddr, bufsize); + + return OK; +} + static void change_video_state(FAR video_mng_t *vmng, enum video_state_e next_state) { enum video_state_e current_state = vmng->video_inf.state; enum video_state_e updated_next_state = next_state; - FAR vbuf_container_t *dma_container; + FAR vbuf_container_t *container; - if ((current_state != VIDEO_STATE_DMA) && - (next_state == VIDEO_STATE_DMA)) + if ((current_state != VIDEO_STATE_CAPTURE) && + (next_state == VIDEO_STATE_CAPTURE)) { - dma_container = - video_framebuff_get_dma_container(&vmng->video_inf.bufinf); - if (dma_container) + container = + video_framebuff_get_vacant_container(&vmng->video_inf.bufinf); + if (container) { - g_video_devops->set_buftype(V4L2_BUF_TYPE_VIDEO_CAPTURE); - g_video_devops->set_buf(dma_container->buf.m.userptr, - dma_container->buf.length); + start_capture(V4L2_BUF_TYPE_VIDEO_CAPTURE, + vmng->video_inf.nr_fmt, + vmng->video_inf.fmt, + &vmng->video_inf.frame_interval, + container->buf.m.userptr, + container->buf.length); } else { @@ -363,10 +662,10 @@ static void change_video_state(FAR video_mng_t *vmng, } else { - if ((current_state == VIDEO_STATE_DMA) && - (next_state != VIDEO_STATE_DMA)) + if ((current_state == VIDEO_STATE_CAPTURE) && + (next_state != VIDEO_STATE_CAPTURE)) { - g_video_devops->cancel_dma(); + g_video_data_ops->stop_capture(); } } @@ -378,7 +677,7 @@ static void change_video_state(FAR video_mng_t *vmng, static bool is_taking_still_picture(FAR video_mng_t *vmng) { return ((vmng->still_inf.state == VIDEO_STATE_STREAMON) || - (vmng->still_inf.state == VIDEO_STATE_DMA)); + (vmng->still_inf.state == VIDEO_STATE_CAPTURE)); } static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize) @@ -388,21 +687,196 @@ static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize) return true; } +static void initialize_frame_setting(FAR uint8_t *nr_fmt, + FAR video_format_t *fmt, + FAR struct v4l2_fract *interval) +{ + ASSERT(nr_fmt && fmt && interval); + + /* Initial setting : QVGA YUV4:2:2 15FPS */ + + *nr_fmt = 1; + fmt[VIDEO_FMT_MAIN].width = VIDEO_HSIZE_QVGA; + fmt[VIDEO_FMT_MAIN].height = VIDEO_VSIZE_QVGA; + fmt[VIDEO_FMT_MAIN].pixelformat = V4L2_PIX_FMT_UYVY; + interval->denominator = 15; + interval->numerator = 1; +} + static void initialize_streamresources(FAR video_type_inf_t *type_inf) { memset(type_inf, 0, sizeof(video_type_inf_t)); type_inf->remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; nxsem_init(&type_inf->lock_state, 0, 1); - nxsem_init(&type_inf->wait_dma.dqbuf_wait_flg, 0, 0); + nxsem_init(&type_inf->wait_capture.dqbuf_wait_flg, 0, 0); + initialize_frame_setting(&type_inf->nr_fmt, + type_inf->fmt, + &type_inf->frame_interval); video_framebuff_init(&type_inf->bufinf); return; } +static int32_t get_default_value(uint32_t id) +{ + int ret; + imgsensor_supported_value_t value; + + if ((g_video_sensor_ops == NULL) || + (g_video_sensor_ops->get_supported_value == NULL)) + { + return -EINVAL; + } + + ret = g_video_sensor_ops->get_supported_value(id, &value); + if (ret != OK) + { + /* Don't care(unsupported parameter) */ + + return 0; + } + + switch (value.type) + { + case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: + return value.u.discrete.default_value; + + case IMGSENSOR_CTRL_TYPE_U8: + case IMGSENSOR_CTRL_TYPE_U16: + case IMGSENSOR_CTRL_TYPE_U32: + + /* Don't care */ + + return 0; + + default: + return value.u.range.default_value; + } +} + +static int32_t initialize_scene_gamma(uint8_t **gamma) +{ + int ret; + imgsensor_supported_value_t sup_val; + imgsensor_value_t val; + int32_t sz; + + *gamma = NULL; + + ASSERT(g_video_sensor_ops); + + if ((g_video_sensor_ops->get_supported_value == NULL) || + (g_video_sensor_ops->get_value == NULL)) + { + return -ENOTTY; + } + + ret = g_video_sensor_ops->get_supported_value + (IMGSENSOR_ID_GAMMA_CURVE, &sup_val); + if (ret != OK) + { + /* Unsupported parameter */ + + return -EINVAL; + } + + switch (sup_val.type) + { + case IMGSENSOR_CTRL_TYPE_U8: + sz = sup_val.u.elems.nr_elems * sizeof(uint8_t); + if (sz / sizeof(uint8_t) != sup_val.u.elems.nr_elems) + { + /* Multiplication overflow */ + + return -EINVAL; + } + + break; + + case IMGSENSOR_CTRL_TYPE_U16: + sz = sup_val.u.elems.nr_elems * sizeof(uint16_t); + if (sz / sizeof(uint16_t) != sup_val.u.elems.nr_elems) + { + /* Multiplication overflow */ + + return -EINVAL; + } + + break; + + default: /* IMGSENSOR_CTRL_TYPE_U32 */ + sz = sup_val.u.elems.nr_elems * sizeof(uint32_t); + if (sz / sizeof(uint32_t) != sup_val.u.elems.nr_elems) + { + /* Multiplication overflow */ + + return -EINVAL; + } + + break; + } + + *gamma = malloc(sz); + val.p_u8 = (uint8_t *)*gamma; + g_video_sensor_ops->get_value(IMGSENSOR_ID_GAMMA_CURVE, sz, &val); + return sz; +} + +static void initialize_scene_parameter(video_scene_params_t *sp) +{ + ASSERT(sp); + + sp->brightness = get_default_value(IMGSENSOR_ID_BRIGHTNESS); + sp->contrast = get_default_value(IMGSENSOR_ID_CONTRAST); + sp->saturation = get_default_value(IMGSENSOR_ID_SATURATION); + sp->hue = get_default_value(IMGSENSOR_ID_HUE); + sp->awb = get_default_value(IMGSENSOR_ID_AUTO_WHITE_BALANCE); + sp->red = get_default_value(IMGSENSOR_ID_RED_BALANCE); + sp->blue = get_default_value(IMGSENSOR_ID_BLUE_BALANCE); + sp->gamma = get_default_value(IMGSENSOR_ID_GAMMA); + sp->gamma_curve_sz = initialize_scene_gamma(&sp->gamma_curve); + sp->ev = get_default_value(IMGSENSOR_ID_EXPOSURE); + sp->hflip_video = get_default_value(IMGSENSOR_ID_HFLIP_VIDEO); + sp->vflip_video = get_default_value(IMGSENSOR_ID_VFLIP_VIDEO); + sp->hflip_still = get_default_value(IMGSENSOR_ID_HFLIP_STILL); + sp->vflip_still = get_default_value(IMGSENSOR_ID_VFLIP_STILL); + sp->sharpness = get_default_value(IMGSENSOR_ID_SHARPNESS); + sp->colorfx = get_default_value(IMGSENSOR_ID_COLORFX); + sp->auto_brightness = get_default_value(IMGSENSOR_ID_AUTOBRIGHTNESS); + sp->rotate = get_default_value(IMGSENSOR_ID_ROTATE); + sp->ae = get_default_value(IMGSENSOR_ID_EXPOSURE_AUTO); + sp->exposure_time = get_default_value(IMGSENSOR_ID_EXPOSURE_ABSOLUTE); + sp->focus = get_default_value(IMGSENSOR_ID_FOCUS_ABSOLUTE); + sp->af = get_default_value(IMGSENSOR_ID_FOCUS_AUTO); + sp->zoom = get_default_value(IMGSENSOR_ID_ZOOM_ABSOLUTE); + sp->iris = get_default_value(IMGSENSOR_ID_IRIS_ABSOLUTE); + sp->wb = get_default_value(IMGSENSOR_ID_AUTO_N_PRESET_WB); + sp->wdr = get_default_value(IMGSENSOR_ID_WIDE_DYNAMIC_RANGE); + sp->stabilization = get_default_value(IMGSENSOR_ID_IMG_STABILIZATION); + sp->iso_auto = get_default_value(IMGSENSOR_ID_ISO_SENSITIVITY_AUTO); + sp->iso = get_default_value(IMGSENSOR_ID_ISO_SENSITIVITY); + sp->meter = get_default_value(IMGSENSOR_ID_EXPOSURE_METERING); + sp->threea_lock = get_default_value(IMGSENSOR_ID_3A_LOCK); + sp->led = get_default_value(IMGSENSOR_ID_FLASH_LED_MODE); + sp->jpeg_quality = get_default_value(IMGSENSOR_ID_JPEG_QUALITY); +} + +static void initialize_scenes_parameter(void) +{ + int i; + video_scene_params_t *sp = &g_video_scene_parameter[0]; + + for (i = 0; i < VIDEO_SCENE_MAX; i++) + { + initialize_scene_parameter(sp++); + } +} + static void initialize_resources(FAR video_mng_t *vmng) { initialize_streamresources(&vmng->video_inf); initialize_streamresources(&vmng->still_inf); + initialize_scenes_parameter(); return; } @@ -410,7 +884,7 @@ static void initialize_resources(FAR video_mng_t *vmng) static void cleanup_streamresources(FAR video_type_inf_t *type_inf) { video_framebuff_uninit(&type_inf->bufinf); - nxsem_destroy(&type_inf->wait_dma.dqbuf_wait_flg); + nxsem_destroy(&type_inf->wait_capture.dqbuf_wait_flg); nxsem_destroy(&type_inf->lock_state); memset(type_inf, 0, sizeof(video_type_inf_t)); type_inf->remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; @@ -418,20 +892,42 @@ static void cleanup_streamresources(FAR video_type_inf_t *type_inf) return; } +static void cleanup_scene_parameter(video_scene_params_t *sp) +{ + ASSERT(sp); + + if (sp->gamma_curve) + { + free(sp->gamma_curve); + } +} + +static void cleanup_scenes_parameter(void) +{ + int i; + video_scene_params_t *sp = &g_video_scene_parameter[0]; + + for (i = 0; i < VIDEO_SCENE_MAX; i++, sp++) + { + cleanup_scene_parameter(sp); + } +} + static void cleanup_resources(FAR video_mng_t *vmng) { /* clean up resource */ - if ((vmng->video_inf.state == VIDEO_STATE_DMA) || - (vmng->still_inf.state == VIDEO_STATE_DMA)) + if ((vmng->video_inf.state == VIDEO_STATE_CAPTURE) || + (vmng->still_inf.state == VIDEO_STATE_CAPTURE)) { - /* If in DMA, stop */ + /* If in capture, stop */ - g_video_devops->cancel_dma(); + g_video_data_ops->stop_capture(); } cleanup_streamresources(&vmng->video_inf); cleanup_streamresources(&vmng->still_inf); + cleanup_scenes_parameter(); return; } @@ -463,10 +959,14 @@ static int video_open(FAR struct file *filep) { /* Only in first execution, open device */ - ret = g_video_devops->open(priv); + ret = g_video_sensor_ops->init(); if (ret == OK) { - initialize_resources(priv); + ret = g_video_data_ops->init(); + if (ret == OK) + { + initialize_resources(priv); + } } } @@ -499,7 +999,8 @@ static int video_close(FAR struct file *filep) if (priv->open_num == 0) { cleanup_resources(priv); - g_video_devops->close(); + g_video_sensor_ops->uninit(); + g_video_data_ops->uninit(); } video_unlock(&priv->lock_open_num); @@ -527,9 +1028,9 @@ static int video_reqbufs(FAR struct video_mng_s *vmng, flags = enter_critical_section(); - if (type_inf->state == VIDEO_STATE_DMA) + if (type_inf->state == VIDEO_STATE_CAPTURE) { - /* In DMA, REQBUFS is not permitted */ + /* In capture, REQBUFS is not permitted */ ret = -EPERM; } @@ -595,13 +1096,17 @@ static int video_qbuf(FAR struct video_mng_s *vmng, } else { - container = video_framebuff_get_dma_container(&type_inf->bufinf); + container = video_framebuff_get_vacant_container + (&type_inf->bufinf); if (container) { - g_video_devops->set_buftype(buf->type); - g_video_devops->set_buf(container->buf.m.userptr, - container->buf.length); - type_inf->state = VIDEO_STATE_DMA; + start_capture(buf->type, + type_inf->nr_fmt, + type_inf->fmt, + &type_inf->frame_interval, + container->buf.m.userptr, + container->buf.length); + type_inf->state = VIDEO_STATE_CAPTURE; } } } @@ -638,17 +1143,17 @@ static int video_dqbuf(FAR struct video_mng_s *vmng, container = video_framebuff_dq_valid_container(&type_inf->bufinf); if (container == NULL) { - /* Not yet done DMA. Wait done */ + /* Not yet done capture. Wait done */ - dqbuf_wait_flg = &type_inf->wait_dma.dqbuf_wait_flg; + dqbuf_wait_flg = &type_inf->wait_capture.dqbuf_wait_flg; - /* Loop until semaphore is unlocked by DMA done or DQCANCEL */ + /* Loop until semaphore is unlocked by capture done or DQCANCEL */ do { if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - /* If start DMA condition is satisfied, start DMA */ + /* If start capture condition is satisfied, start capture */ flags = enter_critical_section(); next_video_state = estimate_next_video_state @@ -657,27 +1162,27 @@ static int video_dqbuf(FAR struct video_mng_s *vmng, leave_critical_section(flags); } - nxsem_wait(dqbuf_wait_flg); + nxsem_wait_uninterruptible(dqbuf_wait_flg); } - while (type_inf->wait_dma.waitend_cause == + while (type_inf->wait_capture.waitend_cause == VIDEO_WAITEND_CAUSE_STILLSTOP); - container = type_inf->wait_dma.done_container; + container = type_inf->wait_capture.done_container; if (!container) { - /* Waking up without DMA data means abort. + /* Waking up without captured data means abort. * Therefore, Check cause. */ - if (type_inf->wait_dma.waitend_cause + if (type_inf->wait_capture.waitend_cause == VIDEO_WAITEND_CAUSE_DQCANCEL) { return -ECANCELED; } } - type_inf->wait_dma.done_container = NULL; + type_inf->wait_capture.done_container = NULL; } memcpy(buf, &container->buf, sizeof(struct v4l2_buffer)); @@ -698,108 +1203,223 @@ static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, return -EINVAL; } - if (!is_sem_waited(&type_inf->wait_dma.dqbuf_wait_flg)) + if (!is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) { /* In not waiting DQBUF case, return OK */ return OK; } - type_inf->wait_dma.waitend_cause = VIDEO_WAITEND_CAUSE_DQCANCEL; + type_inf->wait_capture.waitend_cause = VIDEO_WAITEND_CAUSE_DQCANCEL; - /* If DMA is done before nxsem_post, cause is overwritten */ + /* If capture is done before nxsem_post, cause is overwritten */ - nxsem_post(&type_inf->wait_dma.dqbuf_wait_flg); + nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); return OK; } -static int video_enum_fmt(FAR struct v4l2_fmtdesc *fmt) +static int validate_frame_setting(enum v4l2_buf_type type, + uint8_t nr_fmt, + FAR video_format_t *vfmt, + FAR struct v4l2_fract *interval) { int ret; + imgdata_format_t df[MAX_VIDEO_FMT]; + imgsensor_format_t sf[MAX_VIDEO_FMT]; + imgdata_interval_t di; + imgsensor_interval_t si; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_fmt == NULL)) + ASSERT(vfmt && interval && g_video_sensor_ops && g_video_data_ops); + + if ((g_video_sensor_ops->validate_frame_setting == NULL) || + (g_video_data_ops->validate_frame_setting == NULL)) { - return -EINVAL; + return -ENOTTY; } - ret = g_video_devops->get_range_of_fmt(fmt); + /* Return OK only in case both image data driver and + * image sensor driver support. + */ - return ret; + convert_to_imgdatafmt(&vfmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); + convert_to_imgdatafmt(&vfmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]); + convert_to_imgdatainterval(interval, &di); + convert_to_imgsensorfmt(&vfmt[VIDEO_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); + convert_to_imgsensorfmt(&vfmt[VIDEO_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); + convert_to_imgsensorinterval(interval, &si); + + ret = g_video_sensor_ops->validate_frame_setting(type, nr_fmt, sf, &si); + if (ret != OK) + { + return ret; + } + + return g_video_data_ops->validate_frame_setting(nr_fmt, df, &di); } -static int video_enum_framesizes(FAR struct v4l2_frmsizeenum *frmsize) +static int video_try_fmt(FAR struct video_mng_s *priv, + FAR struct v4l2_format *v4l2) { - int ret; + FAR video_type_inf_t *type_inf; + uint8_t nr_fmt; + video_format_t vf[MAX_VIDEO_FMT]; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_framesize == NULL)) + ASSERT(priv && g_video_sensor_ops && g_video_data_ops); + + if ((g_video_sensor_ops->validate_frame_setting == NULL) || + (g_video_data_ops->validate_frame_setting == NULL)) + { + return -ENOTTY; + } + + if (v4l2 == NULL) { return -EINVAL; } - ret = g_video_devops->get_range_of_framesize(frmsize); - - return ret; -} - -static int video_try_fmt(FAR struct v4l2_format *fmt) -{ - int ret; - - if ((g_video_devops == NULL) || (g_video_devops->try_format == NULL)) + type_inf = get_video_type_inf(priv, v4l2->type); + if (type_inf == NULL) { return -EINVAL; } - ret = g_video_devops->try_format(fmt); + switch (v4l2->fmt.pix.pixelformat) + { + case V4L2_PIX_FMT_SUBIMG_UYVY: + case V4L2_PIX_FMT_SUBIMG_RGB565: + if (type_inf->fmt[VIDEO_FMT_MAIN].pixelformat + != V4L2_PIX_FMT_JPEG_WITH_SUBIMG) + { + return -EPERM; + } - return ret; + /* Validate both main image and subimage. */ + + nr_fmt = 2; + memcpy(&vf[VIDEO_FMT_MAIN], + &type_inf->fmt[VIDEO_FMT_MAIN], + sizeof(video_format_t)); + vf[VIDEO_FMT_SUB].width = v4l2->fmt.pix.width; + vf[VIDEO_FMT_SUB].height = v4l2->fmt.pix.height; + vf[VIDEO_FMT_SUB].pixelformat + = (v4l2->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY) ? + V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; + + break; + + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_JPEG: + case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: + nr_fmt = 1; + vf[VIDEO_FMT_MAIN].width = v4l2->fmt.pix.width; + vf[VIDEO_FMT_MAIN].height = v4l2->fmt.pix.height; + vf[VIDEO_FMT_MAIN].pixelformat = v4l2->fmt.pix.pixelformat; + + break; + + default: + return -EINVAL; + } + + return validate_frame_setting(v4l2->type, + nr_fmt, + vf, + &type_inf->frame_interval); } static int video_s_fmt(FAR struct video_mng_s *priv, FAR struct v4l2_format *fmt) { int ret; + FAR video_type_inf_t *type_inf; - if ((g_video_devops == NULL) || (g_video_devops->set_format == NULL)) + ret = video_try_fmt(priv, fmt); + if (ret != 0) + { + return ret; + } + + type_inf = get_video_type_inf(priv, fmt->type); + if (type_inf == NULL) { return -EINVAL; } - ret = g_video_devops->set_format(fmt); - - return ret; -} - -static int video_enum_frameintervals(FAR struct v4l2_frmivalenum *frmival) -{ - int ret; - - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_frameinterval == NULL)) + if (type_inf->state != VIDEO_STATE_STREAMOFF) { - return -EINVAL; + return -EBUSY; } - ret = g_video_devops->get_range_of_frameinterval(frmival); + switch (fmt->fmt.pix.pixelformat) + { + case V4L2_PIX_FMT_SUBIMG_UYVY: + case V4L2_PIX_FMT_SUBIMG_RGB565: + if (type_inf->fmt[VIDEO_FMT_MAIN].pixelformat + != V4L2_PIX_FMT_JPEG_WITH_SUBIMG) + { + return -EPERM; + } - return ret; + type_inf->fmt[VIDEO_FMT_SUB].width = fmt->fmt.pix.width; + type_inf->fmt[VIDEO_FMT_SUB].height = fmt->fmt.pix.height; + type_inf->fmt[VIDEO_FMT_SUB].pixelformat + = (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY) ? + V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; + type_inf->nr_fmt = 2; + break; + + default: + type_inf->fmt[VIDEO_FMT_MAIN].width = fmt->fmt.pix.width; + type_inf->fmt[VIDEO_FMT_MAIN].height = fmt->fmt.pix.height; + type_inf->fmt[VIDEO_FMT_MAIN].pixelformat + = fmt->fmt.pix.pixelformat; + type_inf->nr_fmt = 1; + break; + } + + return OK; } static int video_s_parm(FAR struct video_mng_s *priv, FAR struct v4l2_streamparm *parm) { int ret; + FAR video_type_inf_t *type_inf; - if ((g_video_devops == NULL) || - (g_video_devops->set_frameinterval == NULL)) + ASSERT(g_video_sensor_ops && g_video_data_ops); + + if ((g_video_sensor_ops->validate_frame_setting == NULL) || + (g_video_data_ops->validate_frame_setting == NULL) || + (parm == NULL)) { return -EINVAL; } - ret = g_video_devops->set_frameinterval(parm); + type_inf = get_video_type_inf(priv, parm->type); + if (type_inf == NULL) + { + return -EINVAL; + } + + if (type_inf->state != VIDEO_STATE_STREAMOFF) + { + return -EBUSY; + } + + ret = validate_frame_setting(parm->type, + type_inf->nr_fmt, + type_inf->fmt, + &parm->parm.capture.timeperframe); + if (ret != OK) + { + return ret; + } + + memcpy(&type_inf->frame_interval, + &parm->parm.capture.timeperframe, + sizeof(struct v4l2_fract)); return ret; } @@ -891,14 +1511,29 @@ static int video_streamoff(FAR struct video_mng_s *vmng, return ret; } -static int video_do_halfpush(bool enable) +static int video_do_halfpush(FAR struct video_mng_s *priv, bool enable) { - if ((g_video_devops == NULL) || (g_video_devops->do_halfpush == NULL)) - { - return -EINVAL; - } + int ret; + struct v4l2_ext_controls ext_controls; + struct v4l2_ext_control control[2]; - return g_video_devops->do_halfpush(enable); + /* Replace to VIDIOC_S_EXT_CTRLS format */ + + control[0].id = V4L2_CID_3A_LOCK; + control[0].value = enable ? + (V4L2_LOCK_EXPOSURE | V4L2_LOCK_WHITE_BALANCE) : 0; + control[1].id = V4L2_CID_AUTO_FOCUS_START; + control[1].value = enable ? true : false; + + ext_controls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ext_controls.count = 2; + ext_controls.controls = control; + + /* Execute VIDIOC_S_EXT_CTRLS */ + + ret = video_s_ext_ctrls(priv, &ext_controls); + + return ret; } static int video_takepict_start(FAR struct video_mng_s *vmng, @@ -906,7 +1541,8 @@ static int video_takepict_start(FAR struct video_mng_s *vmng, { irqstate_t flags; enum video_state_e next_video_state; - FAR vbuf_container_t *dma_container; + FAR vbuf_container_t *container; + int ret = OK; if (vmng == NULL) @@ -918,17 +1554,17 @@ static int video_takepict_start(FAR struct video_mng_s *vmng, if (vmng->still_inf.state != VIDEO_STATE_STREAMOFF) { - ret = -EPERM; + ret = -EPERM; } else { if (capture_num > 0) { - vmng->still_inf.remaining_capnum = capture_num; + vmng->still_inf.remaining_capnum = capture_num; } else { - vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; + vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; } /* Control video stream prior to still stream */ @@ -941,16 +1577,20 @@ static int video_takepict_start(FAR struct video_mng_s *vmng, leave_critical_section(flags); - dma_container = video_framebuff_get_dma_container - (&vmng->still_inf.bufinf); - if (dma_container) + container = video_framebuff_get_vacant_container + (&vmng->still_inf.bufinf); + if (container) { - /* Start video stream DMA */ + /* Start still stream capture */ - g_video_devops->set_buftype(V4L2_BUF_TYPE_STILL_CAPTURE); - g_video_devops->set_buf(dma_container->buf.m.userptr, - dma_container->buf.length); - vmng->still_inf.state = VIDEO_STATE_DMA; + start_capture(V4L2_BUF_TYPE_STILL_CAPTURE, + vmng->still_inf.nr_fmt, + vmng->still_inf.fmt, + &vmng->still_inf.frame_interval, + container->buf.m.userptr, + container->buf.length); + + vmng->still_inf.state = VIDEO_STATE_CAPTURE; } else { @@ -984,9 +1624,9 @@ static int video_takepict_stop(FAR struct video_mng_s *vmng, bool halfpush) else { flags = enter_critical_section(); - if (vmng->still_inf.state == VIDEO_STATE_DMA) + if (vmng->still_inf.state == VIDEO_STATE_CAPTURE) { - g_video_devops->cancel_dma(); + g_video_data_ops->stop_capture(); } leave_critical_section(flags); @@ -1020,14 +1660,8 @@ static int video_queryctrl(FAR struct v4l2_queryctrl *ctrl) /* Replace to VIDIOC_QUERY_EXT_CTRL format */ - ext_ctrl.ctrl_class = ctrl->ctrl_class; - ext_ctrl.id = ctrl->id; - ext_ctrl.type = ctrl->type; - ext_ctrl.minimum = ctrl->minimum; - ext_ctrl.maximum = ctrl->maximum; - ext_ctrl.step = ctrl->step; - ext_ctrl.default_value = ctrl->default_value; - ext_ctrl.flags = ctrl->flags; + ext_ctrl.ctrl_class = ctrl->ctrl_class; + ext_ctrl.id = ctrl->id; ret = video_query_ext_ctrl(&ext_ctrl); @@ -1059,34 +1693,161 @@ static int video_queryctrl(FAR struct v4l2_queryctrl *ctrl) return OK; } -static int video_query_ext_ctrl(FAR struct v4l2_query_ext_ctrl *ctrl) +static void set_parameter_name(uint32_t id, char *name) +{ + int cnt; + int size + = sizeof(g_video_parameter_name) / sizeof(video_parameter_name_t); + + for (cnt = 0; cnt < size; cnt++) + { + if (g_video_parameter_name[cnt].id == id) + { + break; + } + } + + ASSERT(cnt < size); + + /* copy size = 32 is due to V4L2 specification. */ + + strncpy(name, g_video_parameter_name[cnt].name, 32); +} + +static int video_query_ext_ctrl(FAR struct v4l2_query_ext_ctrl *attr) { int ret; + imgsensor_supported_value_t value; + imgsensor_capability_range_t *range = &value.u.range; + imgsensor_capability_discrete_t *disc = &value.u.discrete; + imgsensor_capability_elems_t *elem = &value.u.elems; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_ctrlvalue == NULL)) + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->get_supported_value == NULL) + { + return -ENOTTY; + } + + if (attr == NULL) { return -EINVAL; } - ret = g_video_devops->get_range_of_ctrlvalue(ctrl); + if ((attr->ctrl_class == V4L2_CTRL_CLASS_CAMERA) && + (attr->id == V4L2_CID_SCENE_MODE)) + { + /* Scene mode is processed in only video driver. */ - return ret; + attr->type = V4L2_CTRL_TYPE_INTEGER_MENU; + attr->minimum = 0; + attr->maximum = VIDEO_SCENE_MAX - 1; + attr->step = 1; + attr->default_value = 0; + strncpy(attr->name, "Scene Mode", 32); + } + else + { + ret = g_video_sensor_ops->get_supported_value + (VIDEO_ID(attr->ctrl_class, attr->id), + &value); + if (ret < 0) + { + return ret; + } + + attr->type = value.type; + + switch (value.type) + { + case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: + attr->minimum = 0; + attr->maximum = disc->nr_values - 1; + attr->step = 1; + attr->default_value = disc->default_value; + break; + + case IMGSENSOR_CTRL_TYPE_U8: + case IMGSENSOR_CTRL_TYPE_U16: + case IMGSENSOR_CTRL_TYPE_U32: + attr->minimum = elem->minimum; + attr->maximum = elem->maximum; + attr->step = elem->step; + attr->elems = elem->nr_elems; + break; + + default: + attr->minimum = range->minimum; + attr->maximum = range->maximum; + attr->step = range->step; + attr->default_value = range->default_value; + break; + } + + set_parameter_name(VIDEO_ID(attr->ctrl_class, attr->id), + attr->name); + } + + return OK; } static int video_querymenu(FAR struct v4l2_querymenu *menu) { int ret; + imgsensor_supported_value_t value; - if ((g_video_devops == NULL) || - (g_video_devops->get_menu_of_ctrlvalue == NULL)) + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->get_supported_value == NULL) + { + return -ENOTTY; + } + + if (menu == NULL) { return -EINVAL; } - ret = g_video_devops->get_menu_of_ctrlvalue(menu); + if ((menu->ctrl_class == V4L2_CTRL_CLASS_CAMERA) && + (menu->id == V4L2_CID_SCENE_MODE)) + { + /* Scene mode is processed in only video driver. */ - return ret; + if (menu->index > VIDEO_SCENE_MAX - 1) + { + return -EINVAL; + } + + menu->value = g_video_scene_parameter[menu->index].mode; + } + else + { + ret = g_video_sensor_ops->get_supported_value + (VIDEO_ID(menu->ctrl_class, menu->id), + &value); + if (ret < 0) + { + return ret; + } + + if (value.type != IMGSENSOR_CTRL_TYPE_INTEGER_MENU) + { + /* VIDIOC_QUERYMENU is used only for + * IMGSENSOR_CTRL_TYPE_INTEGER_MENU. + */ + + return -EINVAL; + } + + if (menu->index >= value.u.discrete.nr_values) + { + return -EINVAL; + } + + menu->value = value.u.discrete.values[menu->index]; + } + + return OK; } static int video_g_ctrl(FAR struct video_mng_s *priv, @@ -1158,6 +1919,13 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, int cnt; FAR struct v4l2_ext_control *control; + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->get_value == NULL) + { + return -ENOTTY; + } + if ((priv == NULL) || (ctrls == NULL)) { return -EINVAL; @@ -1167,7 +1935,178 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, cnt < ctrls->count; cnt++, control++) { - ret = g_video_devops->get_ctrlvalue(ctrls->ctrl_class, control); + ret = g_video_sensor_ops->get_value + (VIDEO_ID(ctrls->ctrl_class, control->id), + control->size, + (imgsensor_value_t *)&control->value64); + if (ret < 0) + { + /* Set cnt in that error occurred */ + + ctrls->error_idx = cnt; + return ret; + } + } + + return ret; +} + +static int set_intvalue(uint32_t id, int32_t value32) +{ + imgsensor_value_t value; + + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->set_value == NULL) + { + return -ENOTTY; + } + + value.value32 = value32; + return g_video_sensor_ops->set_value(id, sizeof(int32_t), value); +} + +static int set_pvalue(uint32_t id, int size, void *pval) +{ + imgsensor_value_t value; + + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->set_value == NULL) + { + return -ENOTTY; + } + + value.p_u8 = (uint8_t *)pval; + return g_video_sensor_ops->set_value(id, size, value); +} + +static video_scene_params_t *search_scene_param(enum v4l2_scene_mode mode) +{ + int i; + video_scene_params_t *sp = &g_video_scene_parameter[0]; + + for (i = 0; i < VIDEO_SCENE_MAX; i++, sp++) + { + if (sp->mode == mode) + { + return sp; + } + } + + return NULL; +} + +static int reflect_scene_parameter(enum v4l2_scene_mode mode) +{ + video_scene_params_t *sp; + + sp = search_scene_param(mode); + if (sp == NULL) + { + /* Unsupported scene mode */ + + return -EINVAL; + } + + set_intvalue(IMGSENSOR_ID_BRIGHTNESS, sp->brightness); + set_intvalue(IMGSENSOR_ID_CONTRAST, sp->contrast); + set_intvalue(IMGSENSOR_ID_SATURATION, sp->saturation); + set_intvalue(IMGSENSOR_ID_HUE , sp->hue); + set_intvalue(IMGSENSOR_ID_AUTO_WHITE_BALANCE, sp->awb); + set_intvalue(IMGSENSOR_ID_RED_BALANCE , sp->red); + set_intvalue(IMGSENSOR_ID_BLUE_BALANCE, sp->blue); + set_intvalue(IMGSENSOR_ID_GAMMA, sp->gamma); + set_pvalue(IMGSENSOR_ID_GAMMA_CURVE, sp->gamma_curve_sz, sp->gamma_curve); + set_intvalue(IMGSENSOR_ID_EXPOSURE, sp->ev); + set_intvalue(IMGSENSOR_ID_HFLIP_VIDEO, sp->hflip_video); + set_intvalue(IMGSENSOR_ID_VFLIP_VIDEO, sp->vflip_video); + set_intvalue(IMGSENSOR_ID_HFLIP_STILL, sp->hflip_still); + set_intvalue(IMGSENSOR_ID_VFLIP_STILL, sp->vflip_still); + set_intvalue(IMGSENSOR_ID_SHARPNESS, sp->sharpness); + set_intvalue(IMGSENSOR_ID_COLORFX, sp->colorfx); + set_intvalue(IMGSENSOR_ID_AUTOBRIGHTNESS, sp->auto_brightness); + set_intvalue(IMGSENSOR_ID_ROTATE, sp->rotate); + set_intvalue(IMGSENSOR_ID_EXPOSURE_AUTO, sp->ae); + if ((sp->ae == V4L2_EXPOSURE_MANUAL) || + (sp->ae == V4L2_EXPOSURE_SHUTTER_PRIORITY)) + { + set_intvalue(IMGSENSOR_ID_EXPOSURE_ABSOLUTE, sp->exposure_time); + } + + set_intvalue(IMGSENSOR_ID_FOCUS_ABSOLUTE, sp->focus); + set_intvalue(IMGSENSOR_ID_FOCUS_AUTO, sp->af); + set_intvalue(IMGSENSOR_ID_ZOOM_ABSOLUTE, sp->zoom); + if ((sp->ae == V4L2_EXPOSURE_MANUAL) || + (sp->ae == V4L2_EXPOSURE_APERTURE_PRIORITY)) + { + set_intvalue(IMGSENSOR_ID_IRIS_ABSOLUTE, sp->iris); + } + + set_intvalue(IMGSENSOR_ID_AUTO_N_PRESET_WB, sp->wb); + set_intvalue(IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, sp->wdr); + set_intvalue(IMGSENSOR_ID_IMG_STABILIZATION, sp->stabilization); + set_intvalue(IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, sp->iso_auto); + if (sp->iso_auto == V4L2_ISO_SENSITIVITY_MANUAL) + { + set_intvalue(IMGSENSOR_ID_ISO_SENSITIVITY, sp->iso); + } + + set_intvalue(IMGSENSOR_ID_EXPOSURE_METERING, sp->meter); + set_intvalue(IMGSENSOR_ID_3A_LOCK, sp->threea_lock); + set_intvalue(IMGSENSOR_ID_FLASH_LED_MODE, sp->led); + set_intvalue(IMGSENSOR_ID_JPEG_QUALITY, sp->jpeg_quality); + + g_video_scene_mode = mode; + + return OK; +} + +static int video_s_ext_ctrls(FAR struct video_mng_s *priv, + FAR struct v4l2_ext_controls *ctrls) +{ + int ret = OK; + int cnt; + FAR struct v4l2_ext_control *control; + + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->set_value == NULL) + { + return -ENOTTY; + } + + if ((priv == NULL) || (ctrls == NULL)) + { + return -EINVAL; + } + + for (cnt = 0, control = ctrls->controls; + cnt < ctrls->count; + cnt++, control++) + { + if ((ctrls->ctrl_class == V4L2_CTRL_CLASS_CAMERA) && + (control->id == V4L2_CID_SCENE_MODE)) + { + ret = reflect_scene_parameter(control->value); + } + else + { + ret = g_video_sensor_ops->set_value + (VIDEO_ID(ctrls->ctrl_class, control->id), + control->size, + (imgsensor_value_t)control->value64); + if (ret == 0) + { + if (g_video_scene_mode == V4L2_SCENE_MODE_NONE) + { + save_scene_param + (V4L2_SCENE_MODE_NONE, + VIDEO_ID(ctrls->ctrl_class, control->id), + control); + } + } + } if (ret < 0) { @@ -1181,29 +2120,539 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, return ret; } -static int video_s_ext_ctrls(FAR struct video_mng_s *priv, - FAR struct v4l2_ext_controls *ctrls) +static int video_query_ext_ctrl_scene + (FAR struct v4s_query_ext_ctrl_scene *attr) +{ + if (attr == NULL) + { + return -EINVAL; + } + + return video_query_ext_ctrl(&attr->control); +} + +static int video_querymenu_scene(FAR struct v4s_querymenu_scene *menu) +{ + if (menu == NULL) + { + return -EINVAL; + } + + return video_querymenu(&menu->menu); +} + +static int read_scene_param(enum v4l2_scene_mode mode, + uint32_t id, + struct v4l2_ext_control *control) +{ + int ret = OK; + video_scene_params_t *sp; + imgsensor_supported_value_t value; + + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->get_supported_value == NULL) + { + return -ENOTTY; + } + + if (control == NULL) + { + return -EINVAL; + } + + sp = search_scene_param(mode); + if (sp == NULL) + { + /* Unsupported scene mode */ + + return -EINVAL; + } + + ret = g_video_sensor_ops->get_supported_value(id, &value); + if (ret < 0) + { + /* Unsupported camera parameter */ + + return ret; + } + + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + control->value = sp->brightness; + break; + + case IMGSENSOR_ID_CONTRAST: + control->value = sp->contrast; + break; + + case IMGSENSOR_ID_SATURATION: + control->value = sp->saturation; + break; + + case IMGSENSOR_ID_HUE: + control->value = sp->hue; + break; + + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + control->value = sp->awb; + break; + + case IMGSENSOR_ID_RED_BALANCE: + control->value = sp->red; + break; + + case IMGSENSOR_ID_BLUE_BALANCE: + control->value = sp->blue; + break; + + case IMGSENSOR_ID_GAMMA: + control->value = sp->gamma; + break; + + case IMGSENSOR_ID_GAMMA_CURVE: + memcpy(control->p_u8, + sp->gamma_curve, + sp->gamma_curve_sz); + break; + + case IMGSENSOR_ID_EXPOSURE: + control->value = sp->ev; + break; + + case IMGSENSOR_ID_HFLIP_VIDEO: + control->value = sp->hflip_video; + break; + + case IMGSENSOR_ID_VFLIP_VIDEO: + control->value = sp->vflip_video; + break; + + case IMGSENSOR_ID_HFLIP_STILL: + control->value = sp->hflip_still; + break; + + case IMGSENSOR_ID_VFLIP_STILL: + control->value = sp->vflip_still; + break; + + case IMGSENSOR_ID_SHARPNESS: + control->value = sp->sharpness; + break; + + case IMGSENSOR_ID_COLOR_KILLER: + control->value = (sp->colorfx == V4L2_COLORFX_BW) ? true : false; + break; + + case IMGSENSOR_ID_COLORFX: + control->value = sp->colorfx; + break; + + case IMGSENSOR_ID_AUTOBRIGHTNESS: + control->value = sp->auto_brightness; + break; + + case IMGSENSOR_ID_ROTATE: + control->value = sp->rotate; + break; + + case IMGSENSOR_ID_EXPOSURE_AUTO: + control->value = sp->ae; + break; + + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + control->value = sp->exposure_time; + break; + + case IMGSENSOR_ID_FOCUS_ABSOLUTE: + control->value = sp->focus; + break; + + case IMGSENSOR_ID_FOCUS_AUTO: + control->value = sp->af; + break; + + case IMGSENSOR_ID_ZOOM_ABSOLUTE: + control->value = sp->zoom; + break; + + case IMGSENSOR_ID_IRIS_ABSOLUTE: + control->value = sp->iris; + break; + + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + control->value = sp->wb; + break; + + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + control->value = sp->wdr; + break; + + case IMGSENSOR_ID_IMG_STABILIZATION: + control->value = sp->stabilization; + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY: + control->value = sp->iso; + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + control->value = sp->iso_auto; + break; + + case IMGSENSOR_ID_EXPOSURE_METERING: + control->value = sp->meter; + break; + + case IMGSENSOR_ID_3A_LOCK: + control->value = sp->threea_lock; + break; + + case IMGSENSOR_ID_FLASH_LED_MODE: + control->value = sp->led; + break; + + case IMGSENSOR_ID_JPEG_QUALITY: + control->value = sp->jpeg_quality; + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int video_g_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls) { int ret = OK; int cnt; FAR struct v4l2_ext_control *control; - if ((priv == NULL) || (ctrls == NULL)) + if (ctrls == NULL) { return -EINVAL; } - for (cnt = 0, control = ctrls->controls; - cnt < ctrls->count; + for (cnt = 0, control = ctrls->control.controls; + cnt < ctrls->control.count; cnt++, control++) { - ret = g_video_devops->set_ctrlvalue(ctrls->ctrl_class, control); - - if (ret < 0) + ret = read_scene_param + (ctrls->mode, + VIDEO_ID(ctrls->control.ctrl_class, control->id), + control); + if (ret != OK) { - /* Set cnt in that error occurred */ + ctrls->control.error_idx = cnt; + return ret; + } + } - ctrls->error_idx = cnt; + return ret; +} + +static int check_range(int64_t value, + int64_t min, + int64_t max, + uint64_t step) +{ + if ((value < min) || + (value > max) || + ((value - min) % step != 0)) + { + return -EINVAL; + } + + return OK; +} + +static int save_scene_param(enum v4l2_scene_mode mode, + uint32_t id, + struct v4l2_ext_control *control) +{ + int ret; + int i; + video_scene_params_t *sp; + imgsensor_supported_value_t value; + imgsensor_capability_range_t *range = &value.u.range; + imgsensor_capability_discrete_t *disc = &value.u.discrete; + imgsensor_capability_elems_t *elem = &value.u.elems; + + ASSERT(g_video_sensor_ops); + + if (g_video_sensor_ops->get_supported_value == NULL) + { + return -ENOTTY; + } + + sp = search_scene_param(mode); + if (sp == NULL) + { + /* Unsupported scene mode */ + + return -EINVAL; + } + + ret = g_video_sensor_ops->get_supported_value(id, &value); + if (ret < 0) + { + /* Unsupported camera parameter */ + + return ret; + } + + switch (value.type) + { + case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: + + for (i = 0; i < disc->nr_values; i++) + { + if (control->value == disc->values[i]) + { + break; + } + } + + if (i >= disc->nr_values) + { + return -EINVAL; + } + + break; + + case IMGSENSOR_CTRL_TYPE_U8: + + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u8[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } + + break; + + case IMGSENSOR_CTRL_TYPE_U16: + + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u16[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } + + break; + + case IMGSENSOR_CTRL_TYPE_U32: + + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u32[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } + + break; + + default: + ret = check_range(control->value, + range->minimum, + range->maximum, + range->step); + if (ret != OK) + { + return ret; + } + + break; + } + + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + sp->brightness = control->value; + break; + + case IMGSENSOR_ID_CONTRAST: + sp->contrast = control->value; + break; + + case IMGSENSOR_ID_SATURATION: + sp->saturation = control->value; + break; + + case IMGSENSOR_ID_HUE: + sp->hue = control->value; + break; + + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + sp->awb = control->value; + break; + + case IMGSENSOR_ID_RED_BALANCE: + sp->red = control->value; + break; + + case IMGSENSOR_ID_BLUE_BALANCE: + sp->blue = control->value; + break; + + case IMGSENSOR_ID_GAMMA: + sp->gamma = control->value; + break; + + case IMGSENSOR_ID_GAMMA_CURVE: + memcpy(sp->gamma_curve, + control->p_u8, + sp->gamma_curve_sz); + break; + + case IMGSENSOR_ID_EXPOSURE: + sp->ev = control->value; + break; + + case IMGSENSOR_ID_HFLIP_VIDEO: + sp->hflip_video = control->value; + break; + + case IMGSENSOR_ID_VFLIP_VIDEO: + sp->vflip_video = control->value; + break; + + case IMGSENSOR_ID_HFLIP_STILL: + sp->hflip_still = control->value; + break; + + case IMGSENSOR_ID_VFLIP_STILL: + sp->vflip_still = control->value; + break; + + case IMGSENSOR_ID_SHARPNESS: + sp->sharpness = control->value; + break; + + case IMGSENSOR_ID_COLOR_KILLER: + sp->colorfx = (control->value == true) ? + V4L2_COLORFX_BW : V4L2_COLORFX_NONE; + break; + + case IMGSENSOR_ID_COLORFX: + sp->colorfx = control->value; + break; + + case IMGSENSOR_ID_AUTOBRIGHTNESS: + sp->auto_brightness = control->value; + break; + + case IMGSENSOR_ID_ROTATE: + sp->rotate = control->value; + break; + + case IMGSENSOR_ID_EXPOSURE_AUTO: + sp->ae = control->value; + break; + + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + sp->exposure_time = control->value; + break; + + case IMGSENSOR_ID_FOCUS_ABSOLUTE: + sp->focus = control->value; + break; + + case IMGSENSOR_ID_FOCUS_AUTO: + sp->af = control->value; + break; + + case IMGSENSOR_ID_ZOOM_ABSOLUTE: + sp->zoom = control->value; + break; + + case IMGSENSOR_ID_IRIS_ABSOLUTE: + sp->iris = control->value; + break; + + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + sp->wb = control->value; + break; + + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + sp->wdr = control->value; + break; + + case IMGSENSOR_ID_IMG_STABILIZATION: + sp->stabilization = control->value; + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY: + sp->iso = control->value; + break; + + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + sp->iso_auto = control->value; + break; + + case IMGSENSOR_ID_EXPOSURE_METERING: + sp->meter = control->value; + break; + + case IMGSENSOR_ID_3A_LOCK: + sp->threea_lock = control->value; + break; + + case IMGSENSOR_ID_FLASH_LED_MODE: + sp->led = control->value; + break; + + case IMGSENSOR_ID_JPEG_QUALITY: + sp->jpeg_quality = control->value; + break; + + default: + return -EINVAL; + } + + return OK; +} + +static int video_s_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls) +{ + int ret = OK; + int cnt; + FAR struct v4l2_ext_control *control; + + if (ctrls == NULL) + { + return -EINVAL; + } + + for (cnt = 0, control = ctrls->control.controls; + cnt < ctrls->control.count; + cnt++, control++) + { + ret = save_scene_param + (ctrls->mode, + VIDEO_ID(ctrls->control.ctrl_class, control->id), + control); + if (ret != OK) + { + ctrls->control.error_idx = cnt; return ret; } } @@ -1258,7 +2707,7 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; case VIDIOC_DO_HALFPUSH: - ret = video_do_halfpush(arg); + ret = video_do_halfpush(priv, arg); break; @@ -1272,18 +2721,8 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; - case VIDIOC_ENUM_FMT: - ret = video_enum_fmt((FAR struct v4l2_fmtdesc *)arg); - - break; - - case VIDIOC_ENUM_FRAMESIZES: - ret = video_enum_framesizes((FAR struct v4l2_frmsizeenum *)arg); - - break; - case VIDIOC_TRY_FMT: - ret = video_try_fmt((FAR struct v4l2_format *)arg); + ret = video_try_fmt(priv, (FAR struct v4l2_format *)arg); break; @@ -1292,11 +2731,6 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; - case VIDIOC_ENUM_FRAMEINTERVALS: - ret = video_enum_frameintervals((FAR struct v4l2_frmivalenum *)arg); - - break; - case VIDIOC_S_PARM: ret = video_s_parm(priv, (FAR struct v4l2_streamparm *)arg); @@ -1337,6 +2771,29 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; + case V4SIOC_QUERY_EXT_CTRL_SCENE: + ret = video_query_ext_ctrl_scene + ((FAR struct v4s_query_ext_ctrl_scene *)arg); + + break; + + case V4SIOC_QUERYMENU_SCENE: + ret = video_querymenu_scene((FAR struct v4s_querymenu_scene *)arg); + + break; + + case V4SIOC_G_EXT_CTRLS_SCENE: + ret = video_g_ext_ctrls_scene + ((FAR struct v4s_ext_controls_scene *)arg); + + break; + + case V4SIOC_S_EXT_CTRLS_SCENE: + ret = video_s_ext_ctrls_scene + ((FAR struct v4s_ext_controls_scene *)arg); + + break; + default: videoerr("Unrecognized cmd: %d\n", cmd); ret = - ENOTTY; @@ -1346,46 +2803,6 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return ret; } -static int video_poll_setup(FAR struct video_mng_s *priv, - FAR struct pollfd *fds) -{ - if ((fds->events & POLLIN) == 0) - { - return -EDEADLK; - } - - /* TODO: If data exists, get and nxsem_post If no data, wait dma */ - - return OK; -} - -static int video_poll_teardown(FAR struct video_mng_s *priv, - FAR struct pollfd *fds) -{ - /* TODO: Delete poll wait information */ - - return OK; -} - -static int video_poll(FAR struct file *filep, - FAR struct pollfd *fds, - bool setup) -{ - FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; - - if (setup) - { - return video_poll_setup(priv, fds); - } - else - { - return video_poll_teardown(priv, fds); - } - - return OK; -} - static FAR void *video_register(FAR const char *devpath) { FAR video_mng_t *priv; @@ -1470,12 +2887,96 @@ static int video_unregister(FAR video_mng_t *v_mgr) return ret; } +/* Callback function which device driver call when capture has done. */ + +static int video_complete_capture(uint8_t err_code, uint32_t datasize) +{ + FAR video_mng_t *vmng = (FAR video_mng_t *)video_handler; + FAR video_type_inf_t *type_inf; + FAR vbuf_container_t *container = NULL; + enum v4l2_buf_type buf_type; + irqstate_t flags; + + flags = enter_critical_section(); + + buf_type = (vmng->still_inf.state == VIDEO_STATE_CAPTURE) ? + V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; + + type_inf = get_video_type_inf(vmng, buf_type); + if (type_inf == NULL) + { + leave_critical_section(flags); + return -EINVAL; + } + + if (err_code == 0) + { + type_inf->bufinf.vbuf_curr->buf.flags = 0; + if (type_inf->remaining_capnum > 0) + { + type_inf->remaining_capnum--; + } + } + else + { + type_inf->bufinf.vbuf_curr->buf.flags = V4L2_BUF_FLAG_ERROR; + } + + type_inf->bufinf.vbuf_curr->buf.bytesused = datasize; + video_framebuff_capture_done(&type_inf->bufinf); + + if (is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) + { + /* If waiting capture in DQBUF, + * get/save container and unlock wait + */ + + type_inf->wait_capture.done_container + = video_framebuff_pop_curr_container(&type_inf->bufinf); + type_inf->wait_capture.waitend_cause + = VIDEO_WAITEND_CAUSE_CAPTUREDONE; + nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); + } + + if (type_inf->remaining_capnum == 0) + { + g_video_data_ops->stop_capture(); + type_inf->state = VIDEO_STATE_STREAMOFF; + + /* If stop still stream, notify it to video stream */ + + if ((buf_type == V4L2_BUF_TYPE_STILL_CAPTURE) && + is_sem_waited(&vmng->video_inf.wait_capture.dqbuf_wait_flg)) + { + vmng->video_inf.wait_capture.waitend_cause + = VIDEO_WAITEND_CAUSE_STILLSTOP; + nxsem_post(&vmng->video_inf.wait_capture.dqbuf_wait_flg); + } + } + else + { + container = video_framebuff_get_vacant_container(&type_inf->bufinf); + if (!container) + { + g_video_data_ops->stop_capture(); + type_inf->state = VIDEO_STATE_STREAMON; + } + else + { + g_video_data_ops->set_buf((uint8_t *)container->buf.m.userptr, + container->buf.length); + } + } + + leave_critical_section(flags); + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ -int video_initialize(FAR const char *devpath, - FAR const struct video_devops_s *devops) +int video_initialize(FAR const char *devpath) { if (is_initialized) { @@ -1484,8 +2985,6 @@ int video_initialize(FAR const char *devpath, video_handler = video_register(devpath); - g_video_devops = devops; - is_initialized = true; return OK; @@ -1500,88 +2999,18 @@ int video_uninitialize(void) video_unregister(video_handler); - g_video_devops = NULL; - is_initialized = false; return OK; } -int video_common_notify_dma_done(uint8_t err_code, - uint32_t buf_type, - uint32_t datasize, - FAR void *priv) +void imgsensor_register(const FAR struct imgsensor_ops_s *ops) { - FAR video_mng_t *vmng = (FAR video_mng_t *)priv; - FAR video_type_inf_t *type_inf; - FAR vbuf_container_t *container = NULL; - - type_inf = get_video_type_inf(vmng, buf_type); - if (type_inf == NULL) - { - return -EINVAL; - } - - if (err_code == 0) - { - type_inf->bufinf.vbuf_dma->buf.flags = 0; - if (type_inf->remaining_capnum > 0) - { - type_inf->remaining_capnum--; - } - } - else - { - type_inf->bufinf.vbuf_dma->buf.flags = V4L2_BUF_FLAG_ERROR; - } - - type_inf->bufinf.vbuf_dma->buf.bytesused = datasize; - video_framebuff_dma_done(&type_inf->bufinf); - - if (is_sem_waited(&type_inf->wait_dma.dqbuf_wait_flg)) - { - /* If waiting DMA done in DQBUF, - * get/save container and unlock wait - */ - - type_inf->wait_dma.done_container - = video_framebuff_pop_curr_container(&type_inf->bufinf); - type_inf->wait_dma.waitend_cause - = VIDEO_WAITEND_CAUSE_DMADONE; - nxsem_post(&type_inf->wait_dma.dqbuf_wait_flg); - - /* TODO: in poll wait, unlock wait */ - } - - if (type_inf->remaining_capnum == 0) - { - g_video_devops->cancel_dma(); - type_inf->state = VIDEO_STATE_STREAMOFF; - - /* If stop still stream, notify it to video stream */ - - if ((buf_type == V4L2_BUF_TYPE_STILL_CAPTURE) && - is_sem_waited(&vmng->video_inf.wait_dma.dqbuf_wait_flg)) - { - vmng->video_inf.wait_dma.waitend_cause - = VIDEO_WAITEND_CAUSE_STILLSTOP; - nxsem_post(&vmng->video_inf.wait_dma.dqbuf_wait_flg); - } - } - else - { - container = video_framebuff_get_dma_container(&type_inf->bufinf); - if (!container) - { - g_video_devops->cancel_dma(); - type_inf->state = VIDEO_STATE_STREAMON; - } - else - { - g_video_devops->set_buf(container->buf.m.userptr, - container->buf.length); - } - } - - return OK; + g_video_sensor_ops = ops; } + +void imgdata_register(const FAR struct imgdata_ops_s *ops) +{ + g_video_data_ops = ops; +} + diff --git a/drivers/video/video_framebuff.c b/drivers/video/video_framebuff.c index 37a5b9e229..d4e93d1d21 100644 --- a/drivers/video/video_framebuff.c +++ b/drivers/video/video_framebuff.c @@ -39,11 +39,11 @@ static void init_buf_chain(video_framebuff_t *fbuf) int i; vbuf_container_t *tmp; - fbuf->vbuf_empty = fbuf->vbuf_alloced; - fbuf->vbuf_next_dma = NULL; - fbuf->vbuf_dma = NULL; - fbuf->vbuf_top = NULL; - fbuf->vbuf_tail = NULL; + fbuf->vbuf_empty = fbuf->vbuf_alloced; + fbuf->vbuf_next = NULL; + fbuf->vbuf_curr = NULL; + fbuf->vbuf_top = NULL; + fbuf->vbuf_tail = NULL; tmp = fbuf->vbuf_alloced; for (i = 0; i < fbuf->container_size - 1; i++) @@ -74,9 +74,9 @@ static inline vbuf_container_t *dequeue_vbuf_unsafe(video_framebuff_t *fbuf) vbuf_container_t *ret = fbuf->vbuf_top; if (is_last_one(fbuf)) { - fbuf->vbuf_top = NULL; - fbuf->vbuf_tail = NULL; - fbuf->vbuf_next_dma = NULL; + fbuf->vbuf_top = NULL; + fbuf->vbuf_tail = NULL; + fbuf->vbuf_next = NULL; } else { @@ -97,11 +97,11 @@ static inline vbuf_container_t *dequeue_vbuf_unsafe(video_framebuff_t *fbuf) void video_framebuff_init(video_framebuff_t *fbuf) { - fbuf->mode = V4L2_BUF_MODE_RING; - fbuf->vbuf_empty = NULL; - fbuf->vbuf_top = NULL; - fbuf->vbuf_tail = NULL; - fbuf->vbuf_next_dma = NULL; + fbuf->mode = V4L2_BUF_MODE_RING; + fbuf->vbuf_empty = NULL; + fbuf->vbuf_top = NULL; + fbuf->vbuf_tail = NULL; + fbuf->vbuf_next = NULL; nxsem_init(&fbuf->lock_empty, 0, 1); } @@ -135,7 +135,7 @@ int video_framebuff_realloc_container(video_framebuff_t *fbuf, int sz) if (sz > 0) { fbuf->vbuf_alloced - = (vbuf_container_t *)kmm_malloc(sizeof(vbuf_container_t)*sz); + = (vbuf_container_t *)kmm_malloc(sizeof(vbuf_container_t)*sz); if (fbuf->vbuf_alloced == NULL) { return -ENOMEM; @@ -154,7 +154,7 @@ vbuf_container_t *video_framebuff_get_container(video_framebuff_t *fbuf) { vbuf_container_t *ret; - nxsem_wait(&fbuf->lock_empty); + nxsem_wait_uninterruptible(&fbuf->lock_empty); ret = fbuf->vbuf_empty; if (ret) { @@ -170,7 +170,7 @@ vbuf_container_t *video_framebuff_get_container(video_framebuff_t *fbuf) void video_framebuff_free_container(video_framebuff_t *fbuf, vbuf_container_t *cnt) { - nxsem_wait(&fbuf->lock_empty); + nxsem_wait_uninterruptible(&fbuf->lock_empty); cnt->next = fbuf->vbuf_empty; fbuf->vbuf_empty = cnt; nxsem_post(&fbuf->lock_empty); @@ -186,15 +186,15 @@ void video_framebuff_queue_container(video_framebuff_t *fbuf, { fbuf->vbuf_tail->next = tgt; fbuf->vbuf_tail = tgt; - if (fbuf->vbuf_next_dma == NULL) + if (fbuf->vbuf_next == NULL) { - fbuf->vbuf_next_dma = tgt; + fbuf->vbuf_next = tgt; } } else { fbuf->vbuf_top = fbuf->vbuf_tail = tgt; - fbuf->vbuf_next_dma = tgt; + fbuf->vbuf_next = tgt; } if (fbuf->mode == V4L2_BUF_MODE_RING) @@ -215,7 +215,7 @@ vbuf_container_t *video_framebuff_dq_valid_container(video_framebuff_t *fbuf) vbuf_container_t *ret = NULL; flags = enter_critical_section(); - if (fbuf->vbuf_top != NULL && fbuf->vbuf_top != fbuf->vbuf_next_dma) + if (fbuf->vbuf_top != NULL && fbuf->vbuf_top != fbuf->vbuf_next) { ret = dequeue_vbuf_unsafe(fbuf); } @@ -225,25 +225,26 @@ vbuf_container_t *video_framebuff_dq_valid_container(video_framebuff_t *fbuf) return ret; } -vbuf_container_t *video_framebuff_get_dma_container(video_framebuff_t *fbuf) +vbuf_container_t *video_framebuff_get_vacant_container + (video_framebuff_t *fbuf) { irqstate_t flags; vbuf_container_t *ret; flags = enter_critical_section(); - ret = fbuf->vbuf_dma = fbuf->vbuf_next_dma; + ret = fbuf->vbuf_curr = fbuf->vbuf_next; leave_critical_section(flags); return ret; } -void video_framebuff_dma_done(video_framebuff_t *fbuf) +void video_framebuff_capture_done(video_framebuff_t *fbuf) { - fbuf->vbuf_dma = NULL; - if (fbuf->vbuf_next_dma) + fbuf->vbuf_curr = NULL; + if (fbuf->vbuf_next) { - fbuf->vbuf_next_dma = fbuf->vbuf_next_dma->next; - if (fbuf->vbuf_next_dma == fbuf->vbuf_top) /* RING mode case. */ + fbuf->vbuf_next = fbuf->vbuf_next->next; + if (fbuf->vbuf_next == fbuf->vbuf_top) /* RING mode case. */ { fbuf->vbuf_top = fbuf->vbuf_top->next; fbuf->vbuf_tail = fbuf->vbuf_tail->next; @@ -264,12 +265,12 @@ void video_framebuff_change_mode(video_framebuff_t *fbuf, if (mode == V4L2_BUF_MODE_RING) { fbuf->vbuf_tail->next = fbuf->vbuf_top; - fbuf->vbuf_next_dma = fbuf->vbuf_top; + fbuf->vbuf_next = fbuf->vbuf_top; } else { fbuf->vbuf_tail->next = NULL; - fbuf->vbuf_next_dma = fbuf->vbuf_top; + fbuf->vbuf_next = fbuf->vbuf_top; } } diff --git a/drivers/video/video_framebuff.h b/drivers/video/video_framebuff.h index 06feff3df9..beda4d45fc 100644 --- a/drivers/video/video_framebuff.h +++ b/drivers/video/video_framebuff.h @@ -29,7 +29,7 @@ #include /**************************************************************************** - * Public Functions Definistions + * Public Types ****************************************************************************/ struct vbuf_container_s @@ -49,12 +49,16 @@ struct video_framebuff_s vbuf_container_t *vbuf_empty; vbuf_container_t *vbuf_top; vbuf_container_t *vbuf_tail; - vbuf_container_t *vbuf_dma; - vbuf_container_t *vbuf_next_dma; + vbuf_container_t *vbuf_curr; + vbuf_container_t *vbuf_next; }; typedef struct video_framebuff_s video_framebuff_t; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + /* Buffer access interface. */ void video_framebuff_init @@ -71,13 +75,13 @@ void video_framebuff_queue_container (video_framebuff_t *fbuf, vbuf_container_t *tgt); vbuf_container_t *video_framebuff_dq_valid_container (video_framebuff_t *fbuf); -vbuf_container_t *video_framebuff_get_dma_container +vbuf_container_t *video_framebuff_get_vacant_container (video_framebuff_t *fbuf); vbuf_container_t *video_framebuff_pop_curr_container (video_framebuff_t *fbuf); -void video_framebuff_dma_done +void video_framebuff_capture_done (video_framebuff_t *fbuf); void video_framebuff_change_mode (video_framebuff_t *fbuf, enum v4l2_buf_mode mode); -#endif // __VIDEO_VIDEO_FRAMEBUFF_H__ +#endif // __VIDEO_VIDEO_FRAMEBUFF_H__ diff --git a/include/nuttx/video/imgdata.h b/include/nuttx/video/imgdata.h new file mode 100644 index 0000000000..1847754fc1 --- /dev/null +++ b/include/nuttx/video/imgdata.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * include/nuttx/video/imgdata.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_VIDEO_IMGDATA_H +#define __INCLUDE_NUTTX_VIDEO_IMGDATA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Format definition for start_capture() and validate_frame_setting */ + +#define IMGDATA_FMT_MAX (2) +#define IMGDATA_FMT_MAIN (0) +#define IMGDATA_FMT_SUB (1) +#define IMGDATA_PIX_FMT_UYVY (0) +#define IMGDATA_PIX_FMT_RGB565 (1) +#define IMGDATA_PIX_FMT_JPEG (2) +#define IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG (3) +#define IMGDATA_PIX_FMT_SUBIMG_UYVY (4) +#define IMGDATA_PIX_FMT_SUBIMG_RGB565 (5) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* structure for validate_frame_setting() and start_capture() */ + +typedef struct imgdata_format_s +{ + uint16_t width; + uint16_t height; + uint32_t pixelformat; +} imgdata_format_t; + +typedef struct imgdata_interval_s +{ + uint32_t numerator; + uint32_t denominator; +} imgdata_interval_t; + +typedef int (*imgdata_capture_t)(uint8_t result, uint32_t size); + +/* Structure for Data Control I/F */ + +struct imgdata_ops_s +{ + CODE int (*init)(void); + CODE int (*uninit)(void); + + CODE int (*validate_buf)(uint8_t *addr, uint32_t size); + CODE int (*set_buf)(uint8_t *addr, uint32_t size); + + CODE int (*validate_frame_setting)(uint8_t nr_datafmts, + FAR imgdata_format_t *datafmts, + FAR imgdata_interval_t *interval); + CODE int (*start_capture)(uint8_t nr_datafmts, + FAR imgdata_format_t *datafmts, + FAR imgdata_interval_t *interval, + FAR imgdata_capture_t callback); + CODE int (*stop_capture)(void); +}; + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Register image data operations. */ + +void imgdata_register(const FAR struct imgdata_ops_s *ops); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_VIDEO_IMGDATA_H */ diff --git a/include/nuttx/video/imgsensor.h b/include/nuttx/video/imgsensor.h new file mode 100644 index 0000000000..2545772c6c --- /dev/null +++ b/include/nuttx/video/imgsensor.h @@ -0,0 +1,350 @@ +/**************************************************************************** + * include/nuttx/video/imgsensor.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_VIDEO_IMGSENSOR_H +#define __INCLUDE_NUTTX_VIDEO_IMGSENSOR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Camera parameter IDs */ + +#define IMGSENSOR_ID_BRIGHTNESS (0x00000000) +#define IMGSENSOR_ID_CONTRAST (0x00000001) +#define IMGSENSOR_ID_SATURATION (0x00000002) +#define IMGSENSOR_ID_HUE (0x00000003) +#define IMGSENSOR_ID_AUTO_WHITE_BALANCE (0x00000004) +#define IMGSENSOR_ID_RED_BALANCE (0x00000005) +#define IMGSENSOR_ID_BLUE_BALANCE (0x00000006) +#define IMGSENSOR_ID_GAMMA (0x00000007) +#define IMGSENSOR_ID_GAMMA_CURVE (0x00000008) +#define IMGSENSOR_ID_EXPOSURE (0x00000009) +#define IMGSENSOR_ID_HFLIP_VIDEO (0x0000000a) +#define IMGSENSOR_ID_VFLIP_VIDEO (0x0000000b) +#define IMGSENSOR_ID_HFLIP_STILL (0x0000000c) +#define IMGSENSOR_ID_VFLIP_STILL (0x0000000d) +#define IMGSENSOR_ID_SHARPNESS (0x0000000e) +#define IMGSENSOR_ID_COLOR_KILLER (0x0000000f) +#define IMGSENSOR_ID_COLORFX (0x00000010) +#define IMGSENSOR_ID_AUTOBRIGHTNESS (0x00000011) +#define IMGSENSOR_ID_ROTATE (0x00000012) +#define IMGSENSOR_ID_EXPOSURE_AUTO (0x00010000) +#define IMGSENSOR_ID_EXPOSURE_ABSOLUTE (0x00010001) +#define IMGSENSOR_ID_FOCUS_ABSOLUTE (0x00010002) +#define IMGSENSOR_ID_FOCUS_RELATIVE (0x00010003) +#define IMGSENSOR_ID_FOCUS_AUTO (0x00010004) +#define IMGSENSOR_ID_ZOOM_ABSOLUTE (0x00010005) +#define IMGSENSOR_ID_ZOOM_RELATIVE (0x00010006) +#define IMGSENSOR_ID_ZOOM_CONTINUOUS (0x00010007) +#define IMGSENSOR_ID_IRIS_ABSOLUTE (0x00010008) +#define IMGSENSOR_ID_IRIS_RELATIVE (0x00010009) +#define IMGSENSOR_ID_AUTO_N_PRESET_WB (0x0001000a) +#define IMGSENSOR_ID_WIDE_DYNAMIC_RANGE (0x0001000b) +#define IMGSENSOR_ID_IMG_STABILIZATION (0x0001000c) +#define IMGSENSOR_ID_ISO_SENSITIVITY (0x0001000d) +#define IMGSENSOR_ID_ISO_SENSITIVITY_AUTO (0x0001000e) +#define IMGSENSOR_ID_EXPOSURE_METERING (0x0001000f) +#define IMGSENSOR_ID_3A_LOCK (0x00010011) +#define IMGSENSOR_ID_AUTO_FOCUS_START (0x00010012) +#define IMGSENSOR_ID_AUTO_FOCUS_STOP (0x00010013) +#define IMGSENSOR_ID_3A_PARAMETER (0x00010014) +#define IMGSENSOR_ID_3A_STATUS (0x00010015) +#define IMGSENSOR_ID_FLASH_LED_MODE (0x00020000) +#define IMGSENSOR_ID_JPEG_QUALITY (0x00030000) + +/* bit definition for IMGSENSOR_ID_3A_LOCK */ + +#define IMGSENSOR_LOCK_EXPOSURE (1 << 0) +#define IMGSENSOR_LOCK_WHITE_BALANCE (1 << 1) +#define IMGSENSOR_LOCK_FOCUS (1 << 2) + +/* Status bit definition for IMGSENSOR_ID_3A_STATUS */ + +#define IMGSENSOR_3A_STATUS_STABLE (0) +#define IMGSENSOR_3A_STATUS_AE_OPERATING (1 << 0) +#define IMGSENSOR_3A_STATUS_AWB_OPERATING (1 << 1) +#define IMGSENSOR_3A_STATUS_AF_OPERATING (1 << 2) + +/* Format definition for start_capture() and validate_frame_setting */ + +#define IMGSENSOR_FMT_MAX (2) +#define IMGSENSOR_FMT_MAIN (0) +#define IMGSENSOR_FMT_SUB (1) +#define IMGSENSOR_PIX_FMT_UYVY (0) +#define IMGSENSOR_PIX_FMT_RGB565 (1) +#define IMGSENSOR_PIX_FMT_JPEG (2) +#define IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG (3) +#define IMGSENSOR_PIX_FMT_SUBIMG_UYVY (4) +#define IMGSENSOR_PIX_FMT_SUBIMG_RGB565 (5) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* enumeration for VIDEO_ID_COLORFX */ + +typedef enum imgsensor_colorfx_e +{ + IMGSENSOR_COLORFX_NONE = 0, + IMGSENSOR_COLORFX_BW = 1, + IMGSENSOR_COLORFX_SEPIA = 2, + IMGSENSOR_COLORFX_NEGATIVE = 3, + IMGSENSOR_COLORFX_EMBOSS = 4, + IMGSENSOR_COLORFX_SKETCH = 5, + IMGSENSOR_COLORFX_SKY_BLUE = 6, + IMGSENSOR_COLORFX_GRASS_GREEN = 7, + IMGSENSOR_COLORFX_SKIN_WHITEN = 8, + IMGSENSOR_COLORFX_VIVID = 9, + IMGSENSOR_COLORFX_AQUA = 10, + IMGSENSOR_COLORFX_ART_FREEZE = 11, + IMGSENSOR_COLORFX_SILHOUETTE = 12, + IMGSENSOR_COLORFX_SOLARIZATION = 13, + IMGSENSOR_COLORFX_ANTIQUE = 14, + IMGSENSOR_COLORFX_SET_CBCR = 15, + IMGSENSOR_COLORFX_PASTEL = 16, +} imgsensor_colorfx_t; + +/* enumeration for IMGSENSOR_ID_EXPOSURE_AUTO */ + +typedef enum imgsensor_exposure_auto_type_e +{ + /* exposure time:auto, iris aperture:auto */ + + IMGSENSOR_EXPOSURE_AUTO = 0, + + /* exposure time:manual, iris aperture:manual */ + + IMGSENSOR_EXPOSURE_MANUAL = 1, + + /* exposure time:manual, iris aperture:auto */ + + IMGSENSOR_EXPOSURE_SHUTTER_PRIORITY = 2, + + /* exposure time:auto, iris aperture:manual */ + + IMGSENSOR_EXPOSURE_APERTURE_PRIORITY = 3 +} imgsensor_exposure_auto_type_t; + +/* enumeration for IMGSENSOR_ID_AUTO_N_PRESET_WHITE_BALANCE */ + +typedef enum imgsensor_white_balance_e +{ + IMGSENSOR_WHITE_BALANCE_MANUAL = 0, + IMGSENSOR_WHITE_BALANCE_AUTO = 1, + IMGSENSOR_WHITE_BALANCE_INCANDESCENT = 2, + IMGSENSOR_WHITE_BALANCE_FLUORESCENT = 3, + IMGSENSOR_WHITE_BALANCE_FLUORESCENT_H = 4, + IMGSENSOR_WHITE_BALANCE_HORIZON = 5, + IMGSENSOR_WHITE_BALANCE_DAYLIGHT = 6, + IMGSENSOR_WHITE_BALANCE_FLASH = 7, + IMGSENSOR_WHITE_BALANCE_CLOUDY = 8, + IMGSENSOR_WHITE_BALANCE_SHADE = 9, +} imgsensor_white_balance_t; + +/* enumeration for IMGSENSOR_ID_ISO_SENSITIVITY_AUTO */ + +typedef enum imgsensor_iso_sensitivity_auto_type_e +{ + IMGSENSOR_ISO_SENSITIVITY_MANUAL = 0, + IMGSENSOR_ISO_SENSITIVITY_AUTO = 1, +} imgsensor_iso_sensitivity_auto_type_t; + +/* enumeration for IMGSENSOR_ID_EXPOSURE_METERING */ + +typedef enum imgsensor_exposure_metering_e +{ + IMGSENSOR_EXPOSURE_METERING_AVERAGE = 0, + IMGSENSOR_EXPOSURE_METERING_CENTER_WEIGHTED = 1, + IMGSENSOR_EXPOSURE_METERING_SPOT = 2, + IMGSENSOR_EXPOSURE_METERING_MATRIX = 3, +} imgsensor_exposure_metering_t; + +/* enumeration for IMGSENSOR_ID_FLASH_LED_MODE */ + +typedef enum imgsensor_flash_led_mode_e +{ + IMGSENSOR_FLASH_LED_MODE_NONE = 0, + IMGSENSOR_FLASH_LED_MODE_FLASH = 1, + IMGSENSOR_FLASH_LED_MODE_TORCH = 2, +} imgsensor_flash_led_mode_t; + +/* enumeration for get_supported_value() */ + +typedef enum imgsensor_ctrl_type_e +{ + IMGSENSOR_CTRL_TYPE_INTEGER = 1, + IMGSENSOR_CTRL_TYPE_BOOLEAN = 2, + IMGSENSOR_CTRL_TYPE_INTEGER64 = 5, + IMGSENSOR_CTRL_TYPE_BITMASK = 8, + IMGSENSOR_CTRL_TYPE_INTEGER_MENU = 9, + IMGSENSOR_CTRL_TYPE_U8FIXEDPOINT_Q7 = 10, + IMGSENSOR_CTRL_TYPE_U16FIXEDPOINT_Q8 = 11, + IMGSENSOR_CTRL_TYPE_INTEGER_TIMES_3 = 12, + IMGSENSOR_CTRL_TYPE_U8 = 0x0100, + IMGSENSOR_CTRL_TYPE_U16 = 0x0101, + IMGSENSOR_CTRL_TYPE_U32 = 0x0102, +} imgsensor_ctrl_type_t; + +/* enumeration for stream */ + +typedef enum imgsensor_stream_type_e +{ + IMGSENSOR_STREAM_TYPE_VIDEO = 0, + IMGSENSOR_STREAM_TYPE_STILL = 1, +} imgsensor_stream_type_t; + +/* structure for validate_frame_setting() and start_capture() */ + +typedef struct imgsensor_format_s +{ + uint16_t width; + uint16_t height; + uint32_t pixelformat; +} imgsensor_format_t; + +typedef struct imgsensor_interval_s +{ + uint32_t numerator; + uint32_t denominator; +} imgsensor_interval_t; + +/* structure for get_supported_value() */ + +typedef struct imgsensor_capability_range_s +{ + int64_t minimum; + int64_t maximum; + uint64_t step; + int64_t default_value; +} imgsensor_capability_range_t; + +typedef struct imgsensor_capability_discrete_s +{ + int8_t nr_values; + int32_t *values; + int32_t default_value; +} imgsensor_capability_discrete_t; + +typedef struct imgsensor_capability_elems_s +{ + uint32_t nr_elems; + int64_t minimum; + int64_t maximum; + uint64_t step; +} imgsensor_capability_elems_t; + +typedef struct imgsensor_supported_value_s +{ + imgsensor_ctrl_type_t type; /* control type */ + union + { + /* Use 'range' member in the following types cases. + * IMGSENSOR_CTRL_TYPE_INTEGER + * IMGSENSOR_CTRL_TYPE_BOOLEAN + * IMGSENSOR_CTRL_TYPE_INTEGER64 + * IMGSENSOR_CTRL_TYPE_BITMASK + * IMGSENSOR_CTRL_TYPE_U8FIXEDPOINT_Q7 + * IMGSENSOR_CTRL_TYPE_U16FIXEDPOINT_Q8 + * IMGSENSOR_CTRL_TYPE_INTEGER_TIMES_3 + */ + + imgsensor_capability_range_t range; + + /* Use 'discrete' member in the following type case. + * IMGSENSOR_CTRL_TYPE_INTEGER_MENU + */ + + imgsensor_capability_discrete_t discrete; + + /* Use 'elems' member in the following types cases. + * IMGSENSOR_CTRL_TYPE_U8 + * IMGSENSOR_CTRL_TYPE_U16 + * IMGSENSOR_CTRL_TYPE_U32 + */ + + imgsensor_capability_elems_t elems; + } u; +} imgsensor_supported_value_t; + +typedef union imgsensor_value_u +{ + int32_t value32; + int64_t value64; + uint8_t *p_u8; + uint16_t *p_u16; + uint32_t *p_u32; +} imgsensor_value_t; + +/* Structure for Image Sensor I/F */ + +struct imgsensor_ops_s +{ + CODE int (*init)(void); + CODE int (*uninit)(void); + + CODE int (*validate_frame_setting)(imgsensor_stream_type_t type, + uint8_t nr_datafmts, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); + CODE int (*start_capture)(imgsensor_stream_type_t type, + uint8_t nr_datafmts, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); + CODE int (*stop_capture)(imgsensor_stream_type_t type); + + CODE int (*get_supported_value)(uint32_t id, + FAR imgsensor_supported_value_t *value); + CODE int (*get_value)(uint32_t id, + uint32_t size, + FAR imgsensor_value_t *value); + CODE int (*set_value)(uint32_t id, + uint32_t size, + imgsensor_value_t value); +}; + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Register image sensor operations. */ + +void imgsensor_register(const FAR struct imgsensor_ops_s *ops); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_VIDEO_HALIF_H */ diff --git a/include/nuttx/video/isx012.h b/include/nuttx/video/isx012.h index 61a61a772a..7130a4035b 100644 --- a/include/nuttx/video/isx012.h +++ b/include/nuttx/video/isx012.h @@ -49,7 +49,7 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -FAR struct video_devops_s *isx012_initialize(void); +int isx012_initialize(FAR struct i2c_master_s *i2c); int isx012_uninitialize(void); #undef EXTERN diff --git a/include/nuttx/video/video.h b/include/nuttx/video/video.h index 4dbe4b1e7b..63e83fbd96 100644 --- a/include/nuttx/video/video.h +++ b/include/nuttx/video/video.h @@ -25,10 +25,8 @@ * Included Files ****************************************************************************/ -#include -#include #include - +#include #include "video_controls.h" #ifdef __cplusplus @@ -150,6 +148,30 @@ extern "C" #define VIDIOC_CANCEL_DQBUF _VIDIOC(0x0016) +/* Query control for scene parameter + * Address pointing to struct v4s_query_ext_ctrl_scene + */ + +#define V4SIOC_QUERY_EXT_CTRL_SCENE _VIDIOC(0x0017) + +/* Query menu for scene parameter + * Address pointing to struct v4s_querymenu_scene + */ + +#define V4SIOC_QUERYMENU_SCENE _VIDIOC(0x0018) + +/* Get current control value + * Address pointing to struct v4s_ext_controls_scene + */ + +#define V4SIOC_G_EXT_CTRLS_SCENE _VIDIOC(0x0019) + +/* Set control value + * Address pointing to struct v4s_ext_controls_scene + */ + +#define V4SIOC_S_EXT_CTRLS_SCENE _VIDIOC(0x001a) + #define VIDEO_HSIZE_QVGA (320) /* QVGA horizontal size */ #define VIDEO_VSIZE_QVGA (240) /* QVGA vertical size */ #define VIDEO_HSIZE_VGA (640) /* VGA horizontal size */ @@ -188,6 +210,14 @@ extern "C" #define V4L2_PIX_FMT_JPEG_WITH_SUBIMG v4l2_fourcc('J', 'S', 'U', 'B') +/* YUV 4:2:2 for sub image */ + +#define V4L2_PIX_FMT_SUBIMG_UYVY v4l2_fourcc('S', 'Y', 'U', 'V') + +/* RGB565 for sub image */ + +#define V4L2_PIX_FMT_SUBIMG_RGB565 v4l2_fourcc('S', 'R', 'G', 'B') + /* MAX length of v4l2_fmtdesc description string */ #define V4L2_FMT_DSC_MAX (32) @@ -343,14 +373,13 @@ struct v4l2_fmtdesc uint32_t flags; char description[V4L2_FMT_DSC_MAX]; /* Description string */ uint32_t pixelformat; /* Format fourcc */ - uint32_t subimg_pixelformat; /* Format fourcc */ }; enum v4l2_frmsizetypes { - V4L2_FRMSIZE_TYPE_DISCRETE = 1, /* Discrete value */ + V4L2_FRMSIZE_TYPE_DISCRETE = 1, /* Discrete value */ V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, /* Continuous value */ - V4L2_FRMSIZE_TYPE_STEPWISE = 3, /* Step value */ + V4L2_FRMSIZE_TYPE_STEPWISE = 3, /* Step value */ }; struct v4l2_frmsize_discrete @@ -375,33 +404,16 @@ struct v4l2_frmsizeenum uint32_t buf_type; /* enum #v4l2_buf_type */ uint32_t pixel_format; /* Pixel format */ uint32_t type; /* Frame size type the device supports. */ - union - { /* Frame size */ - struct v4l2_frmsize_discrete discrete; /* Use in type = - * V4L2_FRMSIZE_TYPE_DISCRETE - * case - */ - struct v4l2_frmsize_stepwise stepwise; /* Use in type = - * V4L2_FRMSIZE_TYPE_CONTINUOUS - * or V4L2_FRMSIZE_TYPE_STEPWISE - * case - */ - }; - uint32_t subimg_pixel_format; /* Pixel format of sub image */ - uint32_t subimg_type; /* Frame size type of subimage. */ + + /* In type == V4L2_FRMSIZE_TYPE_DISCRETE case, use discrete. + * Otherwise, use stepwise. + */ union - { /* Frame size of subimage */ - struct v4l2_frmsize_discrete discrete; /* Use in subimg_type = - * V4L2_FRMSIZE_TYPE_DISCRETE - * case - */ - struct v4l2_frmsize_stepwise stepwise; /* Use in subimg_type = - * V4L2_FRMSIZE_TYPE_CONTINUOUS - * or V4L2_FRMSIZE_TYPE_STEPWISE - * case - */ - } subimg; + { + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; }; /* type of frame interval enumeration */ @@ -437,9 +449,6 @@ struct v4l2_frmivalenum uint32_t pixel_format; /* Pixel format */ uint16_t width; /* Frame width */ uint16_t height; /* Frame height */ - uint32_t subimg_pixel_format; /* Pixel format for sub image */ - uint16_t subimg_width; /* Frame width for sub image */ - uint16_t subimg_height; /* Frame height for sub image */ uint32_t type; /* Frame interval type */ union { /* Frame interval */ @@ -455,9 +464,6 @@ struct v4l2_pix_format uint16_t width; /* Image width in pixels */ uint16_t height; /* Image height in pixels */ uint32_t pixelformat; /* The pixel format or type of compression. */ - uint16_t subimg_width; /* sub image width in pixels in case of pixelformat = V4L2_PIX_FMT_JPEG_WITH_SUBIMG */ - uint16_t subimg_height; /* sub image height in pixels in case of pixelformat = V4L2_PIX_FMT_JPEG_WITH_SUBIMG */ - uint32_t subimg_pixelformat; /* The pixel format of sub image in case of pixelformat = V4L2_PIX_FMT_JPEG_WITH_SUBIMG */ uint32_t field; /* enum #v4l2_field */ uint32_t bytesperline; /* for padding, zero if unused */ uint32_t sizeimage; /* Size in bytes of the buffer to hold a complete image */ @@ -556,7 +562,7 @@ struct v4l2_query_ext_ctrl uint32_t dims[V4L2_CTRL_MAX_DIMS]; /* Dimensions */ }; -begin_packed_struct struct v4l2_querymenu +struct v4l2_querymenu { uint16_t ctrl_class; /* camera control class */ uint16_t id; /* camera control id */ @@ -566,7 +572,7 @@ begin_packed_struct struct v4l2_querymenu char name[32]; /* name of menu */ int64_t value; /* value of menu */ }; -} end_packed_struct; +}; struct v4l2_control { @@ -578,7 +584,7 @@ struct v4l2_control * ioctl(VIDIOC_G_EXT_CTRLS / VIDIOC_S_EXT_CTRLS) */ -begin_packed_struct struct v4l2_ext_control +struct v4l2_ext_control { uint16_t id; /* camera control id */ uint16_t size; /* size of value(not use) */ @@ -592,7 +598,7 @@ begin_packed_struct struct v4l2_ext_control uint32_t *p_u32; /* QUERY_EXT_CTRL type = U32 */ void *ptr; }; -} end_packed_struct; +}; struct v4l2_ext_controls { @@ -606,9 +612,29 @@ struct v4l2_ext_controls struct v4l2_ext_control *controls; /* each control information */ }; -/**************************************************************************** - * Public Data - ****************************************************************************/ +/* Structure for V4SIOC_S_EXT_CTRLS and V4SIOC_G_EXT_CTRLS */ + +struct v4s_ext_controls_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be controled */ + struct v4l2_ext_controls control; /* same as VIDIOC_S_EXT_CTRLS */ +}; + +/* Structure for V4SIOC_QUERY_EXT_CTRL */ + +struct v4s_query_ext_ctrl_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be queried */ + struct v4l2_query_ext_ctrl control; /* same as VIDIOC_QUERY_EXT_CTRL */ +}; + +/* Structure for V4SIOC_QUERYMENU */ + +struct v4s_querymenu_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be queried */ + struct v4l2_querymenu menu; /* same as VIDIOC_QUERYMENU */ +}; /**************************************************************************** * Public Function Prototypes @@ -622,8 +648,7 @@ struct v4l2_ext_controls * negative value is returned. */ -int video_initialize(FAR const char *devpath, - FAR const struct video_devops_s *devops); +int video_initialize(FAR const char *devpath); /* Uninitialize video driver. * diff --git a/include/nuttx/video/video_halif.h b/include/nuttx/video/video_halif.h deleted file mode 100644 index c6791aecb7..0000000000 --- a/include/nuttx/video/video_halif.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** - * include/nuttx/video/video_halif.h - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you 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. - * - ****************************************************************************/ - -#ifndef __INCLUDE_NUTTX_VIDEO_HALIF_H -#define __INCLUDE_NUTTX_VIDEO_HALIF_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ -#include - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -struct video_devops_s -{ - CODE int (*open)(FAR void *video_priv); - CODE int (*close)(void); - - CODE int (*do_halfpush)(bool enable); - CODE int (*set_buftype)(enum v4l2_buf_type type); - CODE int (*set_buf)(uint32_t bufaddr, uint32_t bufsize); - CODE int (*cancel_dma)(void); - CODE int (*get_range_of_fmt)(FAR struct v4l2_fmtdesc *format); - CODE int (*get_range_of_framesize)(FAR struct v4l2_frmsizeenum *frmsize); - CODE int (*try_format)(FAR struct v4l2_format *format); - CODE int (*set_format)(FAR struct v4l2_format *format); - CODE int (*get_range_of_frameinterval) - (FAR struct v4l2_frmivalenum *frmival); - CODE int (*set_frameinterval)(FAR struct v4l2_streamparm *parm); - CODE int (*get_range_of_ctrlvalue)(FAR struct v4l2_query_ext_ctrl *range); - CODE int (*get_menu_of_ctrlvalue)(FAR struct v4l2_querymenu *menu); - CODE int (*get_ctrlvalue)(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); - CODE int (*set_ctrlvalue)(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); - CODE int (*refresh)(void); -}; - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -#ifdef __cplusplus -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -/**************************************************************************** - * Public Functions Definitions - ****************************************************************************/ - -int video_common_notify_dma_done(uint8_t err_code, - uint32_t buf_type, - uint32_t datasize, - FAR void *priv); - -#undef EXTERN -#ifdef __cplusplus -} -#endif - -#endif /* __INCLUDE_NUTTX_VIDEO_HALIF_H */