You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/05/31 11:52:41 UTC

[incubator-nuttx] 01/02: drivers: video: add isx019 camera sensor

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 72f399e0528b5aebc10ba3da1fb7a7cddea9c928
Author: Alin Jerpelea <al...@sony.com>
AuthorDate: Wed May 11 07:59:27 2022 +0000

    drivers: video: add isx019 camera sensor
    
    The driver is provided by Spresense SDK
    
    ISX019 has the DOL-HDR feature, which combines images with different exposure so that
    both bright and dark data of high-contrast subject can be viewed at the same time.
    
    Signed-off-by: Alin Jerpelea <al...@sony.com>
---
 boards/arm/cxd56xx/common/src/Make.defs            |    4 +
 boards/arm/cxd56xx/common/src/cxd56_isx019.c       |  203 ++
 boards/arm/cxd56xx/spresense/include/board.h       |    7 +-
 .../arm/cxd56xx/spresense/include/cxd56_isx019.h   |  131 +
 boards/arm/cxd56xx/spresense/src/cxd56_bringup.c   |   12 +-
 drivers/video/Kconfig                              |   35 +
 drivers/video/Make.defs                            |    4 +
 drivers/video/isx019.c                             | 3249 ++++++++++++++++++++
 drivers/video/isx019_range.h                       |  133 +
 drivers/video/isx019_reg.h                         |  408 +++
 include/nuttx/video/isx019.h                       |   55 +
 11 files changed, 4238 insertions(+), 3 deletions(-)

diff --git a/boards/arm/cxd56xx/common/src/Make.defs b/boards/arm/cxd56xx/common/src/Make.defs
index 572a772536..5c0e6a66d7 100644
--- a/boards/arm/cxd56xx/common/src/Make.defs
+++ b/boards/arm/cxd56xx/common/src/Make.defs
@@ -154,6 +154,10 @@ ifeq ($(CONFIG_VIDEO_ISX012),y)
 CSRCS += cxd56_isx012.c
 endif
 
+ifeq ($(CONFIG_VIDEO_ISX019),y)
+CSRCS += cxd56_isx019.c
+endif
+
 ifeq ($(CONFIG_CXD56_IMAGEPROC),y)
   CSRCS += cxd56_imageproc.c
 endif
diff --git a/boards/arm/cxd56xx/common/src/cxd56_isx019.c b/boards/arm/cxd56xx/common/src/cxd56_isx019.c
new file mode 100644
index 0000000000..b8aed7043a
--- /dev/null
+++ b/boards/arm/cxd56xx/common/src/cxd56_isx019.c
@@ -0,0 +1,203 @@
+/****************************************************************************
+ * boards/arm/cxd56xx/common/src/cxd56_isx019.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 <nuttx/config.h>
+
+#include <stdio.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/board.h>
+#include <nuttx/signal.h>
+
+#include "cxd56_gpio.h"
+#include "cxd56_pinconfig.h"
+#include "cxd56_i2c.h"
+#include "cxd56_clock.h"
+
+#include <arch/board/board.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Check if the following are defined in the board.h */
+
+#ifndef IMAGER_RST
+#  error "IMAGER_RST must be defined in board.h !!"
+#endif
+
+#define POWER_CHECK_TIME            (1 * USEC_PER_MSEC)   /* ms */
+#define POWER_OFF_TIME              (50 * USEC_PER_MSEC)  /* ms */
+
+#define POWER_CHECK_RETRY           (10)
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int board_isx019_power_on(void)
+{
+  int ret;
+  int i;
+
+  ret = board_power_control(POWER_IMAGE_SENSOR, true);
+  if (ret)
+    {
+      _err("ERROR: Failed to power on ImageSensor. %d\n", ret);
+      return -ENODEV;
+    }
+
+  ret = -ETIMEDOUT;
+  for (i = 0; i < POWER_CHECK_RETRY; i++)
+    {
+      /* Need to wait for a while after power-on */
+
+      nxsig_usleep(POWER_CHECK_TIME);
+
+      if (board_power_monitor(POWER_IMAGE_SENSOR))
+        {
+          ret = OK;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+int board_isx019_power_off(void)
+{
+  int ret;
+  int i;
+
+  ret = board_power_control(POWER_IMAGE_SENSOR, false);
+  if (ret)
+    {
+      _err("ERROR: Failed to power off ImageSensor. %d\n", ret);
+      return -ENODEV;
+    }
+
+  /* Need to wait for power-off to be reflected */
+
+  nxsig_usleep(POWER_OFF_TIME);
+
+  ret = -ETIMEDOUT;
+  for (i = 0; i < POWER_CHECK_RETRY; i++)
+    {
+      if (!board_power_monitor(POWER_IMAGE_SENSOR))
+        {
+          ret = OK;
+          break;
+        }
+
+      nxsig_usleep(POWER_CHECK_TIME);
+    }
+
+  return ret;
+}
+
+void board_isx019_set_reset(void)
+{
+  cxd56_gpio_write(IMAGER_RST, false);
+}
+
+void board_isx019_release_reset(void)
+{
+  cxd56_gpio_write(IMAGER_RST, true);
+}
+
+struct i2c_master_s *board_isx019_initialize(void)
+{
+  int retry = 50;
+
+  _info("Initializing ISX019...\n");
+
+  while (!g_rtc_enabled && 0 < retry--)
+    {
+      /* ISX019 requires stable RTC */
+
+      nxsig_usleep(100 * USEC_PER_MSEC);
+    }
+
+  cxd56_gpio_config(IMAGER_RST, false);
+  board_isx019_set_reset();
+
+  /* To avoid IS_DATA0 and IS_DATA7 being Hi-Z state during FPGA config,
+   * output these pins to LOW.
+   */
+
+  cxd56_gpio_config(PIN_IS_DATA0, false);
+  cxd56_gpio_config(PIN_IS_DATA7, false);
+  cxd56_gpio_write(PIN_IS_DATA0, false);
+  cxd56_gpio_write(PIN_IS_DATA7, false);
+
+  /* Initialize i2c device */
+
+  return cxd56_i2cbus_initialize(IMAGER_I2C);
+}
+
+int board_isx019_uninitialize(struct i2c_master_s *i2c)
+{
+  int ret;
+
+  _info("Uninitializing ISX019...\n");
+
+  /* Restore IS_DATA0 and IS_DATA7 to Hi-Z state */
+
+  cxd56_gpio_config(PIN_IS_DATA0, false);
+  cxd56_gpio_config(PIN_IS_DATA7, false);
+  cxd56_gpio_write_hiz(PIN_IS_DATA0);
+  cxd56_gpio_write_hiz(PIN_IS_DATA7);
+
+  /* Uninitialize i2c device */
+
+  ret = isx019_uninitialize();
+  if (ret < 0)
+    {
+      _err("Failed to uninitialize ISX019.\n");
+    }
+
+  if (i2c == NULL)
+    {
+      _err("Error uninitialize ISX019.\n");
+      return -ENODEV;
+    }
+  else
+    {
+      ret = cxd56_i2cbus_uninitialize(i2c);
+      if (ret < 0)
+        {
+          _err("Error uninitialize I2C BUS.\n");
+          return -EPERM;
+        }
+    }
+
+  return ret;
+}
+
+uint32_t board_isx019_get_master_clock(void)
+{
+  return cxd56_get_xosc_clock();
+}
diff --git a/boards/arm/cxd56xx/spresense/include/board.h b/boards/arm/cxd56xx/spresense/include/board.h
index fa720ca65c..ad695ea8a0 100644
--- a/boards/arm/cxd56xx/spresense/include/board.h
+++ b/boards/arm/cxd56xx/spresense/include/board.h
@@ -64,7 +64,12 @@
 #include "cxd56_scd41.h"
 #include "cxd56_sensors.h"
 
-#include "cxd56_isx012.h"
+#ifdef CONFIG_VIDEO_ISX012
+#  include "cxd56_isx012.h"
+#endif /* CONFIG_VIDEO_ISX012 */
+#ifdef CONFIG_VIDEO_ISX019
+#  include "cxd56_isx019.h"
+#endif /* CONFIG_VIDEO_ISX019 */
 
 /****************************************************************************
  * Pre-processor Definitions
diff --git a/boards/arm/cxd56xx/spresense/include/cxd56_isx019.h b/boards/arm/cxd56xx/spresense/include/cxd56_isx019.h
new file mode 100644
index 0000000000..f99bde8384
--- /dev/null
+++ b/boards/arm/cxd56xx/spresense/include/cxd56_isx019.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * boards/arm/cxd56xx/spresense/include/cxd56_isx019.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 __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_ISX019_H
+#define __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_ISX019_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/video/isx019.h>
+#include <nuttx/video/video.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_isx019_power_on
+ *
+ * Description:
+ *   Power on ISX019
+ *
+ ****************************************************************************/
+
+int board_isx019_power_on(void);
+
+/****************************************************************************
+ * Name: board_isx019_power_off
+ *
+ * Description:
+ *   Power off ISX019
+ *
+ ****************************************************************************/
+
+int board_isx019_power_off(void);
+
+/****************************************************************************
+ * Name: board_isx019_set_reset
+ *
+ * Description:
+ *   Set reset ISX019
+ *
+ ****************************************************************************/
+
+void board_isx019_set_reset(void);
+
+/****************************************************************************
+ * Name: board_isx019_release_reset
+ *
+ * Description:
+ *   Release reset ISX019
+ *
+ ****************************************************************************/
+
+void board_isx019_release_reset(void);
+
+/****************************************************************************
+ * Name: board_isx019_initialize
+ *
+ * Description:
+ *   Initialize ISX019 i2c driver and register the ISX019 device.
+ *
+ ****************************************************************************/
+
+struct i2c_master_s *board_isx019_initialize(void);
+
+/****************************************************************************
+ * Name: board_isx019_uninitialize
+ *
+ * Description:
+ *   Uninitialize ISX019 i2c driver and register the ISX019 device.
+ *
+ ****************************************************************************/
+
+int board_isx019_uninitialize(struct i2c_master_s *i2c);
+
+/****************************************************************************
+ * Name: board_isx019_get_master_clock
+ *
+ * Description:
+ *   Get ISX019 master clock.
+ *
+ ****************************************************************************/
+
+uint32_t board_isx019_get_master_clock(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_ISX019_H */
diff --git a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c
index e38a400adb..a736fa3c74 100644
--- a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c
+++ b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c
@@ -372,13 +372,21 @@ int cxd56_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_VIDEO_ISX019
+  ret = isx019_initialize();
+  if (ret < 0)
+    {
+      _err("ERROR: Failed to initialize ISX019 board. %d\n", errno);
+    }
+#endif
+
 #ifdef CONFIG_VIDEO_ISX012
   ret = isx012_initialize();
   if (ret < 0)
     {
       _err("ERROR: Failed to initialize ISX012 board. %d\n", errno);
     }
-#endif /* CONFIG_VIDEO_ISX012 */
+#endif
 
 #ifdef CONFIG_CXD56_CISIF
   ret = cxd56_cisif_initialize();
@@ -387,7 +395,7 @@ int cxd56_bringup(void)
       _err("ERROR: Failed to initialize CISIF. %d\n", errno);
       ret = ERROR;
     }
-#endif /* CONFIG_CXD56_CISIF */
+#endif
 
 #if defined(CONFIG_CXD56_SDIO)
   /* In order to prevent Hi-Z from being input to the SD Card controller,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8b57c429c2..1508938ed5 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -150,6 +150,41 @@ config VIDEO_ISX012
 	default n
 	select I2C
 
+config VIDEO_ISX019
+	bool "ISX019 Image sensor"
+	default n
+	select I2C
+
+if VIDEO_ISX019
+choice
+	prompt "HDR mode selection"
+	default VIDEO_ISX019_DOL3
+	---help---
+		ISX019 has the DOL-HDR feature, which combines images with different exposure so that
+		both bright and dark data of high-contrast subject can be viewed at the same time.
+		Select DOLX(X = 2 or 3), in which X represents the number of combined images.
+
+config VIDEO_ISX019_DOL3
+	bool "DOL3"
+	---help---
+		DOL3 is the mode that combines 3 images with different exposure.
+
+config VIDEO_ISX019_DOL2
+	bool "DOL2"
+	---help---
+		DOL2 is the mode that combines 2 images with different exposure.
+
+endchoice
+
+config VIDEO_ISX019_INITIAL_JPEG_QUALITY
+	int "Initial JPEG quality"
+	default 70
+	range 1 100
+	---help---
+		The initial JPEG quality.
+
+endif
+
 config VIDEO_OV2640
 	bool "OV2640 camera chip"
 	default n
diff --git a/drivers/video/Make.defs b/drivers/video/Make.defs
index 0828a4ae98..de29436788 100644
--- a/drivers/video/Make.defs
+++ b/drivers/video/Make.defs
@@ -38,6 +38,10 @@ ifeq ($(CONFIG_VIDEO_ISX012),y)
   CSRCS += isx012.c
 endif
 
+ifeq ($(CONFIG_VIDEO_ISX019),y)
+  CSRCS += isx019.c
+endif
+
 ifeq ($(CONFIG_VIDEO_OV2640),y)
   CSRCS += ov2640.c
 endif
diff --git a/drivers/video/isx019.c b/drivers/video/isx019.c
new file mode 100644
index 0000000000..9bc8c68aed
--- /dev/null
+++ b/drivers/video/isx019.c
@@ -0,0 +1,3249 @@
+/****************************************************************************
+ * drivers/video/isx019.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 <nuttx/config.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/signal.h>
+#include <arch/board/board.h>
+#include <nuttx/video/isx019.h>
+#include <nuttx/video/imgsensor.h>
+#include <math.h>
+#include <nuttx/semaphore.h>
+
+#include "isx019_reg.h"
+#include "isx019_range.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Wait time on power on sequence. */
+
+#define TRANSITION_TIME_TO_STARTUP   (120 * USEC_PER_MSEC) /* unit : usec */
+#define TRANSITION_TIME_TO_STREAMING (30 * USEC_PER_MSEC)  /* unit : usec */
+
+/* For get_supported_value() I/F */
+
+#define SET_RANGE(range, min, max, s, def) \
+        do                                 \
+          {                                \
+            (range).minimum       = (min); \
+            (range).maximum       = (max); \
+            (range).step          = (s);   \
+            (range).default_value = (def); \
+          }                                \
+        while (0);
+
+#define SET_DISCRETE(disc, nr, val, def)   \
+        do                                 \
+          {                                \
+            (disc).nr_values     = (nr);   \
+            (disc).values        = (val);  \
+            (disc).default_value = (def);  \
+          }                                \
+        while (0);
+
+#define SET_ELEMS(elem, nr, min, max, s)   \
+        do                                 \
+          {                                \
+            (elem).nr_elems      = (nr);   \
+            (elem).minimum       = (min);  \
+            (elem).maximum       = (max);  \
+            (elem).step          = (s);    \
+          }                                \
+        while (0);
+
+#define COMPARE_FRAMESIZE(w, h, sup_w, sup_h)  (((w) == (sup_w)) && \
+                                                ((h) == (sup_h)))
+
+#define VALIDATE_FRAMESIZE(w, h) (COMPARE_FRAMESIZE((w), (h), 1280, 960) || \
+                                  COMPARE_FRAMESIZE((w), (h), 1280, 720) || \
+                                  COMPARE_FRAMESIZE((w), (h),  640, 480) || \
+                                  COMPARE_FRAMESIZE((w), (h),  640, 360) || \
+                                  COMPARE_FRAMESIZE((w), (h),  480, 360) || \
+                                  COMPARE_FRAMESIZE((w), (h),  320, 240) || \
+                                  COMPARE_FRAMESIZE((w), (h),  160, 120))
+
+#define VALIDATE_THUMNAIL_SIZE(m, s) (((s) != 0) && \
+                                      ((m) % (s) == 0) && \
+                                      ((m) / (s) < 5)  && \
+                                      ((m) / (s) > 0))
+
+/* For set_value() and get_value() I/F */
+
+#define SET_REGINFO(a, c, o, s) do \
+                                  {                      \
+                                    (a)->category = (c); \
+                                    (a)->offset   = (o); \
+                                    (a)->size     = (s); \
+                                  }                      \
+                                while (0);
+
+#define VALIDATE_RANGE(v, min, max, step) (((v) >= (min)) && \
+                                           ((v) <= (max)) && \
+                                           (((v) - (min)) % (step) == 0))
+
+/* Offset for IMGSENSOR_ID_3A_PARAMETER control */
+
+#define OFFSET_3APARAMETER_AWB_R      (0)
+#define OFFSET_3APARAMETER_AWB_B      (2)
+#define OFFSET_3APARAMETER_AE_SHTTIME (4)
+#define OFFSET_3APARAMETER_AE_GAIN    (8)
+
+/* Index of array for drive mode setting */
+
+#define INDEX_SENS     (0)
+#define INDEX_POST     (1)
+#define INDEX_SENSPOST (2)
+#define INDEX_IO       (3)
+
+/* Timer value for power on control */
+
+#define ISX019_ACCESSIBLE_WAIT_SEC    (0)
+#define ISX019_ACCESSIBLE_WAIT_USEC   (200000)
+#define FPGA_ACCESSIBLE_WAIT_SEC      (1)
+#define FPGA_ACCESSIBLE_WAIT_USEC     (0)
+
+/* Array size of DQT setting for JPEG quality */
+
+#define JPEG_DQT_ARRAY_SIZE (64)
+
+/* ISX019 standard master clock */
+
+#define ISX019_STANDARD_MASTER_CLOCK (27000000)
+
+/* Vivid colors setting */
+
+#define VIVID_COLORS_SATURATION (0xf0)
+#define VIVID_COLORS_SHARPNESS  (0x20)
+
+/* Black white colors setting */
+
+#define BW_COLORS_SATURATION (0x00)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct isx019_default_value_s
+{
+  int32_t brightness;
+  int32_t contrast;
+  int32_t saturation;
+  int32_t hue;
+  int32_t awb;
+  int32_t gamma;
+  int32_t ev;
+  int32_t hflip_video;
+  int32_t vflip_video;
+  int32_t hflip_still;
+  int32_t vflip_still;
+  int32_t sharpness;
+  int32_t ae;
+  int32_t exptime;
+  int32_t wbmode;
+  int32_t hdr;
+  int32_t iso;
+  int32_t iso_auto;
+  int32_t meter;
+  int32_t threealock;
+  int32_t threeastatus;
+  int32_t jpgquality;
+};
+
+typedef struct isx019_default_value_s isx019_default_value_t;
+
+struct isx019_rect_s
+{
+  int32_t left;
+  int32_t top;
+  uint32_t width;
+  uint32_t height;
+};
+
+typedef struct isx019_rect_s isx019_rect_t;
+
+struct isx019_dev_s
+{
+  sem_t fpga_lock;
+  sem_t i2c_lock;
+  FAR struct i2c_master_s *i2c;
+  float clock_ratio;
+  isx019_default_value_t  default_value;
+  imgsensor_stream_type_t stream;
+  imgsensor_white_balance_t wb_mode;
+  uint8_t flip_video;
+  uint8_t flip_still;
+  isx019_rect_t clip_video;
+  isx019_rect_t clip_still;
+  int32_t iso;
+  double  gamma;
+  int32_t jpg_quality;
+  imgsensor_colorfx_t colorfx;
+};
+
+typedef struct isx019_dev_s isx019_dev_t;
+
+typedef CODE int32_t (*convert_t)(int32_t value32);
+
+typedef CODE int (*setvalue_t)(imgsensor_value_t value);
+typedef CODE int (*getvalue_t)(FAR imgsensor_value_t *value);
+
+struct isx019_reginfo_s
+{
+  uint16_t category;
+  uint16_t offset;
+  uint8_t  size;
+};
+
+typedef struct isx019_reginfo_s isx019_reginfo_t;
+
+struct isx019_fpga_jpg_quality_s
+{
+  /* JPEG quality */
+
+  int quality;
+
+  /* DQT header setting for y component */
+
+  uint8_t y_head[JPEG_DQT_ARRAY_SIZE];
+
+  /* DQT calculation data for y component */
+
+  uint8_t y_calc[JPEG_DQT_ARRAY_SIZE];
+
+  /* DQT header setting for c component */
+
+  uint8_t c_head[JPEG_DQT_ARRAY_SIZE];
+
+  /* DQT calculation data for c component */
+
+  uint8_t c_calc[JPEG_DQT_ARRAY_SIZE];
+};
+
+typedef struct isx019_fpga_jpg_quality_s isx019_fpga_jpg_quality_t;
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static bool isx019_is_available(void);
+static int isx019_init(void);
+static int isx019_uninit(void);
+static FAR const char *isx019_get_driver_name(void);
+static int isx019_validate_frame_setting(imgsensor_stream_type_t type,
+                                         uint8_t nr_datafmt,
+                                         FAR imgsensor_format_t *datafmts,
+                                         FAR imgsensor_interval_t *interval);
+static int isx019_start_capture(imgsensor_stream_type_t type,
+                                uint8_t nr_datafmt,
+                                FAR imgsensor_format_t *datafmts,
+                                FAR imgsensor_interval_t *interval);
+static int isx019_stop_capture(imgsensor_stream_type_t type);
+static int isx019_get_supported_value(uint32_t id,
+                                     FAR imgsensor_supported_value_t *value);
+static int isx019_get_value(uint32_t id, uint32_t size,
+                            FAR imgsensor_value_t *value);
+static int isx019_set_value(uint32_t id, uint32_t size,
+                            imgsensor_value_t value);
+static int initialize_jpg_quality(void);
+static int send_read_cmd(FAR struct i2c_config_s *config,
+                         uint8_t cat,
+                         uint16_t addr,
+                         uint8_t size);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static isx019_dev_t g_isx019_private;
+
+static struct imgsensor_ops_s g_isx019_ops =
+{
+  isx019_is_available,
+  isx019_init,
+  isx019_uninit,
+  isx019_get_driver_name,
+  isx019_validate_frame_setting,
+  isx019_start_capture,
+  isx019_stop_capture,
+  isx019_get_supported_value,
+  isx019_get_value,
+  isx019_set_value,
+};
+
+static isx019_fpga_jpg_quality_t g_isx019_jpg_quality[] =
+{
+  {
+    10,
+      {
+         21,  15,  15,  26,  18,  26,  43,  21,
+         21,  43,  43,  43,  32,  43,  43,  43,
+         43,  43,  43,  43,  43,  64,  43,  43,
+         43,  43,  43,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+          3,   4, 133, 131, 131, 131,   1,   1,
+          4, 135,   3, 131, 131, 131,   1,   1,
+        133,   3,   2, 131, 131,   1,   1,   1,
+        131, 131, 131, 131,   1,   1,   1,   1,
+        131, 131, 131,   1,   1,   1,   1,   1,
+        131, 131,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+      },
+      {
+         21,  26,  26,  32,  26,  32,  43,  26,
+         26,  43,  64,  43,  32,  43,  64,  64,
+         64,  43,  43,  64,  64,  64,  64,  64,
+         43,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+          3, 133,   2, 131,   1,   1,   1,   1,
+        133, 133, 133, 131,   1,   1,   1,   1,
+          2, 133,   2, 131,   1,   1,   1,   1,
+        131, 131, 131, 131,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+      }
+  },
+  {
+    20,
+      {
+         18,  14,  14,  14,  15,  14,  21,  15,
+         15,  21,  32,  21,  18,  21,  32,  32,
+         26,  21,  21,  26,  32,  32,  26,  26,
+         26,  26,  26,  32,  43,  32,  32,  32,
+         32,  32,  32,  43,  43,  43,  43,  43,
+         43,  43,  43,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+        135, 137, 137,   3,   2,   2,   2, 131,
+        137,   4,   4,   3, 133, 133,   2, 131,
+        137,   4, 135,   3, 133,   2, 131,   1,
+          3,   3,   3, 133,   2, 131,   1,   1,
+          2, 133, 133,   2, 131,   1,   1,   1,
+          2, 133,   2, 131,   1,   1,   1,   1,
+          2,   2, 131,   1,   1,   1,   1,   1,
+        131, 131,   1,   1,   1,   1,   1,   1,
+      },
+      {
+         21,  21,  21,  21,  26,  21,  26,  21,
+         21,  26,  26,  21,  26,  21,  26,  32,
+         26,  26,  26,  26,  32,  43,  32,  32,
+         32,  32,  32,  43,  64,  43,  43,  43,
+         43,  43,  43,  64,  64,  64,  43,  43,
+         43,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+          3,   3,   3, 133, 133,   2, 131,   1,
+          3, 133,   3,   3, 133,   2, 131,   1,
+          3,   3, 133, 133,   2, 131,   1,   1,
+        133,   3, 133,   2, 131, 131,   1,   1,
+        133, 133,   2, 131, 131,   1,   1,   1,
+          2,   2, 131, 131,   1,   1,   1,   1,
+        131, 131,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+      }
+  },
+  {
+    30,
+      {
+         15,  11,  11,  11,  12,  11,  15,  12,
+         12,  15,  21,  15,  13,  15,  21,  26,
+         21,  15,  15,  21,  26,  32,  21,  21,
+         21,  21,  21,  32,  32,  21,  26,  26,
+         26,  26,  21,  32,  32,  32,  32,  43,
+         32,  32,  32,  43,  43,  43,  43,  43,
+         43,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+          4,  12,  12,   4,   3, 133,   2,   2,
+         12, 139, 139,   4,   3,   3,   3,   2,
+         12, 139,   5,   4,   3, 133,   2, 131,
+          4,   4,   4,   3, 133,   2, 131,   1,
+          3,   3,   3, 133, 131, 131,   1,   1,
+        133,   3, 133,   2, 131,   1,   1,   1,
+          2,   3,   2, 131,   1,   1,   1,   1,
+          2,   2, 131,   1,   1,   1,   1,   1,
+      },
+      {
+         18,  15,  15,  18,  18,  18,  21,  18,
+         18,  21,  21,  18,  21,  18,  21,  26,
+         21,  21,  21,  21,  26,  43,  26,  26,
+         26,  26,  26,  43,  43,  32,  32,  32,
+         32,  32,  32,  43,  43,  43,  43,  43,
+         43,  43,  43,  43,  43,  43,  43,  43,
+         43,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+        135,   4, 135,   3,   3, 133, 131, 131,
+          4, 135, 135, 135,   3, 133,   2, 131,
+        135, 135,   3,   3, 133,   2, 131, 131,
+          3, 135,   3, 133,   2, 131, 131,   1,
+          3,   3, 133,   2, 131, 131,   1,   1,
+        133, 133,   2, 131, 131,   1,   1,   1,
+        131,   2, 131, 131,   1,   1,   1,   1,
+        131, 131, 131,   1,   1,   1,   1,   1,
+      }
+  },
+  {
+    40,
+      {
+         12,   8,   8,   8,   9,   8,  12,   9,
+          9,  12,  18,  11,  10,  11,  18,  21,
+         15,  12,  12,  15,  21,  26,  18,  18,
+         21,  18,  18,  26,  21,  18,  21,  21,
+         21,  21,  18,  21,  21,  26,  26,  32,
+         26,  26,  21,  32,  32,  43,  43,  32,
+         32,  43,  43,  43,  43,  43,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+        139,   8,   8, 139, 135,   3, 133,   3,
+          8,   7,   7,  12,   4, 135, 135,   3,
+          8,   7, 141, 139, 135,   3, 133,   2,
+        139,  12, 139,   3,   3, 133,   2, 131,
+        135,   4, 135,   3,   2, 131, 131,   1,
+          3, 135,   3, 133, 131, 131,   1,   1,
+        133, 135, 133,   2, 131,   1,   1,   1,
+          3,   3,   2, 131,   1,   1,   1,   1,
+      },
+      {
+         13,  11,  11,  13,  14,  13,  15,  14,
+         14,  15,  21,  14,  15,  14,  21,  21,
+         15,  18,  18,  15,  21,  26,  21,  21,
+         21,  21,  21,  26,  32,  26,  21,  21,
+         21,  21,  26,  32,  32,  32,  32,  32,
+         32,  32,  32,  43,  43,  32,  32,  43,
+         43,  43,  43,  43,  43,  43,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+      },
+      {
+          5,  12,   5,   4,   3,   3, 133,   2,
+         12, 137, 137, 137,   4,   3, 133,   2,
+          5, 137,   4, 135,   3,   3,   2, 131,
+          4, 137, 135,   3,   3,   2, 131, 131,
+          3,   4,   3,   3,   2,   2, 131,   1,
+          3,   3,   3,   2,   2, 131,   1,   1,
+        133, 133,   2, 131, 131,   1,   1,   1,
+          2,   2, 131, 131,   1,   1,   1,   1,
+      }
+  },
+  {
+    50,
+      {
+          8,   6,   6,   6,   6,   6,   8,   6,
+          6,   8,  12,   8,   7,   8,  12,  14,
+         10,   8,   8,  10,  14,  15,  13,  13,
+         14,  13,  13,  15,  18,  12,  14,  13,
+         13,  14,  12,  18,  15,  18,  18,  21,
+         18,  18,  15,  26,  26,  26,  26,  26,
+         26,  32,  32,  32,  32,  32,  43,  43,
+         43,  43,  43,  43,  43,  43,  43,  43,
+      },
+      {
+          8,  11,  11,   8, 139, 137,   4, 135,
+         11,  11,  11,   8, 141,   5, 139,   4,
+         11,  11,   9,   8,   5, 137, 135, 133,
+          8,   8,   8, 137,   5, 135, 133,   2,
+        139, 141,   5,   5,   3, 133,   2, 131,
+        137,   5, 137, 135, 133,   2, 131, 131,
+          4, 139, 135, 133,   2, 131, 131, 131,
+        135,   4, 133,   2, 131, 131, 131, 131,
+      },
+      {
+          9,   8,   8,   9,  10,   9,  11,   9,
+          9,  11,  14,  11,  13,  11,  14,  18,
+         14,  14,  14,  14,  18,  18,  13,  13,
+         14,  13,  13,  18,  26,  18,  15,  15,
+         15,  15,  18,  26,  21,  21,  21,  21,
+         21,  21,  21,  26,  26,  26,  26,  26,
+         26,  32,  32,  32,  32,  32,  43,  43,
+         43,  43,  43,  43,  43,  43,  43,  43,
+      },
+      {
+          7,   8,   7,  12, 137, 135, 135, 133,
+          8, 141,   7,  12, 137,   5, 135,   3,
+          7,   7,   5, 137,   5,   4,   3, 133,
+         12,  12, 137, 137,   4,   3, 133,   2,
+        137, 137,   5,   4,   3, 133,   2, 131,
+        135,   5,   4,   3, 133,   2, 131, 131,
+        135, 135,   3, 133,   2, 131, 131, 131,
+        133,   3, 133,   2, 131, 131, 131, 131,
+      }
+  },
+  {
+    60,
+      {
+          6,   4,   4,   4,   5,   4,   6,   5,
+          5,   6,   9,   6,   5,   6,   9,  11,
+          8,   6,   6,   8,  11,  12,  10,  10,
+         11,  10,  10,  12,  15,  12,  12,  12,
+         12,  12,  12,  15,  12,  14,  15,  15,
+         15,  14,  12,  18,  18,  21,  21,  18,
+         18,  26,  26,  26,  26,  26,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+      },
+      {
+         11,  16,  16,  11,   7,  12, 139,   4,
+         16,  13,  13,  11,   8, 141, 139, 139,
+         16,  13,  13,  11, 141, 139, 137, 135,
+         11,  11,  11,  12, 139,   4, 135, 133,
+          7,   8, 141, 139,   4,   3, 133,   2,
+         12, 141, 139,   4,   3, 133,   2,   2,
+        139, 139, 137, 135, 133,   2,   2,   2,
+          4, 139, 135, 133,   2,   2,   2,   2,
+      },
+      {
+          7,   7,   7,  13,  12,  13,  26,  15,
+         15,  26,  26,  21,  18,  21,  26,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+         32,  32,  32,  32,  32,  32,  32,  32,
+      },
+      {
+          9,   9,   5, 133, 133,   2,   2,   2,
+          9, 139,   4,   3,   2,   2,   2,   2,
+          5,   4, 135,   2,   2,   2,   2,   2,
+        133,   3,   2,   2,   2,   2,   2,   2,
+        133,   2,   2,   2,   2,   2,   2,   2,
+          2,   2,   2,   2,   2,   2,   2,   2,
+          2,   2,   2,   2,   2,   2,   2,   2,
+          2,   2,   2,   2,   2,   2,   2,   2,
+      }
+  },
+  {
+    70,
+      {
+          4,   3,   3,   3,   3,   3,   4,   3,
+          3,   4,   6,   4,   3,   4,   6,   7,
+          5,   4,   4,   5,   7,   8,   6,   6,
+          7,   6,   6,   8,  10,   8,   9,   9,
+          9,   9,   8,  10,  10,  12,  12,  12,
+         12,  12,  10,  12,  12,  13,  13,  12,
+         12,  18,  18,  18,  18,  18,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+      },
+      {
+         16,  21,  21,  16,  11,   9,   8, 141,
+         21,  21,  21,  16,  13,  11,   8, 141,
+         21,  21,  21,  16,  11,   7, 139, 139,
+         16,  16,  16,   9,   7, 139, 139, 135,
+         11,  13,  11,   7, 139,   5, 135,   3,
+          9,  11,   7, 139,   5, 135,   3,   3,
+          8,   8, 139, 139, 135,   3,   3,   3,
+        141, 141, 139, 135,   3,   3,   3,   3,
+      },
+      {
+          4,   5,   5,   8,   7,   8,  15,  10,
+         10,  15,  21,  14,  14,  14,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+      },
+      {
+         16,  13,   8,   4,   3,   3,   3,   3,
+         13,   9, 141, 137,   3,   3,   3,   3,
+          8, 141, 137,   3,   3,   3,   3,   3,
+          4, 137,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+      }
+  },
+  {
+    80,
+      {
+          2,   2,   2,   2,   2,   2,   2,   2,
+          2,   2,   3,   2,   2,   2,   3,   4,
+          3,   2,   2,   3,   4,   5,   4,   4,
+          4,   4,   4,   5,   6,   5,   5,   5,
+          5,   5,   5,   6,   6,   7,   7,   8,
+          7,   7,   6,   9,   9,  10,  10,   9,
+          9,  12,  12,  12,  12,  12,  12,  12,
+         12,  12,  12,  12,  12,  12,  12,  12,
+      },
+      {
+         32,  32,  32,  32,  21,  16,  13,  11,
+         32,  32,  32,  32,  21,  16,  13,  11,
+         32,  32,  32,  32,  16,  13,   9,   7,
+         32,  32,  32,  16,  13,   9,   7, 139,
+         21,  21,  16,  13,   8, 141, 139, 139,
+         16,  16,  13,   9, 141, 139, 139, 139,
+         13,  13,   9,   7, 139, 139, 139, 139,
+         11,  11,   7, 139, 139, 139, 139, 139,
+      },
+      {
+          3,   3,   3,   5,   4,   5,   9,   6,
+          6,   9,  13,  11,   9,  11,  13,  15,
+         14,  14,  14,  14,  15,  15,  12,  12,
+         12,  12,  12,  15,  15,  12,  12,  12,
+         12,  12,  12,  15,  12,  12,  12,  12,
+         12,  12,  12,  12,  12,  12,  12,  12,
+         12,  12,  12,  12,  12,  12,  12,  12,
+         12,  12,  12,  12,  12,  12,  12,  12,
+      },
+      {
+         21,  21,  13,   7,   5,   4,   4,   4,
+         21,  16,  11,  12, 137, 139, 139, 139,
+         13,  11,   7, 137, 139, 139, 139, 139,
+          7,  12, 137, 139, 139, 139, 139, 139,
+          5, 137, 139, 139, 139, 139, 139, 139,
+          4, 139, 139, 139, 139, 139, 139, 139,
+          4, 139, 139, 139, 139, 139, 139, 139,
+          4, 139, 139, 139, 139, 139, 139, 139,
+      }
+  },
+  {
+    90,
+      {
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   2,   1,   1,   1,   2,   2,
+          2,   1,   1,   2,   2,   2,   2,   2,
+          2,   2,   2,   2,   3,   2,   3,   3,
+          3,   3,   2,   3,   3,   4,   4,   4,
+          4,   4,   3,   5,   5,   5,   5,   5,
+          5,   7,   7,   7,   7,   7,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+      },
+      {
+         64,  64,  64,  64,  32,  32,  32,  21,
+         64,  64,  64,  64,  32,  32,  32,  21,
+         64,  64,  64,  64,  32,  21,  16,  13,
+         64,  64,  64,  32,  21,  16,  13,   9,
+         32,  32,  32,  21,  16,  13,   9,   8,
+         32,  32,  21,  16,  13,   9,   8,   8,
+         32,  32,  16,  13,   9,   8,   8,   8,
+         21,  21,  13,   9,   8,   8,   8,   8,
+      },
+      {
+          1,   1,   1,   2,   2,   2,   5,   3,
+          3,   5,   7,   5,   4,   5,   7,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+      },
+      {
+         64,  64,  32,  13,   9,   8,   8,   8,
+         64,  32,  21,  13,   8,   8,   8,   8,
+         32,  21,  16,   8,   8,   8,   8,   8,
+         13,  13,   8,   8,   8,   8,   8,   8,
+          9,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+          8,   8,   8,   8,   8,   8,   8,   8,
+      }
+  },
+  {
+    100,
+      {
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   1,   2,   2,   2,   2,   2,
+          2,   2,   2,   2,   2,   2,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+      },
+      {
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  64,
+         64,  64,  64,  64,  64,  64,  64,  32,
+         64,  64,  64,  64,  64,  64,  32,  32,
+         64,  64,  64,  64,  64,  32,  32,  21,
+         64,  64,  64,  64,  32,  32,  21,  21,
+         64,  64,  64,  32,  32,  21,  21,  21,
+         64,  64,  32,  32,  21,  21,  21,  21,
+      },
+      {
+          1,   1,   1,   1,   1,   1,   1,   1,
+          1,   1,   2,   2,   1,   2,   2,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+          3,   3,   3,   3,   3,   3,   3,   3,
+      },
+      {
+         64,  64,  64,  64,  32,  21,  21,  21,
+         64,  64,  64,  32,  21,  21,  21,  21,
+         64,  64,  64,  21,  21,  21,  21,  21,
+         64,  32,  21,  21,  21,  21,  21,  21,
+         32,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+         21,  21,  21,  21,  21,  21,  21,  21,
+      }
+  }
+};
+
+#define NR_JPGSETTING_TBL \
+        (sizeof(g_isx019_jpg_quality) / sizeof(isx019_fpga_jpg_quality_t))
+
+int32_t g_isx019_colorfx[] =
+{
+  IMGSENSOR_COLORFX_NONE,
+  IMGSENSOR_COLORFX_BW,
+  IMGSENSOR_COLORFX_VIVID,
+};
+
+#define NR_COLORFX (sizeof(g_isx019_colorfx) / sizeof(int32_t))
+
+int32_t g_isx019_wbmode[] =
+{
+  IMGSENSOR_WHITE_BALANCE_AUTO,
+  IMGSENSOR_WHITE_BALANCE_INCANDESCENT,
+  IMGSENSOR_WHITE_BALANCE_FLUORESCENT,
+  IMGSENSOR_WHITE_BALANCE_DAYLIGHT,
+  IMGSENSOR_WHITE_BALANCE_CLOUDY,
+  IMGSENSOR_WHITE_BALANCE_SHADE,
+};
+
+#define NR_WBMODE (sizeof(g_isx019_wbmode) / sizeof(int32_t))
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void i2c_lock(void)
+{
+  nxsem_wait_uninterruptible(&g_isx019_private.i2c_lock);
+}
+
+static void i2c_unlock(void)
+{
+  nxsem_post(&g_isx019_private.i2c_lock);
+}
+
+static void fpga_lock(void)
+{
+  nxsem_wait_uninterruptible(&g_isx019_private.fpga_lock);
+}
+
+static void fpga_unlock(void)
+{
+  nxsem_post(&g_isx019_private.fpga_lock);
+}
+
+int fpga_i2c_write(uint8_t addr, FAR uint8_t *data, uint8_t size)
+{
+  struct i2c_config_s config;
+  static uint8_t buf[FPGA_I2C_REGSIZE_MAX + FPGA_I2C_REGADDR_LEN];
+  int ret;
+
+  DEBUGASSERT(size <= FPGA_I2C_REGSIZE_MAX);
+
+  config.frequency = ISX019_I2C_FREQUENCY;
+  config.address   = ISX019_I2C_SLVADDR;
+  config.addrlen   = ISX019_I2C_SLVADDR_LEN;
+
+  i2c_lock();
+
+  /* ISX019 requires that send read command to ISX019 before FPGA access. */
+
+  send_read_cmd(&config, CAT_VERSION, ROM_VERSION, 1);
+
+  config.frequency = FPGA_I2C_FREQUENCY;
+  config.address   = FPGA_I2C_SLVADDR;
+  config.addrlen   = FPGA_I2C_SLVADDR_LEN;
+
+  buf[FPGA_I2C_OFFSET_ADDR] = addr;
+  memcpy(&buf[FPGA_I2C_OFFSET_WRITEDATA], data, size);
+  ret = i2c_write(g_isx019_private.i2c,
+                  &config,
+                  buf,
+                  size + FPGA_I2C_REGADDR_LEN);
+  i2c_unlock();
+
+  return ret;
+}
+
+static int fpga_i2c_read(uint8_t addr, FAR uint8_t *data, uint8_t size)
+{
+  int ret;
+  struct i2c_config_s config;
+
+  DEBUGASSERT(size <= FPGA_I2C_REGSIZE_MAX);
+
+  config.frequency = ISX019_I2C_FREQUENCY;
+  config.address   = ISX019_I2C_SLVADDR;
+  config.addrlen   = ISX019_I2C_SLVADDR_LEN;
+
+  i2c_lock();
+
+  /* ISX019 requires that send read command to ISX019 before FPGA access. */
+
+  send_read_cmd(&config, CAT_VERSION, ROM_VERSION, 1);
+
+  config.frequency = FPGA_I2C_FREQUENCY;
+  config.address   = FPGA_I2C_SLVADDR;
+  config.addrlen   = FPGA_I2C_SLVADDR_LEN;
+
+  ret = i2c_write(g_isx019_private.i2c,
+                  &config,
+                  &addr,
+                  FPGA_I2C_REGADDR_LEN);
+  if (ret >= 0)
+    {
+      ret = i2c_read(g_isx019_private.i2c, &config, data, size);
+    }
+
+  i2c_unlock();
+
+  return ret;
+}
+
+static void fpga_activate_setting(void)
+{
+  uint8_t regval = FPGA_ACTIVATE_REQUEST;
+  fpga_i2c_write(FPGA_ACTIVATE, &regval, 1);
+
+  while (1)
+    {
+      fpga_i2c_read(FPGA_ACTIVATE, &regval, 1);
+      if (regval == 0)
+        {
+          break;
+        }
+    }
+}
+
+static uint8_t calc_isx019_chksum(FAR uint8_t *data, uint8_t len)
+{
+  int i;
+  uint8_t chksum = 0;
+
+  for (i = 0; i < len; i++)
+    {
+      /* ISX019 checksum is lower 8bit of addition result.
+       * So, no problem even if overflow occur.
+       */
+
+      chksum += data[i];
+    }
+
+  return chksum;
+}
+
+static bool validate_isx019_chksum(FAR uint8_t *data, uint8_t len)
+{
+  uint8_t chksum;
+
+  chksum = calc_isx019_chksum(data, len - 1);
+
+  return (data[len - 1] == chksum);
+}
+
+static int recv_write_response(FAR struct i2c_config_s *config)
+{
+  int ret;
+  uint8_t buf[ISX019_I2C_WRRES_TOTALLEN];
+
+  ret = i2c_read(g_isx019_private.i2c, config, buf, sizeof(buf));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if ((buf[ISX019_I2C_OFFSET_TOTALLEN] != ISX019_I2C_WRRES_TOTALLEN) ||
+      (buf[ISX019_I2C_OFFSET_CMDNUM]   != 1) ||
+      (buf[ISX019_I2C_OFFSET_CMDLEN]   != ISX019_I2C_WRRES_LEN) ||
+      (buf[ISX019_I2C_OFFSET_STS]      != ISX019_I2C_STS_OK) ||
+      !validate_isx019_chksum(buf, ISX019_I2C_WRRES_TOTALLEN))
+    {
+      return -EPROTO;
+    }
+
+  return OK;
+}
+
+static int recv_read_response(FAR struct i2c_config_s *config,
+                              FAR uint8_t *data,
+                              uint8_t size)
+{
+  int ret;
+  uint8_t buf[ISX019_I2C_WRREQ_TOTALLEN(ISX019_I2C_REGSIZE_MAX)] =
+    {
+      0
+    };
+
+  DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX);
+
+  ret = i2c_read(g_isx019_private.i2c,
+                 config, buf, ISX019_I2C_RDRES_TOTALLEN(size));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if ((buf[ISX019_I2C_OFFSET_TOTALLEN] != ISX019_I2C_RDRES_TOTALLEN(size)) ||
+      (buf[ISX019_I2C_OFFSET_CMDNUM]   != 1) ||
+      (buf[ISX019_I2C_OFFSET_CMDLEN]   != ISX019_I2C_RDRES_LEN(size)) ||
+      (buf[ISX019_I2C_OFFSET_STS]      != ISX019_I2C_STS_OK) ||
+      !validate_isx019_chksum(buf, ISX019_I2C_RDRES_TOTALLEN(size)))
+    {
+      return -EPROTO;
+    }
+
+  memcpy(data, &buf[ISX019_I2C_OFFSET_READDATA], size);
+
+  return OK;
+}
+
+static int send_write_cmd(FAR struct i2c_config_s *config,
+                          uint8_t cat,
+                          uint16_t addr,
+                          FAR uint8_t *data,
+                          uint8_t size)
+{
+  int len;
+  uint8_t buf[ISX019_I2C_WRREQ_TOTALLEN(ISX019_I2C_REGSIZE_MAX)] =
+    {
+      0
+    };
+
+  DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX);
+
+  buf[ISX019_I2C_OFFSET_TOTALLEN]  = ISX019_I2C_WRREQ_TOTALLEN(size);
+  buf[ISX019_I2C_OFFSET_CMDNUM]    = 1;
+  buf[ISX019_I2C_OFFSET_CMDLEN]    = ISX019_I2C_WRREQ_LEN(size);
+  buf[ISX019_I2C_OFFSET_CMD]       = ISX019_I2C_CMD_WRITE;
+  buf[ISX019_I2C_OFFSET_CATEGORY]  = cat;
+  buf[ISX019_I2C_OFFSET_ADDRESS_H] = addr >> 8;
+  buf[ISX019_I2C_OFFSET_ADDRESS_L] = addr & 0xff;
+
+  memcpy(&buf[ISX019_I2C_OFFSET_WRITEDATA], data, size);
+
+  len = ISX019_I2C_OFFSET_WRITEDATA + size;
+  buf[len] = calc_isx019_chksum(buf, len);
+  len++;
+
+  return i2c_write(g_isx019_private.i2c, config, buf, len);
+}
+
+static int isx019_i2c_write(uint8_t cat,
+                            uint16_t addr,
+                            FAR uint8_t *data,
+                            uint8_t size)
+{
+  int ret;
+  struct i2c_config_s config;
+
+  DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX);
+
+  config.frequency = ISX019_I2C_FREQUENCY;
+  config.address   = ISX019_I2C_SLVADDR;
+  config.addrlen   = ISX019_I2C_SLVADDR_LEN;
+
+  i2c_lock();
+
+  ret = send_write_cmd(&config, cat, addr, data, size);
+  if (ret == OK)
+    {
+      ret = recv_write_response(&config);
+    }
+
+  i2c_unlock();
+  return ret;
+}
+
+static int send_read_cmd(FAR struct i2c_config_s *config,
+                         uint8_t cat,
+                         uint16_t addr,
+                         uint8_t size)
+{
+  int ret;
+  int len;
+  uint8_t buf[ISX019_I2C_RDREQ_TOTALLEN] =
+    {
+      0
+    };
+
+  buf[ISX019_I2C_OFFSET_TOTALLEN]  = ISX019_I2C_RDREQ_TOTALLEN;
+  buf[ISX019_I2C_OFFSET_CMDNUM]    = 1;
+  buf[ISX019_I2C_OFFSET_CMDLEN]    = ISX019_I2C_RDREQ_LEN;
+  buf[ISX019_I2C_OFFSET_CMD]       = ISX019_I2C_CMD_READ;
+  buf[ISX019_I2C_OFFSET_CATEGORY]  = cat;
+  buf[ISX019_I2C_OFFSET_ADDRESS_H] = addr >> 8;
+  buf[ISX019_I2C_OFFSET_ADDRESS_L] = addr & 0xff;
+  buf[ISX019_I2C_OFFSET_READSIZE]  = size;
+
+  len = ISX019_I2C_OFFSET_READSIZE + 1;
+  buf[len] = calc_isx019_chksum(buf, len);
+  len++;
+
+  ret = i2c_write(g_isx019_private.i2c, config, buf, len);
+  return ret;
+}
+
+static int isx019_i2c_read(uint8_t cat,
+                           uint16_t addr,
+                           FAR uint8_t *data,
+                           uint8_t size)
+{
+  int ret;
+  struct i2c_config_s config;
+
+  DEBUGASSERT(size <= ISX019_I2C_REGSIZE_MAX);
+
+  config.frequency = ISX019_I2C_FREQUENCY;
+  config.address   = ISX019_I2C_SLVADDR;
+  config.addrlen   = ISX019_I2C_SLVADDR_LEN;
+
+  i2c_lock();
+
+  ret = send_read_cmd(&config, cat, addr, size);
+  if (ret == OK)
+    {
+      ret = recv_read_response(&config, data, size);
+    }
+
+  i2c_unlock();
+
+  return ret;
+}
+
+static void fpga_init(void)
+{
+  uint8_t regval;
+
+  regval = FPGA_RESET_ENABLE;
+  fpga_i2c_write(FPGA_RESET, &regval, 1);
+  regval = FPGA_DATA_OUTPUT_STOP;
+  fpga_i2c_write(FPGA_DATA_OUTPUT, &regval, 1);
+  fpga_activate_setting();
+  regval = FPGA_RESET_RELEASE;
+  fpga_i2c_write(FPGA_RESET, &regval, 1);
+  fpga_activate_setting();
+}
+
+static int set_drive_mode(void)
+{
+  uint8_t drv[] =
+    {
+#ifdef CONFIG_VIDEO_ISX019_DOL2
+      DOL2_30FPS_SENS, DOL2_30FPS_POST, DOL2_30FPS_SENSPOST, DOL2_30FPS_IO
+#else
+      DOL3_30FPS_SENS, DOL3_30FPS_POST, DOL3_30FPS_SENSPOST, DOL3_30FPS_IO
+#endif
+    };
+
+  nxsig_usleep(TRANSITION_TIME_TO_STARTUP);
+
+  isx019_i2c_write(CAT_CONFIG, MODE_SENSSEL,      &drv[INDEX_SENS], 1);
+  isx019_i2c_write(CAT_CONFIG, MODE_POSTSEL,      &drv[INDEX_POST], 1);
+  isx019_i2c_write(CAT_CONFIG, MODE_SENSPOST_SEL, &drv[INDEX_SENSPOST], 1);
+
+  nxsig_usleep(TRANSITION_TIME_TO_STREAMING);
+
+  return OK;
+}
+
+static bool try_repeat(int sec, int usec, CODE int (*trial_func)(void))
+{
+  int ret;
+  struct timeval start;
+  struct timeval now;
+  struct timeval delta;
+  struct timeval wait;
+
+  wait.tv_sec = sec;
+  wait.tv_usec = usec;
+
+  gettimeofday(&start, NULL);
+  while (1)
+    {
+      ret = trial_func();
+      if (ret != -ENODEV)
+        {
+          break;
+        }
+      else
+        {
+          gettimeofday(&now, NULL);
+          timersub(&now, &start, &delta);
+          if (timercmp(&delta, &wait, >))
+            {
+              break;
+            }
+        }
+    };
+
+  return (ret == OK);
+}
+
+static int try_isx019_i2c(void)
+{
+  uint8_t buf;
+  return isx019_i2c_read(CAT_SYSCOM, DEVSTS, &buf, 1);
+}
+
+static int try_fpga_i2c(void)
+{
+  uint8_t buf;
+  return fpga_i2c_read(FPGA_VERSION, &buf, 1);
+}
+
+static void power_on(void)
+{
+  g_isx019_private.i2c = board_isx019_initialize();
+  board_isx019_power_on();
+  board_isx019_release_reset();
+}
+
+static void power_off(void)
+{
+  board_isx019_set_reset();
+  board_isx019_power_off();
+  board_isx019_uninitialize(g_isx019_private.i2c);
+}
+
+static bool isx019_is_available(void)
+{
+  bool ret;
+
+  power_on();
+
+  /* Try to access via I2C
+   * about both ISX019 image sensor and FPGA.
+   */
+
+  ret = false;
+  if (try_repeat(ISX019_ACCESSIBLE_WAIT_SEC,
+                ISX019_ACCESSIBLE_WAIT_USEC,
+                try_isx019_i2c))
+    {
+      if (try_repeat(FPGA_ACCESSIBLE_WAIT_SEC,
+                     FPGA_ACCESSIBLE_WAIT_USEC,
+                     try_fpga_i2c))
+        {
+          ret = true;
+        }
+    }
+
+  power_off();
+
+  return ret;
+}
+
+static int32_t get_value32(uint32_t id)
+{
+  imgsensor_value_t val;
+  isx019_get_value(id, 0, &val);
+  return val.value32;
+}
+
+static void store_default_value(void)
+{
+  FAR isx019_default_value_t *def = &g_isx019_private.default_value;
+
+  def->brightness   = get_value32(IMGSENSOR_ID_BRIGHTNESS);
+  def->contrast     = get_value32(IMGSENSOR_ID_CONTRAST);
+  def->saturation   = get_value32(IMGSENSOR_ID_SATURATION);
+  def->hue          = get_value32(IMGSENSOR_ID_HUE);
+  def->awb          = get_value32(IMGSENSOR_ID_AUTO_WHITE_BALANCE);
+  def->gamma        = get_value32(IMGSENSOR_ID_GAMMA);
+  def->ev           = get_value32(IMGSENSOR_ID_EXPOSURE);
+  def->hflip_video  = get_value32(IMGSENSOR_ID_HFLIP_VIDEO);
+  def->vflip_video  = get_value32(IMGSENSOR_ID_VFLIP_VIDEO);
+  def->hflip_still  = get_value32(IMGSENSOR_ID_HFLIP_STILL);
+  def->vflip_still  = get_value32(IMGSENSOR_ID_VFLIP_STILL);
+  def->sharpness    = get_value32(IMGSENSOR_ID_SHARPNESS);
+  def->ae           = get_value32(IMGSENSOR_ID_EXPOSURE_AUTO);
+  def->exptime      = get_value32(IMGSENSOR_ID_EXPOSURE_ABSOLUTE);
+  def->wbmode       = get_value32(IMGSENSOR_ID_AUTO_N_PRESET_WB);
+  def->hdr          = get_value32(IMGSENSOR_ID_WIDE_DYNAMIC_RANGE);
+  def->iso          = get_value32(IMGSENSOR_ID_ISO_SENSITIVITY);
+  def->iso_auto     = get_value32(IMGSENSOR_ID_ISO_SENSITIVITY_AUTO);
+  def->meter        = get_value32(IMGSENSOR_ID_EXPOSURE_METERING);
+  def->threealock   = get_value32(IMGSENSOR_ID_3A_LOCK);
+  def->threeastatus = get_value32(IMGSENSOR_ID_3A_STATUS);
+  def->jpgquality   = get_value32(IMGSENSOR_ID_JPEG_QUALITY);
+}
+
+static int isx019_init(void)
+{
+  uint32_t clk;
+
+  power_on();
+  set_drive_mode();
+  fpga_init();
+  initialize_jpg_quality();
+  store_default_value();
+  clk = board_isx019_get_master_clock();
+  g_isx019_private.clock_ratio
+    = (float)clk / ISX019_STANDARD_MASTER_CLOCK;
+
+  return OK;
+}
+
+static int isx019_uninit(void)
+{
+  power_off();
+  return OK;
+}
+
+static FAR const char *isx019_get_driver_name(void)
+{
+#ifdef CONFIG_VIDEO_ISX019_NAME_WITH_VERSION
+  static char name[16];
+  uint8_t f_ver = 0;
+  uint16_t is_ver = 0;
+
+  isx019_i2c_read(CAT_VERSION, ROM_VERSION, (FAR uint8_t *)&is_ver, 2);
+  fpga_i2c_read(FPGA_VERSION, &f_ver, 1);
+  snprintf(name, sizeof(name), "ISX019 v%04x_%02d", is_ver, f_ver);
+
+  return name;
+#else
+  return "ISX019";
+#endif
+}
+
+static int validate_format(int nr_fmt, FAR imgsensor_format_t *fmt)
+{
+  int ret;
+
+  uint16_t main_w;
+  uint16_t main_h;
+  uint16_t sub_w;
+  uint16_t sub_h;
+
+  if ((nr_fmt < 1) || (nr_fmt > 2))
+    {
+      return -EINVAL;
+    }
+
+  if (fmt == NULL)
+    {
+      return -EINVAL;
+    }
+
+  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 */
+      case IMGSENSOR_PIX_FMT_JPEG:             /* JPEG */
+      case IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + sub image */
+
+        if (!VALIDATE_FRAMESIZE(main_w, main_h))
+          {
+            ret = -EINVAL;
+            break;
+          }
+
+        if (nr_fmt > 1)
+          {
+            sub_w = fmt[IMGSENSOR_FMT_SUB].width;
+            sub_h = fmt[IMGSENSOR_FMT_SUB].height;
+            if (!VALIDATE_THUMNAIL_SIZE(main_w, sub_w) ||
+                !VALIDATE_THUMNAIL_SIZE(main_h, sub_h))
+              {
+                ret = -EINVAL;
+                break;
+              }
+          }
+
+        ret = OK;
+        break;
+
+      default: /* otherwise */
+        ret = -EINVAL;
+        break;
+    }
+
+  return ret;
+}
+
+static int validate_frameinterval(FAR imgsensor_interval_t *interval)
+{
+  int ret = -EINVAL;
+
+  if (interval == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Avoid multiplication overflow */
+
+  if ((interval->denominator * 10) / 10 != interval->denominator)
+    {
+      return -EINVAL;
+    }
+
+  /* Avoid division by zero */
+
+  if (interval->numerator == 0)
+    {
+      return -EINVAL;
+    }
+
+  switch ((interval->denominator * 10) / interval->numerator)
+    {
+      case 300:  /* 30FPS  */
+      case 150:  /* 15FPS  */
+      case 100:  /* 10FPS  */
+      case 75:   /* 7.5FPS */
+        ret = OK;
+        break;
+
+      default:  /* otherwise  */
+        ret = -EINVAL;
+        break;
+    }
+
+  return ret;
+}
+
+static int isx019_validate_frame_setting(imgsensor_stream_type_t type,
+                                         uint8_t nr_fmt,
+                                         FAR imgsensor_format_t *fmt,
+                                         FAR imgsensor_interval_t *interval)
+{
+  int ret = OK;
+
+  ret = validate_format(nr_fmt, fmt);
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  return validate_frameinterval(interval);
+}
+
+static int activate_flip(imgsensor_stream_type_t type)
+{
+  uint8_t flip;
+
+  flip = (type == IMGSENSOR_STREAM_TYPE_VIDEO) ?
+         g_isx019_private.flip_video : g_isx019_private.flip_still;
+
+  return isx019_i2c_write(CAT_CONFIG, REVERSE, &flip, 1);
+}
+
+static int activate_clip(imgsensor_stream_type_t type,
+                         uint16_t w,
+                         uint16_t h)
+{
+  FAR isx019_rect_t *clip;
+  uint8_t size;
+  uint8_t top;
+  uint8_t left = 0;
+
+  clip = (type == IMGSENSOR_STREAM_TYPE_VIDEO) ?
+         &g_isx019_private.clip_video : &g_isx019_private.clip_still;
+
+  switch (w)
+    {
+      case 1280:
+        if (clip->width == 640) /* In this case, c_h == 360 */
+          {
+            size = FPGA_CLIP_640_360;
+            top  = clip->top / FPGA_CLIP_UNIT;
+            left = clip->left / FPGA_CLIP_UNIT;
+
+            if (h == 720)
+              {
+                /* Shift (960 - 720) / 2 lines */
+
+                top  += 120 / FPGA_CLIP_UNIT;
+              }
+          }
+        else if (clip->width == 1280)
+          {
+            /* In this case, clip->height == 720 */
+
+            size = FPGA_CLIP_1280_720;
+            top  = clip->top / FPGA_CLIP_UNIT;
+            left = clip->left / FPGA_CLIP_UNIT;
+          }
+        else /* no clip */
+          {
+            if (h == 720)
+              {
+                size = FPGA_CLIP_1280_720;
+
+                /* Shift (960 - 720) / 2 lines */
+
+                top = 120 / FPGA_CLIP_UNIT;
+              }
+            else
+              {
+                size = FPGA_CLIP_NON;
+                top  = 0;
+                left = 0;
+              }
+          }
+
+        break;
+
+      default: /* 640 */
+        if (clip->width == 640)
+          {
+            /* In this case, clip->height == 360 */
+
+            size = FPGA_CLIP_640_360;
+            top  = clip->top / FPGA_CLIP_UNIT;
+            left = clip->left / FPGA_CLIP_UNIT;
+          }
+        else /* no clip */
+          {
+            if (h == 360)
+              {
+                size = FPGA_CLIP_640_360;
+
+                /* Shift (480 - 360) / 2 lines */
+
+                top  = 60 / FPGA_CLIP_UNIT;
+              }
+            else
+              {
+                size = FPGA_CLIP_NON;
+                top  = 0;
+                left = 0;
+              }
+          }
+
+        break;
+    }
+
+  fpga_i2c_write(FPGA_CLIP_SIZE, &size, 1);
+  fpga_i2c_write(FPGA_CLIP_TOP,  &top, 1);
+  fpga_i2c_write(FPGA_CLIP_LEFT, &left, 1);
+
+  return OK;
+}
+
+static int isx019_start_capture(imgsensor_stream_type_t type,
+                                uint8_t nr_fmt,
+                                FAR imgsensor_format_t *fmt,
+                                FAR imgsensor_interval_t *interval)
+{
+  int ret;
+  uint8_t regval = 0;
+
+  ret = isx019_validate_frame_setting(type, nr_fmt, fmt, interval);
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  ret = activate_flip(type);
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  fpga_lock();
+
+  /* Update FORMAT_AND_SCALE register of FPGA */
+
+  switch (fmt[IMGSENSOR_FMT_MAIN].pixelformat)
+    {
+      case IMGSENSOR_PIX_FMT_RGB565:
+        regval |= FPGA_FORMAT_RGB;
+        break;
+
+      case IMGSENSOR_PIX_FMT_UYVY:
+        regval |= FPGA_FORMAT_YUV;
+        break;
+
+      case IMGSENSOR_PIX_FMT_JPEG:
+        regval |= FPGA_FORMAT_JPEG;
+        break;
+
+      default: /* IMGSENSOR_PIX_FMT_JPEG_WITH_SUBIMG */
+        if (nr_fmt == 1)
+          {
+            regval |= FPGA_FORMAT_JPEG;
+          }
+        else
+          {
+            regval |= FPGA_FORMAT_THUMBNAIL;
+          }
+
+        break;
+    }
+
+  switch (fmt[IMGSENSOR_FMT_MAIN].width)
+   {
+     case 1280:
+       regval |= FPGA_SCALE_1280_960;
+       activate_clip(type,
+                     fmt[IMGSENSOR_FMT_MAIN].width,
+                     fmt[IMGSENSOR_FMT_MAIN].height);
+       break;
+
+     case 640:
+       regval |= FPGA_SCALE_640_480;
+       activate_clip(type,
+                     fmt[IMGSENSOR_FMT_MAIN].width,
+                     fmt[IMGSENSOR_FMT_MAIN].height);
+       break;
+
+     case 320:
+       regval |= FPGA_SCALE_320_240;
+       break;
+
+     default: /* 160 */
+
+       regval |= FPGA_SCALE_160_120;
+       break;
+   }
+
+  fpga_i2c_write(FPGA_FORMAT_AND_SCALE, &regval, 1);
+
+  /* Update FPS_AND_THUMBNAIL register of FPGA */
+
+  regval = 0;
+
+  if (nr_fmt == 2)
+    {
+      switch (fmt[IMGSENSOR_FMT_MAIN].width / fmt[IMGSENSOR_FMT_SUB].width)
+        {
+          case 1 : /* 1/1 */
+            regval |= FPGA_THUMBNAIL_SCALE_1_1;
+            break;
+
+          case 2 : /* 1/2 */
+            regval |= FPGA_THUMBNAIL_SCALE_1_2;
+            break;
+
+          case 4 : /* 1/4 */
+            regval |= FPGA_THUMBNAIL_SCALE_1_4;
+            break;
+
+          default : /* 1/8 */
+            regval |= FPGA_THUMBNAIL_SCALE_1_8;
+            break;
+        }
+    }
+
+  switch ((interval->denominator * 10) / interval->numerator)
+    {
+      case 300:  /* 30FPS */
+        regval |= FPGA_FPS_1_1;
+        break;
+
+      case 150:  /* 15FPS */
+        regval |= FPGA_FPS_1_2;
+        break;
+
+      case 100:  /* 10FPS */
+        regval |= FPGA_FPS_1_3;
+        break;
+
+      case 75:   /* 7.5FPS */
+        regval |= FPGA_FPS_1_4;
+        break;
+
+      default:   /* otherwise */
+
+        /* It may not come here because the value has already been validated
+         * in validate_frameinterval().
+         */
+
+        break;
+    }
+
+  fpga_i2c_write(FPGA_FPS_AND_THUMBNAIL, &regval, 1);
+
+  regval = FPGA_DATA_OUTPUT_START;
+  fpga_i2c_write(FPGA_DATA_OUTPUT, &regval, 1);
+
+  fpga_activate_setting();
+  fpga_unlock();
+  g_isx019_private.stream = type;
+
+  return OK;
+}
+
+static int isx019_stop_capture(imgsensor_stream_type_t type)
+{
+  uint8_t regval;
+
+  regval = FPGA_DATA_OUTPUT_STOP;
+  fpga_lock();
+  fpga_i2c_write(FPGA_DATA_OUTPUT, &regval, 1);
+  fpga_activate_setting();
+  fpga_unlock();
+  return OK;
+}
+
+static int isx019_get_supported_value(uint32_t id,
+                                      FAR imgsensor_supported_value_t *val)
+{
+  int ret = OK;
+  FAR struct isx019_default_value_s *def = &g_isx019_private.default_value;
+
+  DEBUGASSERT(val);
+
+  switch (id)
+    {
+      case IMGSENSOR_ID_BRIGHTNESS:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_BRIGHTNESS, MAX_BRIGHTNESS,
+                                STEP_BRIGHTNESS, def->brightness);
+        break;
+
+      case IMGSENSOR_ID_CONTRAST:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_CONTRAST, MAX_CONTRAST,
+                                STEP_CONTRAST, def->contrast);
+        break;
+
+      case IMGSENSOR_ID_SATURATION:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_SATURATION, MAX_SATURATION,
+                                STEP_SATURATION, def->saturation);
+        break;
+
+      case IMGSENSOR_ID_HUE:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_HUE, MAX_HUE,
+                                STEP_HUE, def->hue);
+        break;
+
+      case IMGSENSOR_ID_AUTO_WHITE_BALANCE:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_AWB, MAX_AWB,
+                                STEP_AWB, def->awb);
+        break;
+
+      case IMGSENSOR_ID_GAMMA:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_GAMMA, MAX_GAMMA,
+                                STEP_GAMMA, def->gamma);
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_EXPOSURE, MAX_EXPOSURE,
+                                STEP_EXPOSURE, def->ev);
+        break;
+
+      case IMGSENSOR_ID_HFLIP_VIDEO:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_HFLIP, MAX_HFLIP,
+                                STEP_HFLIP, def->hflip_video);
+        break;
+
+      case IMGSENSOR_ID_VFLIP_VIDEO:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_VFLIP, MAX_VFLIP,
+                                STEP_VFLIP, def->vflip_video);
+        break;
+
+      case IMGSENSOR_ID_HFLIP_STILL:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_HFLIP, MAX_HFLIP,
+                                STEP_HFLIP, def->hflip_still);
+        break;
+
+      case IMGSENSOR_ID_VFLIP_STILL:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_VFLIP, MAX_VFLIP,
+                                STEP_VFLIP, def->hflip_still);
+        break;
+
+      case IMGSENSOR_ID_SHARPNESS:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_SHARPNESS, MAX_SHARPNESS,
+                                STEP_SHARPNESS, def->sharpness);
+        break;
+
+      case IMGSENSOR_ID_COLORFX:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU;
+        SET_DISCRETE(val->u.discrete,
+                     NR_COLORFX,
+                     g_isx019_colorfx,
+                     IMGSENSOR_COLORFX_NONE);
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_AUTO:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_AE, MAX_AE,
+                                STEP_AE, def->ae);
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_ABSOLUTE:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_EXPOSURETIME, MAX_EXPOSURETIME,
+                                STEP_EXPOSURETIME, def->exptime);
+        break;
+
+      case IMGSENSOR_ID_AUTO_N_PRESET_WB:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER_MENU;
+        SET_DISCRETE(val->u.discrete,
+                     NR_WBMODE,
+                     g_isx019_wbmode,
+                     IMGSENSOR_WHITE_BALANCE_AUTO);
+        break;
+
+      case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_HDR, MAX_HDR,
+                                STEP_HDR, def->hdr);
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_ISO, MAX_ISO,
+                                STEP_ISO, def->iso);
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_AUTOISO, MAX_AUTOISO,
+                                STEP_AUTOISO, def->iso_auto);
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_METERING:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_METER, MAX_METER,
+                                STEP_METER, def->meter);
+        break;
+
+      case IMGSENSOR_ID_3A_LOCK:
+        val->type = IMGSENSOR_CTRL_TYPE_BITMASK;
+        SET_RANGE(val->u.range, MIN_3ALOCK, MAX_3ALOCK,
+                                STEP_3ALOCK, def->threealock);
+        break;
+
+      case IMGSENSOR_ID_3A_PARAMETER:
+        val->type = IMGSENSOR_CTRL_TYPE_U8;
+        SET_ELEMS(val->u.elems, NRELEM_3APARAM, MIN_3APARAM, MAX_3APARAM,
+                                STEP_3APARAM);
+        break;
+
+      case IMGSENSOR_ID_3A_STATUS:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_3ASTATUS, MAX_3ASTATUS,
+                                STEP_3ASTATUS, def->threeastatus);
+        break;
+
+      case IMGSENSOR_ID_JPEG_QUALITY:
+        val->type = IMGSENSOR_CTRL_TYPE_INTEGER;
+        SET_RANGE(val->u.range, MIN_JPGQUALITY, MAX_JPGQUALITY,
+                                STEP_JPGQUALITY, def->jpgquality);
+        break;
+
+      case IMGSENSOR_ID_CLIP_VIDEO:
+      case IMGSENSOR_ID_CLIP_STILL:
+        val->type = IMGSENSOR_CTRL_TYPE_U32;
+        SET_ELEMS(val->u.elems, NRELEM_CLIP, MIN_CLIP, MAX_CLIP,
+                                STEP_CLIP);
+        break;
+
+      default:
+        ret = -EINVAL;
+        break;
+    }
+
+  return ret;
+}
+
+static int32_t not_convert(int32_t val)
+{
+  return val;
+}
+
+static int32_t convert_brightness_is2reg(int32_t val)
+{
+  return (val << 2);
+}
+
+static int32_t convert_brightness_reg2is(int32_t val)
+{
+  return (val >> 2);
+}
+
+static int32_t convert_hue_is2reg(int32_t val)
+{
+  return (val * 90) / 128;
+}
+
+static int32_t convert_hue_reg2is(int32_t val)
+{
+  return (val * 128) / 90;
+}
+
+static int32_t convert_awb_is2reg(int32_t val)
+{
+  return (val == 1) ? 0 : 2;
+}
+
+static int32_t convert_awb_reg2is(int32_t val)
+{
+  return (val == 0) ? 1 : 0;
+}
+
+static int32_t convert_hdr_is2reg(int32_t val)
+{
+  int32_t ret = AEWDMODE_AUTO;
+
+  switch (val)
+    {
+      case 0:
+        ret = AEWDMODE_NORMAL;
+        break;
+
+      case 1:
+        ret = AEWDMODE_AUTO;
+        break;
+
+      case 2:
+        ret = AEWDMODE_HDR;
+        break;
+
+      default:
+        /* It may not come here because the value has already been validated
+         * in validate_value().
+         */
+
+        break;
+    }
+
+  return ret;
+}
+
+static int32_t convert_hdr_reg2is(int32_t val)
+{
+  int32_t ret;
+
+  switch (val)
+    {
+      case AEWDMODE_NORMAL:
+        ret = 0;
+        break;
+
+      case AEWDMODE_AUTO:
+        ret = 1;
+        break;
+
+      default: /* AEWDMODE_HDR */
+        ret = 2;
+        break;
+    }
+
+  return ret;
+}
+
+static convert_t get_reginfo(uint32_t id, bool is_set,
+                             FAR isx019_reginfo_t *reg)
+{
+  convert_t cvrt = NULL;
+
+  DEBUGASSERT(reg);
+
+  switch (id)
+    {
+      case IMGSENSOR_ID_BRIGHTNESS:
+        SET_REGINFO(reg, CAT_PICTTUNE, UIBRIGHTNESS, 2);
+        cvrt = is_set ? convert_brightness_is2reg
+                      : convert_brightness_reg2is;
+        break;
+
+      case IMGSENSOR_ID_CONTRAST:
+        SET_REGINFO(reg, CAT_PICTTUNE, UICONTRAST, 1);
+        cvrt = not_convert;
+        break;
+
+      case IMGSENSOR_ID_SATURATION:
+        SET_REGINFO(reg, CAT_PICTTUNE, UISATURATION, 1);
+        cvrt = not_convert;
+        break;
+
+      case IMGSENSOR_ID_HUE:
+        SET_REGINFO(reg, CAT_PICTTUNE, UIHUE, 1);
+        cvrt = is_set ? convert_hue_is2reg : convert_hue_reg2is;
+        break;
+
+      case IMGSENSOR_ID_AUTO_WHITE_BALANCE:
+        SET_REGINFO(reg, CAT_CATAWB, AWBMODE, 1);
+        cvrt = is_set ? convert_awb_is2reg : convert_awb_reg2is;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE:
+        SET_REGINFO(reg, CAT_AEDGRM, EVSEL, 1);
+        cvrt = not_convert;
+        break;
+
+      case IMGSENSOR_ID_SHARPNESS:
+        SET_REGINFO(reg, CAT_PICTTUNE, UISHARPNESS, 1);
+        cvrt = not_convert;
+        break;
+
+      case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE:
+        SET_REGINFO(reg, CAT_AEWD, AEWDMODE, 1);
+        cvrt = is_set ? convert_hdr_is2reg : convert_hdr_reg2is;
+        break;
+
+      default:
+        break;
+    }
+
+  return cvrt;
+}
+
+static void set_flip(FAR uint8_t *flip, uint8_t direction, int32_t val)
+{
+  DEBUGASSERT(flip);
+
+  *flip = (val == 0) ? (*flip & ~direction) : (*flip | direction);
+}
+
+static int set_hflip_video(imgsensor_value_t val)
+{
+  set_flip(&g_isx019_private.flip_video, H_REVERSE, val.value32);
+  if (g_isx019_private.stream == IMGSENSOR_STREAM_TYPE_VIDEO)
+    {
+      activate_flip(IMGSENSOR_STREAM_TYPE_VIDEO);
+    }
+
+  return OK;
+}
+
+static int set_vflip_video(imgsensor_value_t val)
+{
+  set_flip(&g_isx019_private.flip_video, V_REVERSE, val.value32);
+  if (g_isx019_private.stream == IMGSENSOR_STREAM_TYPE_VIDEO)
+    {
+      activate_flip(IMGSENSOR_STREAM_TYPE_VIDEO);
+    }
+
+  return OK;
+}
+
+static int set_hflip_still(imgsensor_value_t val)
+{
+  set_flip(&g_isx019_private.flip_still, H_REVERSE, val.value32);
+  if (g_isx019_private.stream == IMGSENSOR_STREAM_TYPE_STILL)
+    {
+      activate_flip(IMGSENSOR_STREAM_TYPE_STILL);
+    }
+
+  return OK;
+}
+
+static int set_vflip_still(imgsensor_value_t val)
+{
+  set_flip(&g_isx019_private.flip_still, V_REVERSE, val.value32);
+  if (g_isx019_private.stream == IMGSENSOR_STREAM_TYPE_STILL)
+    {
+      activate_flip(IMGSENSOR_STREAM_TYPE_STILL);
+    }
+
+  return OK;
+}
+
+static int set_colorfx(imgsensor_value_t val)
+{
+  int ret = -EINVAL;
+  FAR isx019_default_value_t *def = &g_isx019_private.default_value;
+  int32_t sat;
+  int32_t sharp;
+
+  /* ISX019 realize color effects by adjusting saturation and sharpness. */
+
+  switch (val.value32)
+    {
+      case IMGSENSOR_COLORFX_NONE:
+
+        sat   = def->saturation;
+        sharp = def->sharpness;
+        break;
+
+      case IMGSENSOR_COLORFX_BW:
+
+        sat   = BW_COLORS_SATURATION;
+        sharp = def->sharpness;
+        break;
+
+      case IMGSENSOR_COLORFX_VIVID:
+
+        sat   = VIVID_COLORS_SATURATION;
+        sharp = VIVID_COLORS_SHARPNESS;
+        break;
+
+      default:
+
+        /* It may not come here because the value has already been validated
+         * in validate_value().
+         */
+
+        break;
+    }
+
+  ret = isx019_i2c_write(CAT_PICTTUNE, UISATURATION, (FAR uint8_t *)&sat, 1);
+  if (ret == OK)
+    {
+      ret = isx019_i2c_write(CAT_PICTTUNE,
+                             UISHARPNESS,
+                             (FAR uint8_t *)&sharp,
+                             1);
+      if (ret == OK)
+        {
+          g_isx019_private.colorfx = val.value32;
+        }
+    }
+
+  return ret;
+}
+
+static int set_ae(imgsensor_value_t val)
+{
+  uint32_t regval = 0;
+
+  if (val.value32 == IMGSENSOR_EXPOSURE_AUTO)
+    {
+      regval = 0;
+    }
+  else
+    {
+      isx019_i2c_read(CAT_AESOUT, SHT_TIME, (FAR uint8_t *)&regval, 4);
+    }
+
+  return isx019_i2c_write(CAT_CATAE, SHT_PRIMODE, (FAR uint8_t *)&regval, 4);
+}
+
+static int set_exptime(imgsensor_value_t val)
+{
+  uint32_t regval;
+
+  /* Take into account the master clock and convert unit.
+   *   image sensor I/F : 100usec
+   *   register         :   1usec
+   */
+
+  regval = val.value32 * 100 * g_isx019_private.clock_ratio;
+
+  return isx019_i2c_write(CAT_CATAE, SHT_PRIMODE, (FAR uint8_t *)&regval, 4);
+}
+
+static int set_wbmode(imgsensor_value_t val)
+{
+  /*  AWBMODE     mode0 : auto, mode4 : user defined white balance
+   *  AWBUSER_NO  definition number for AWBMODE = mode4
+   *  USER0_R, USER1_B : R,B value for AWBUSER_NO = 0
+   *  USER1_R, USER1_B : R,B value for AWBUSER_NO = 1
+   */
+
+  uint8_t  mode;
+  uint16_t r_addr;
+  uint16_t b_addr;
+  uint16_t r;
+  uint16_t b;
+  static bool toggle = false;
+
+  if (toggle)
+    {
+      r_addr = USER0_R;
+      b_addr = USER0_B;
+      toggle = false;
+    }
+  else
+    {
+      r_addr = USER1_R;
+      b_addr = USER1_B;
+      toggle = true;
+    }
+
+  switch (val.value32)
+    {
+      case IMGSENSOR_WHITE_BALANCE_AUTO:
+        mode = AWBMODE_AUTO;
+        break;
+
+      case IMGSENSOR_WHITE_BALANCE_INCANDESCENT:
+        r = RED_INCANDESCENT;
+        b = BLUE_INCANDESCENT;
+        mode = AWBMODE_MANUAL;
+        break;
+
+      case IMGSENSOR_WHITE_BALANCE_FLUORESCENT:
+        r = RED_FLUORESCENT;
+        b = BLUE_FLUORESCENT;
+        mode = AWBMODE_MANUAL;
+        break;
+
+      case IMGSENSOR_WHITE_BALANCE_DAYLIGHT:
+        r = RED_DAYLIGHT;
+        b = BLUE_DAYLIGHT;
+        mode = AWBMODE_MANUAL;
+        break;
+
+      case IMGSENSOR_WHITE_BALANCE_CLOUDY:
+        r = RED_CLOUDY;
+        b = BLUE_CLOUDY;
+        mode = AWBMODE_MANUAL;
+        break;
+
+      default: /* IMGSENSOR_WHITE_BALANCE_SHADE */
+        r = RED_SHADE;
+        b = BLUE_SHADE;
+        mode = AWBMODE_MANUAL;
+        break;
+    }
+
+  isx019_i2c_write(CAT_AWB_USERTYPE, r_addr, (FAR uint8_t *)&r, 2);
+  isx019_i2c_write(CAT_AWB_USERTYPE, b_addr, (FAR uint8_t *)&b, 2);
+  isx019_i2c_write(CAT_CATAWB, AWBUSER_NO, (FAR uint8_t *)&toggle, 1);
+  isx019_i2c_write(CAT_CATAWB, AWBMODE, &mode, 1);
+
+  g_isx019_private.wb_mode = val.value32;
+
+  return OK;
+}
+
+static int set_meter(imgsensor_value_t val)
+{
+  uint8_t normal;
+  uint8_t hdr;
+
+  switch (val.value32)
+    {
+      case IMGSENSOR_EXPOSURE_METERING_AVERAGE:
+        normal = AEWEIGHT_AVERAGE;
+        hdr    = AEWEIGHTHDR_AVERAGE;
+        break;
+
+      case IMGSENSOR_EXPOSURE_METERING_CENTER_WEIGHTED:
+        normal = AEWEIGHT_CENTER;
+        hdr    = AEWEIGHTHDR_CENTER;
+        break;
+
+      case IMGSENSOR_EXPOSURE_METERING_SPOT:
+        normal = AEWEIGHT_SPOT;
+        hdr    = AEWEIGHTHDR_SPOT;
+        break;
+
+      default: /* IMGSENSOR_EXPOSURE_METERING_MATRIX */
+        normal = AEWEIGHT_MATRIX;
+        hdr    = AEWEIGHTHDR_MATRIX;
+        break;
+    }
+
+  isx019_i2c_write(CAT_AUTOCTRL, AEWEIGHTMODE, &normal, 1);
+  isx019_i2c_write(CAT_AEWD, AEWEIGHTMODE_WD, &hdr, 1);
+
+  return OK;
+}
+
+static int set_3alock(imgsensor_value_t val)
+{
+  uint8_t regval;
+
+  regval = (val.value32 & IMGSENSOR_LOCK_WHITE_BALANCE) ? AWBMODE_HOLD
+                                                        : AWBMODE_AUTO;
+  isx019_i2c_write(CAT_CATAWB, AWBMODE, &regval, 1);
+
+  regval = (val.value32 & IMGSENSOR_LOCK_EXPOSURE) ? AEMODE_HOLD
+                                                   : AEMODE_AUTO;
+  isx019_i2c_write(CAT_CATAE,  AEMODE,  &regval,  1);
+
+  return OK;
+}
+
+static int set_3aparameter(imgsensor_value_t val)
+{
+  uint16_t gain;
+  uint8_t regval;
+
+  if (val.p_u8 == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Convert unit
+   *  GAIN_LEVEL register(accessed in get_3aparameter()) : 0.3dB
+   *  GAIN_PRIMODE register(accessed in this function)   : 0.1dB
+   */
+
+  gain = val.p_u8[OFFSET_3APARAMETER_AE_GAIN] * 3;
+
+  isx019_i2c_write
+  (CAT_AWB_USERTYPE, USER4_R, &val.p_u8[OFFSET_3APARAMETER_AWB_R], 2);
+  isx019_i2c_write
+  (CAT_AWB_USERTYPE, USER4_B, &val.p_u8[OFFSET_3APARAMETER_AWB_B], 2);
+
+  regval = 4;
+  isx019_i2c_write(CAT_CATAWB, AWBUSER_NO, (FAR uint8_t *)&regval, 1);
+
+  regval = AWBMODE_MANUAL;
+  isx019_i2c_write(CAT_CATAWB, AWBMODE, &regval, 1);
+
+  isx019_i2c_write
+  (CAT_CATAE, SHT_PRIMODE, &val.p_u8[OFFSET_3APARAMETER_AE_SHTTIME], 4);
+  isx019_i2c_write(CAT_CATAE, GAIN_PRIMODE, (FAR uint8_t *)&gain, 2);
+
+  return OK;
+}
+
+static uint16_t calc_gain(double iso)
+{
+  double gain;
+
+  gain = 1 + 10 * log(iso) / M_LN10;
+
+  /* In the above formula, the unit of gain is dB.
+   * Because the register has the 0.1dB unit,
+   * return 10 times dB value.
+   */
+
+  return (uint16_t)(gain * 10);
+}
+
+static int set_iso(imgsensor_value_t val)
+{
+  uint16_t gain;
+
+  /* ISX019 has not ISO sensitivity register but gain register.
+   * So, calculate gain from ISO sensitivity.
+   */
+
+  gain = calc_gain(val.value32 / 1000);
+  isx019_i2c_write(CAT_CATAE, GAIN_PRIMODE, (FAR uint8_t *)&gain, 2);
+
+  g_isx019_private.iso = val.value32;
+  return OK;
+}
+
+static int set_iso_auto(imgsensor_value_t val)
+{
+  uint8_t  buf;
+  uint16_t gain;
+
+  if (val.value32 == IMGSENSOR_ISO_SENSITIVITY_AUTO)
+    {
+      gain = 0;
+      g_isx019_private.iso = 0;
+    }
+  else /* IMGSENSOR_ISO_SENSITIVITY_MANUAL */
+    {
+      isx019_i2c_read(CAT_CATAE, GAIN_PRIMODE, (FAR uint8_t *)&gain, 2);
+
+      if (gain == 0)
+        {
+          /* gain = 0 means auto adjustment mode.
+           * In such a case, apply current auto adjustment value
+           * as manual setting.
+           * Note : auto adjustment value register has the unit 0.3dB.
+           *        So, convert the unit to 0.1dB.
+           */
+
+          isx019_i2c_read(CAT_AECOM, GAIN_LEVEL, &buf, 1);
+          gain = buf * 3;
+        }
+
+      g_isx019_private.iso = val.value32;
+    }
+
+  return isx019_i2c_write(CAT_CATAE, GAIN_PRIMODE, (FAR uint8_t *)&gain, 2);
+}
+
+static uint16_t calc_gamma_regval(double in, double gamma)
+{
+  double out;
+
+  /* 1) Calculate the normalized result.
+   *    formula :  output = input^gamma
+   * 2) Perform scaling for ISX019 register.
+   * 3) Change the format from the floating-point number type
+   *    to the fixed-point number type according to the register.
+   */
+
+  out = pow(in, gamma);
+  out *= GAM_OUTPUT_SCALE;
+
+  return ((uint8_t)out) << 2;
+}
+
+static int set_gamma(imgsensor_value_t val)
+{
+  int i;
+  uint16_t regval;
+  uint16_t offset;
+  double gamma;
+
+  gamma = (double)val.value32 / 1000;
+
+  /* ISX019 gamma adjustment feature is constructed by
+   * registers for low-input and registers for high-input.
+   */
+
+  offset = GAM_KNOT_C0;
+
+  for (i = 0; i < NR_GAM_KNOT_LOWINPUT; i++)
+    {
+      regval = calc_gamma_regval((double)i * GAM_LOWINPUT_INTERVAL, gamma);
+      isx019_i2c_write(CAT_PICTGAMMA, offset, (FAR uint8_t *)&regval, 2);
+      offset += 2;
+    }
+
+  offset = GAM_KNOT_C11;
+
+  for (i = 0; i < NR_GAM_KNOT_HIGHINPUT; i++)
+    {
+      regval = calc_gamma_regval
+               ((double)(i + 1) * GAM_HIGHINPUT_INTERVAL, gamma);
+      isx019_i2c_write(CAT_PICTGAMMA, offset, (FAR uint8_t *)&regval, 2);
+      offset += 2;
+    }
+
+  /* Special register setting.
+   * GAM_KNOT_C9 and GAM_KNOT_C10 need to be set
+   * to be continuous.
+   * So, this driver set GAM_KNOT_C10 = GAM_KNOT_C8,
+   * GAM_KNOT_C9 = GAM_KNOT_C11.
+   */
+
+  isx019_i2c_read(CAT_PICTGAMMA,  GAM_KNOT_C8, (FAR uint8_t *)&regval, 2);
+  isx019_i2c_write(CAT_PICTGAMMA, GAM_KNOT_C10, (FAR uint8_t *)&regval, 2);
+  isx019_i2c_read(CAT_PICTGAMMA,  GAM_KNOT_C11, (FAR uint8_t *)&regval, 2);
+  isx019_i2c_write(CAT_PICTGAMMA, GAM_KNOT_C9, (FAR uint8_t *)&regval, 2);
+
+  g_isx019_private.gamma = val.value32;
+  return OK;
+}
+
+static void search_dqt_data(int32_t quality,
+                            FAR uint8_t **y_head, FAR uint8_t **y_calc,
+                            FAR uint8_t **c_head, FAR uint8_t **c_calc)
+{
+  int i;
+  FAR isx019_fpga_jpg_quality_t *jpg = &g_isx019_jpg_quality[0];
+
+  *y_head = NULL;
+  *y_calc = NULL;
+  *c_head = NULL;
+  *c_calc = NULL;
+
+  /* Search approximate DQT data from a table by rounding quality. */
+
+  quality = ((quality + 5) / 10) * 10;
+  if (quality == 0)
+    {
+      /* Set the minimum value of quality to 10. */
+
+      quality = 10;
+    }
+
+  for (i = 0; i < NR_JPGSETTING_TBL; i++)
+    {
+      if (quality == jpg->quality)
+        {
+          *y_head = jpg->y_head;
+          *y_calc = jpg->y_calc;
+          *c_head = jpg->c_head;
+          *c_calc = jpg->c_calc;
+          break;
+        }
+
+      jpg++;
+    }
+}
+
+int set_dqt(uint8_t component, uint8_t target, FAR uint8_t *buf)
+{
+  int i;
+  uint8_t addr;
+  uint8_t select;
+  uint8_t data;
+  uint8_t regval;
+
+  if (target == FPGA_DQT_DATA)
+    {
+      addr   = FPGA_DQT_ADDRESS;
+      select = FPGA_DQT_SELECT;
+      data   = FPGA_DQT_DATA;
+    }
+  else
+    {
+      addr   = FPGA_DQT_CALC_ADDRESS;
+      select = FPGA_DQT_CALC_SELECT;
+      data   = FPGA_DQT_CALC_DATA;
+    }
+
+  fpga_i2c_write(select, &component, 1);
+  for (i = 0; i < JPEG_DQT_ARRAY_SIZE; i++)
+    {
+      regval = i | FPGA_DQT_WRITE | FPGA_DQT_BUFFER;
+      fpga_i2c_write(addr, &regval, 1);
+      fpga_i2c_write(data, &buf[i], 1);
+    }
+
+  return OK;
+}
+
+static int set_jpg_quality(imgsensor_value_t val)
+{
+  FAR uint8_t *y_head;
+  FAR uint8_t *y_calc;
+  FAR uint8_t *c_head;
+  FAR uint8_t *c_calc;
+
+  /* Set JPEG quality by setting DQT information to FPGA. */
+
+  search_dqt_data(val.value32, &y_head, &y_calc, &c_head, &c_calc);
+  if ((y_head == NULL) ||
+      (y_calc == NULL) ||
+      (c_head == NULL) ||
+      (c_calc == NULL))
+    {
+      return -EINVAL;
+    }
+
+  fpga_lock();
+
+  /* Update DQT data and activate them. */
+
+  set_dqt(FPGA_DQT_LUMA,   FPGA_DQT_DATA, y_head);
+  set_dqt(FPGA_DQT_CHROMA, FPGA_DQT_DATA, c_head);
+  set_dqt(FPGA_DQT_LUMA,   FPGA_DQT_CALC_DATA, y_calc);
+  set_dqt(FPGA_DQT_CHROMA, FPGA_DQT_CALC_DATA, c_calc);
+  fpga_activate_setting();
+
+  /* Update non-active side in preparation for other activation trigger. */
+
+  set_dqt(FPGA_DQT_LUMA,   FPGA_DQT_DATA, y_head);
+  set_dqt(FPGA_DQT_CHROMA, FPGA_DQT_DATA, c_head);
+  set_dqt(FPGA_DQT_LUMA,   FPGA_DQT_CALC_DATA, y_calc);
+  set_dqt(FPGA_DQT_CHROMA, FPGA_DQT_CALC_DATA, c_calc);
+
+  fpga_unlock();
+
+  g_isx019_private.jpg_quality = val.value32;
+  return OK;
+}
+
+static int initialize_jpg_quality(void)
+{
+  imgsensor_value_t val;
+
+  val.value32 = CONFIG_VIDEO_ISX019_INITIAL_JPEG_QUALITY;
+  return set_jpg_quality(val);
+}
+
+static bool validate_clip_setting(FAR uint32_t *clip)
+{
+  bool ret = false;
+  uint32_t w;
+  uint32_t h;
+
+  DEBUGASSERT(clip);
+
+  w = clip[IMGSENSOR_CLIP_INDEX_WIDTH];
+  h = clip[IMGSENSOR_CLIP_INDEX_HEIGHT];
+
+  if (((w == 1280) && (h == 720)) ||
+      ((w ==  640) && (h == 360)) ||
+      ((w ==  0) && (h == 0)))
+    {
+      ret = true;
+    }
+
+  return ret;
+}
+
+static int set_clip(FAR uint32_t *val, FAR isx019_rect_t *target)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (!validate_clip_setting(val))
+    {
+      return -EINVAL;
+    }
+
+  target->left   = (int32_t)val[IMGSENSOR_CLIP_INDEX_LEFT];
+  target->top    = (int32_t)val[IMGSENSOR_CLIP_INDEX_TOP];
+  target->width  = val[IMGSENSOR_CLIP_INDEX_WIDTH];
+  target->height = val[IMGSENSOR_CLIP_INDEX_HEIGHT];
+
+  return OK;
+}
+
+static int set_clip_video(imgsensor_value_t val)
+{
+  return set_clip(val.p_u32, &g_isx019_private.clip_video);
+}
+
+static int set_clip_still(imgsensor_value_t val)
+{
+  return set_clip(val.p_u32, &g_isx019_private.clip_still);
+}
+
+static setvalue_t set_value_func(uint32_t id)
+{
+  setvalue_t func = NULL;
+
+  switch (id)
+    {
+      case IMGSENSOR_ID_GAMMA:
+        func = set_gamma;
+        break;
+
+      case IMGSENSOR_ID_HFLIP_VIDEO:
+        func = set_hflip_video;
+        break;
+
+      case IMGSENSOR_ID_VFLIP_VIDEO:
+        func = set_vflip_video;
+        break;
+
+      case IMGSENSOR_ID_HFLIP_STILL:
+        func = set_hflip_still;
+        break;
+
+      case IMGSENSOR_ID_VFLIP_STILL:
+        func = set_vflip_still;
+        break;
+
+      case IMGSENSOR_ID_COLORFX:
+        func = set_colorfx;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_AUTO:
+        func = set_ae;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_ABSOLUTE:
+        func = set_exptime;
+        break;
+
+      case IMGSENSOR_ID_AUTO_N_PRESET_WB:
+        func = set_wbmode;
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY:
+        func = set_iso;
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO:
+        func = set_iso_auto;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_METERING:
+        func = set_meter;
+        break;
+
+      case IMGSENSOR_ID_3A_LOCK:
+        func = set_3alock;
+        break;
+
+      case IMGSENSOR_ID_3A_PARAMETER:
+        func = set_3aparameter;
+        break;
+
+      case IMGSENSOR_ID_JPEG_QUALITY:
+        func = set_jpg_quality;
+        break;
+
+      case IMGSENSOR_ID_CLIP_VIDEO:
+        func = set_clip_video;
+        break;
+
+      case IMGSENSOR_ID_CLIP_STILL:
+        func = set_clip_still;
+        break;
+
+      default:
+        break;
+    }
+
+  return func;
+}
+
+static int32_t get_flip(uint8_t *flip, uint8_t direction)
+{
+  DEBUGASSERT(flip);
+
+  return (*flip & direction) ? 1 : 0;
+}
+
+static int get_hflip_video(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = get_flip(&g_isx019_private.flip_video, H_REVERSE);
+  return OK;
+}
+
+static int get_vflip_video(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = get_flip(&g_isx019_private.flip_video, V_REVERSE);
+  return OK;
+}
+
+static int get_hflip_still(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = get_flip(&g_isx019_private.flip_still, H_REVERSE);
+  return OK;
+}
+
+static int get_vflip_still(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = get_flip(&g_isx019_private.flip_still, V_REVERSE);
+  return OK;
+}
+
+static int get_colorfx(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = g_isx019_private.colorfx;
+  return OK;
+}
+
+static int get_ae(FAR imgsensor_value_t *val)
+{
+  uint32_t regval;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read(CAT_CATAE, SHT_PRIMODE, (FAR uint8_t *)&regval, 4);
+
+  val->value32 = (regval == 0) ? IMGSENSOR_EXPOSURE_AUTO
+                               : IMGSENSOR_EXPOSURE_MANUAL;
+
+  return OK;
+}
+
+static int get_exptime(FAR imgsensor_value_t *val)
+{
+  uint32_t regval;
+
+  isx019_i2c_read(CAT_AESOUT, SHT_TIME, (FAR uint8_t *)&regval, 4);
+
+  /* Round up to the nearest 100usec for eliminating errors in reverting to
+   * application value because this driver converts application value to
+   * value that takes into account the clock ratio and unit difference.
+   */
+
+  val->value32 = ((regval / g_isx019_private.clock_ratio) + 99) / 100;
+
+  return OK;
+}
+
+static int get_wbmode(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = g_isx019_private.wb_mode;
+
+  return OK;
+}
+
+static int get_meter(FAR imgsensor_value_t *val)
+{
+  uint8_t regval;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read(CAT_AUTOCTRL, AEWEIGHTMODE, &regval, 1);
+
+  switch (regval)
+    {
+      case AEWEIGHT_AVERAGE:
+        val->value32 = IMGSENSOR_EXPOSURE_METERING_AVERAGE;
+        break;
+
+      case AEWEIGHT_CENTER:
+        val->value32 = IMGSENSOR_EXPOSURE_METERING_CENTER_WEIGHTED;
+        break;
+
+      case AEWEIGHT_SPOT:
+        val->value32 = IMGSENSOR_EXPOSURE_METERING_SPOT;
+        break;
+
+      default: /* AEWEIGHT_MATRIX */
+        val->value32 = IMGSENSOR_EXPOSURE_METERING_MATRIX;
+        break;
+    }
+
+  return OK;
+}
+
+static int get_3alock(FAR imgsensor_value_t *val)
+{
+  uint8_t regval;
+  uint8_t awb;
+  uint8_t ae;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read(CAT_CATAWB, AWBMODE, &regval, 1);
+  awb = (regval == AWBMODE_AUTO) ? 0 : IMGSENSOR_LOCK_WHITE_BALANCE;
+
+  isx019_i2c_read(CAT_CATAE,  AEMODE,  &regval,  1);
+  ae = (regval == AEMODE_AUTO) ? 0 : IMGSENSOR_LOCK_EXPOSURE;
+
+  val->value32 = awb | ae;
+
+  return OK;
+}
+
+static int get_3aparameter(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (val->p_u8 == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read
+  (CAT_AWBSOUT, CONT_R,     &val->p_u8[OFFSET_3APARAMETER_AWB_R], 2);
+  isx019_i2c_read
+  (CAT_AWBSOUT, CONT_B,     &val->p_u8[OFFSET_3APARAMETER_AWB_B], 2);
+  isx019_i2c_read
+  (CAT_AESOUT,  SHT_TIME,   &val->p_u8[OFFSET_3APARAMETER_AE_SHTTIME], 4);
+  isx019_i2c_read
+  (CAT_AECOM,   GAIN_LEVEL, &val->p_u8[OFFSET_3APARAMETER_AE_GAIN], 1);
+
+  return OK;
+}
+
+static int get_3astatus(FAR imgsensor_value_t *val)
+{
+  uint8_t regval;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read(CAT_AWBSOUT, AWBSTS, &regval, 1);
+
+  switch (regval)
+    {
+      case AWBSTS_STABLE:
+        val->value32 = IMGSENSOR_3A_STATUS_STABLE;
+        break;
+
+      case AWBSTS_AEWAIT:
+        val->value32 = IMGSENSOR_3A_STATUS_AE_OPERATING;
+        break;
+
+      default:
+        val->value32 = IMGSENSOR_3A_STATUS_AE_OPERATING |
+                       IMGSENSOR_3A_STATUS_AWB_OPERATING;
+    }
+
+  return OK;
+}
+
+static double calc_iso(double gain)
+{
+  int k;
+  double z;
+  double r;
+
+  /* ISO sensitivity = 10^((gain - 1) / 10)
+   * So, replace z = (gain - 1) / 10 and
+   * calculate 10^z.
+   */
+
+  /*  Devide z into integer and other parts.
+   *  z =  log10(E) (k * ln2 + r)
+   *  (k : integer, r < 0.5 * ln2)
+   *
+   * Then, 10^z = (2^k) * e^r (r < 0.5 * ln2)
+   */
+
+  z = (gain - 1) / 10;
+
+  k = z * M_LN10 / M_LN2;
+  r = z * M_LN10 - k * M_LN2;
+
+  return (1 << k) * exp(r);
+}
+
+static int get_iso(FAR imgsensor_value_t *val)
+{
+  uint8_t buf = 0;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (g_isx019_private.iso == 0)
+    {
+      /* iso = 0 means auto adjustment mode.
+       * In such a case, get gain from auto adjustment value register,
+       * which has the unit 0.3dB, and convert the gain to ISO.
+       */
+
+      isx019_i2c_read(CAT_AECOM, GAIN_LEVEL, &buf, 1);
+      val->value32 = calc_iso((double)buf * 0.3) * USEC_PER_MSEC;
+    }
+  else
+    {
+      val->value32 = g_isx019_private.iso;
+    }
+
+  return OK;
+}
+
+static int get_iso_auto(FAR imgsensor_value_t *val)
+{
+  uint16_t gain;
+
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  isx019_i2c_read(CAT_CATAE, GAIN_PRIMODE, (FAR uint8_t *)&gain, 2);
+
+  val->value32 = (gain == 0) ? IMGSENSOR_ISO_SENSITIVITY_AUTO
+                             : IMGSENSOR_ISO_SENSITIVITY_MANUAL;
+  return OK;
+}
+
+static int get_gamma(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = g_isx019_private.gamma;
+
+  return OK;
+}
+
+static int get_jpg_quality(FAR imgsensor_value_t *val)
+{
+  if (val == NULL)
+    {
+      return -EINVAL;
+    }
+
+  val->value32 = g_isx019_private.jpg_quality;
+  return OK;
+}
+
+static getvalue_t get_value_func(uint32_t id)
+{
+  getvalue_t func = NULL;
+
+  switch (id)
+    {
+      case IMGSENSOR_ID_GAMMA:
+        func = get_gamma;
+        break;
+
+      case IMGSENSOR_ID_HFLIP_VIDEO:
+        func = get_hflip_video;
+        break;
+
+      case IMGSENSOR_ID_VFLIP_VIDEO:
+        func = get_vflip_video;
+        break;
+
+      case IMGSENSOR_ID_HFLIP_STILL:
+        func = get_hflip_still;
+        break;
+
+      case IMGSENSOR_ID_VFLIP_STILL:
+        func = get_vflip_still;
+        break;
+
+      case IMGSENSOR_ID_COLORFX:
+        func = get_colorfx;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_AUTO:
+        func = get_ae;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_ABSOLUTE:
+        func = get_exptime;
+        break;
+
+      case IMGSENSOR_ID_AUTO_N_PRESET_WB:
+        func = get_wbmode;
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY:
+        func = get_iso;
+        break;
+
+      case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO:
+        func = get_iso_auto;
+        break;
+
+      case IMGSENSOR_ID_EXPOSURE_METERING:
+        func = get_meter;
+        break;
+
+      case IMGSENSOR_ID_3A_LOCK:
+        func = get_3alock;
+        break;
+
+      case IMGSENSOR_ID_3A_PARAMETER:
+        func = get_3aparameter;
+        break;
+
+      case IMGSENSOR_ID_3A_STATUS:
+        func = get_3astatus;
+        break;
+
+      case IMGSENSOR_ID_JPEG_QUALITY:
+        func = get_jpg_quality;
+        break;
+
+      default:
+        break;
+    }
+
+  return func;
+}
+
+static int isx019_get_value(uint32_t id,
+                            uint32_t size,
+                            FAR imgsensor_value_t *val)
+{
+  int ret = -EINVAL;
+  isx019_reginfo_t reg;
+  convert_t cvrt;
+  getvalue_t get;
+  int32_t val32;
+
+  DEBUGASSERT(val);
+
+  cvrt = get_reginfo(id, false, &reg);
+  if (cvrt)
+    {
+      ret = isx019_i2c_read
+            (reg.category, reg.offset, (FAR uint8_t *)&val32, reg.size);
+      val->value32 = cvrt(val32);
+    }
+  else
+    {
+      get = get_value_func(id);
+      if (get)
+        {
+          ret = get(val);
+        }
+    }
+
+  return ret;
+}
+
+static int validate_range(int32_t val,
+                          FAR imgsensor_capability_range_t *range)
+{
+  int ret = OK;
+
+  if (!VALIDATE_RANGE(val, range->minimum, range->maximum, range->step))
+    {
+      ret = -EINVAL;
+    }
+
+  return ret;
+}
+
+static int validate_discrete(int32_t val,
+                             FAR imgsensor_capability_discrete_t *disc)
+{
+  int ret = -EINVAL;
+  int i;
+
+  for (i = 0; i < disc->nr_values; i++)
+    {
+      if (val == disc->values[i])
+        {
+          ret = OK;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+static int validate_elems_u8(FAR uint8_t *val, uint32_t sz,
+                             FAR imgsensor_capability_elems_t *elems)
+{
+  int ret = OK;
+  int i;
+
+  if (sz != elems->nr_elems)
+    {
+      return -EINVAL;
+    }
+
+  for (i = 0; i < elems->nr_elems; i++)
+    {
+      if (!VALIDATE_RANGE
+           (val[i], elems->minimum, elems->maximum, elems->step))
+        {
+          ret = -EINVAL;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+static int validate_elems_u16 (FAR uint16_t *val, uint32_t sz,
+                               FAR imgsensor_capability_elems_t *elems)
+{
+  int ret = OK;
+  int i;
+
+  if (sz != elems->nr_elems * sizeof(uint16_t))
+    {
+      return -EINVAL;
+    }
+
+  for (i = 0; i < elems->nr_elems; i++)
+    {
+      if (!VALIDATE_RANGE
+           (val[i], elems->minimum, elems->maximum, elems->step))
+        {
+          ret = -EINVAL;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+static int validate_elems_u32 (FAR uint32_t *val, uint32_t sz,
+                               FAR imgsensor_capability_elems_t *elems)
+{
+  int ret = OK;
+  int i;
+
+  if (sz != elems->nr_elems * sizeof(uint32_t))
+    {
+      return -EINVAL;
+    }
+
+  for (i = 0; i < elems->nr_elems; i++)
+    {
+      if (!VALIDATE_RANGE
+           (val[i], elems->minimum, elems->maximum, elems->step))
+        {
+          ret = -EINVAL;
+          break;
+        }
+    }
+
+  return ret;
+}
+
+static int validate_value(uint32_t id,
+                          uint32_t size,
+                          imgsensor_value_t val)
+{
+  int ret;
+  imgsensor_supported_value_t sup;
+
+  ret = isx019_get_supported_value(id, &sup);
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  switch (sup.type)
+    {
+      case IMGSENSOR_CTRL_TYPE_INTEGER_MENU:
+        ret = validate_discrete(val.value32, &sup.u.discrete);
+        break;
+
+      case IMGSENSOR_CTRL_TYPE_U8:
+        ret = validate_elems_u8(val.p_u8, size, &sup.u.elems);
+        break;
+
+      case IMGSENSOR_CTRL_TYPE_U16:
+        ret = validate_elems_u16(val.p_u16, size, &sup.u.elems);
+        break;
+
+      case IMGSENSOR_CTRL_TYPE_U32:
+        ret = validate_elems_u32(val.p_u32, size, &sup.u.elems);
+        break;
+
+      default:
+        ret = validate_range(val.value32, &sup.u.range);
+        break;
+    }
+
+  return ret;
+}
+
+static int isx019_set_value(uint32_t id,
+                            uint32_t size,
+                            imgsensor_value_t val)
+{
+  int ret = -EINVAL;
+  isx019_reginfo_t reg;
+  convert_t cvrt;
+  setvalue_t set;
+  int32_t val32;
+
+  ret = validate_value(id, size, val);
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  cvrt = get_reginfo(id, true, &reg);
+  if (cvrt)
+    {
+      val32 = cvrt(val.value32);
+      ret = isx019_i2c_write
+            (reg.category, reg.offset, (FAR uint8_t *)&val32, reg.size);
+    }
+  else
+    {
+      set = set_value_func(id);
+      if (set)
+        {
+          ret = set(val);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int isx019_initialize(void)
+{
+  imgsensor_register(&g_isx019_ops);
+  nxsem_init(&g_isx019_private.i2c_lock, 0, 1);
+  nxsem_init(&g_isx019_private.fpga_lock, 0, 1);
+  return OK;
+}
+
+int isx019_uninitialize(void)
+{
+  nxsem_destroy(&g_isx019_private.i2c_lock);
+  nxsem_destroy(&g_isx019_private.fpga_lock);
+  return OK;
+}
+
+#ifdef CONFIG_VIDEO_ISX019_REGDEBUG
+int isx019_read_register(uint8_t cat,
+                         uint16_t addr,
+                         FAR uint8_t *buf,
+                         uint8_t size)
+{
+  int ret;
+
+  if (cat == 0xff)
+    {
+      ret = fpga_i2c_read((uint8_t)addr, buf, size);
+    }
+  else
+    {
+      ret = isx019_i2c_read(cat, addr, buf, size);
+    }
+
+  return ret;
+}
+#endif
diff --git a/drivers/video/isx019_range.h b/drivers/video/isx019_range.h
new file mode 100644
index 0000000000..4a3d6d143f
--- /dev/null
+++ b/drivers/video/isx019_range.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+ * drivers/video/isx019_range.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 __DRIVERS_VIDEO_ISX019_RANGE_H
+#define __DRIVERS_VIDEO_ISX019_RANGE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <limits.h>
+#include <nuttx/video/imgsensor.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MIN_BRIGHTNESS        (-128)
+#define MAX_BRIGHTNESS        (127)
+#define STEP_BRIGHTNESS       (1)
+
+#define MIN_CONTRAST          (0)
+#define MAX_CONTRAST          (255)
+#define STEP_CONTRAST         (1)
+
+#define MIN_SATURATION        (0)
+#define MAX_SATURATION        (255)
+#define STEP_SATURATION       (1)
+
+#define MIN_HUE               (-128)
+#define MAX_HUE               (127)
+#define STEP_HUE              (1)
+
+#define MIN_GAMMA             (0)
+#define MAX_GAMMA             (INT_MAX)
+#define STEP_GAMMA            (1)
+
+#define MIN_AWB               (0)
+#define MAX_AWB               (1)
+#define STEP_AWB              (1)
+
+#define MIN_EXPOSURE          (-6)
+#define MAX_EXPOSURE          (6)
+#define STEP_EXPOSURE         (1)
+
+#define MIN_HFLIP             (0)
+#define MAX_HFLIP             (1)
+#define STEP_HFLIP            (1)
+
+#define MIN_VFLIP        (0)
+#define MAX_VFLIP        (1)
+#define STEP_VFLIP       (1)
+
+#define MIN_SHARPNESS        (0)
+#define MAX_SHARPNESS        (255)
+#define STEP_SHARPNESS       (1)
+
+#define MIN_AE        (0)
+#define MAX_AE        (1)
+#define STEP_AE       (1)
+
+#define MIN_EXPOSURETIME        (1)
+#define MAX_EXPOSURETIME        (102000)
+#define STEP_EXPOSURETIME       (1)
+
+#define MIN_WBMODE        (0)
+#define MAX_WBMODE        (7)
+#define STEP_WBMODE       (1)
+
+#define MIN_HDR           (0)
+#define MAX_HDR           (2)
+#define STEP_HDR          (1)
+
+#define MIN_METER        (0)
+#define MAX_METER        (3)
+#define STEP_METER       (1)
+
+#define MIN_PAN        (-32)
+#define MAX_PAN        (32)
+#define STEP_PAN       (1)
+
+#define MIN_TILT        (-32)
+#define MAX_TILT        (32)
+#define STEP_TILT       (1)
+
+#define MIN_ISO        (1)
+#define MAX_ISO        (INT_MAX)
+#define STEP_ISO       (1)
+
+#define MIN_AUTOISO        (0)
+#define MAX_AUTOISO        (1)
+#define STEP_AUTOISO       (1)
+
+#define MIN_3ALOCK        (0)
+#define MAX_3ALOCK        (3)
+#define STEP_3ALOCK       (1)
+
+#define NRELEM_3APARAM     (9)
+#define MIN_3APARAM        (0)
+#define MAX_3APARAM        (255)
+#define STEP_3APARAM       (1)
+
+#define MIN_3ASTATUS        (0)
+#define MAX_3ASTATUS        (3)
+#define STEP_3ASTATUS       (1)
+
+#define MIN_JPGQUALITY        (1)
+#define MAX_JPGQUALITY        (100)
+#define STEP_JPGQUALITY       (1)
+
+#define NRELEM_CLIP           IMGSENSOR_CLIP_NELEM
+#define MIN_CLIP              (0)
+#define MAX_CLIP              (1280)
+#define STEP_CLIP             (8)
+
+#endif /* __DRIVERS_VIDEO_ISX019_RANGE_H */
diff --git a/drivers/video/isx019_reg.h b/drivers/video/isx019_reg.h
new file mode 100644
index 0000000000..71aead7cbd
--- /dev/null
+++ b/drivers/video/isx019_reg.h
@@ -0,0 +1,408 @@
+/****************************************************************************
+ * drivers/video/isx019_reg.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 __DRIVERS_VIDEO_ISX019_REG_H
+#define __DRIVERS_VIDEO_ISX019_REG_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* FPGA I2C setting */
+
+#define FPGA_I2C_SLVADDR           (0x1b)
+#define FPGA_I2C_SLVADDR_LEN       (7)
+#define FPGA_I2C_REGSIZE_MAX       (1)
+#define FPGA_I2C_REGADDR_LEN       (1)
+#define FPGA_I2C_FREQUENCY         (100000) /* Standard mode : 100kHz */
+
+/* FPGA I2C offset */
+
+#define FPGA_I2C_OFFSET_ADDR       (0)
+#define FPGA_I2C_OFFSET_WRITEDATA  (1)
+#define FPGA_I2C_OFFSET_READDATA   (0)
+
+/* FPGA register address */
+
+#define FPGA_RESET                     (0x00)
+#define FPGA_DATA_OUTPUT               (0x01)
+#define FPGA_FORMAT_AND_SCALE          (0x02)
+#define FPGA_FPS_AND_THUMBNAIL         (0x03)
+#define FPGA_CLIP_SIZE                 (0x04)
+#define FPGA_CLIP_TOP                  (0x05)
+#define FPGA_CLIP_LEFT                 (0x06)
+#define FPGA_DQT_ADDRESS               (0x07)
+#define FPGA_DQT_SELECT                (0x08)
+#define FPGA_DQT_DATA                  (0x09)
+#define FPGA_DQT_CALC_ADDRESS          (0x0A)
+#define FPGA_DQT_CALC_SELECT           (0x0B)
+#define FPGA_DQT_CALC_DATA             (0x0C)
+#define FPGA_ACTIVATE                  (0x0D)
+#define FPGA_PIN_OUTPUT_SELECT         (0x20)
+#define FPGA_PIN_STATUS                (0x21)
+#define FPGA_VERSION                   (0x30)
+
+/* value for setting to FPGA register */
+
+#define FPGA_RESET_ENABLE  (0x00)
+#define FPGA_RESET_RELEASE (0x01)
+
+#define FPGA_DATA_OUTPUT_START (0x01)
+#define FPGA_DATA_OUTPUT_STOP  (0x00)
+
+#define FPGA_FORMAT_RGB       (0x00)
+#define FPGA_FORMAT_YUV       (0x01)
+#define FPGA_FORMAT_JPEG      (0x02)
+#define FPGA_FORMAT_THUMBNAIL (0x03)
+
+#define FPGA_SCALE_1280_960   (0<<4)
+#define FPGA_SCALE_640_480    (1<<4)
+#define FPGA_SCALE_320_240    (2<<4)
+#define FPGA_SCALE_160_120    (3<<4)
+
+#define FPGA_FPS_BITS (0x03)
+#define FPGA_FPS_1_1  (0x00)
+#define FPGA_FPS_1_2  (0x01)
+#define FPGA_FPS_1_3  (0x02)
+#define FPGA_FPS_1_4  (0x03)
+
+#define FPGA_THUMBNAIL_SCALE_1_1 (0<<4)
+#define FPGA_THUMBNAIL_SCALE_1_2 (1<<4)
+#define FPGA_THUMBNAIL_SCALE_1_4 (2<<4)
+#define FPGA_THUMBNAIL_SCALE_1_8 (3<<4)
+
+#define FPGA_CLIP_NON         (0x00)
+#define FPGA_CLIP_1280_720    (0x01)
+#define FPGA_CLIP_640_360     (0x02)
+#define FPGA_CLIP_UNIT        (8)
+
+#define FPGA_DQT_READ (0<<6)
+#define FPGA_DQT_WRITE (1<<6)
+
+#define FPGA_DQT_CURRENT (0<<7)
+#define FPGA_DQT_BUFFER  (1<<7)
+
+#define FPGA_DQT_LUMA   (0x00)
+#define FPGA_DQT_CHROMA (0x01)
+
+#define FPGA_ACTIVATE_REQUEST (0x01)
+
+#define FPGA_PIN_OUTPUT_EXBUSY (0x00)
+#define FPGA_PIN_OUTPUT_ERROR  (0x01)
+
+#define FPGA_PIN_STATUS_EXBUSY (1<<0)
+#define FPGA_PIN_STATUS_ERROR  (1<<4)
+
+/* ISX019 I2C setting */
+
+#define ISX019_I2C_SLVADDR         (0x1a)
+#define ISX019_I2C_SLVADDR_LEN     (7)
+#define ISX019_I2C_REGSIZE_MAX     (4)
+#define ISX019_I2C_REGADDR_LEN     (4)
+#define ISX019_I2C_FREQUENCY       (100000) /* Standard mode : 100kHz */
+
+/* Offset of ISX019 I2C command format */
+
+#define ISX019_I2C_OFFSET_TOTALLEN   (0)
+#define ISX019_I2C_OFFSET_CMDNUM (1)
+#define ISX019_I2C_OFFSET_CMDLEN (2)
+#define ISX019_I2C_OFFSET_CMD    (3)
+#define ISX019_I2C_OFFSET_CATEGORY   (4)
+#define ISX019_I2C_OFFSET_ADDRESS_H  (5)
+#define ISX019_I2C_OFFSET_ADDRESS_L  (6)
+#define ISX019_I2C_OFFSET_WRITEDATA  (7)
+#define ISX019_I2C_OFFSET_READSIZE   (7)
+#define ISX019_I2C_OFFSET_FLASHCODE1 (4)
+#define ISX019_I2C_OFFSET_FLASHCODE2 (5)
+#define ISX019_I2C_OFFSET_FLASHCODE3 (6)
+#define ISX019_I2C_OFFSET_FLASHCODE4 (7)
+#define ISX019_I2C_OFFSET_STS        (3)
+#define ISX019_I2C_OFFSET_READDATA   (4)
+
+/* Command code of ISX019 I2C command format */
+
+#define ISX019_I2C_CMD_FLASHLOCK  (0x00)
+#define ISX019_I2C_CMD_READ       (0x01)
+#define ISX019_I2C_CMD_WRITE      (0x02)
+#define ISX019_I2C_CMD_FLASHWRITE (0x05)
+
+/* Command length of ISX019 I2C command format */
+
+#define ISX019_I2C_TOTALLEN(s)       (3 + (s))
+
+#define ISX019_I2C_WRREQ_LEN(s)      (5 + (s))
+#define ISX019_I2C_WRRES_LEN         (2)
+#define ISX019_I2C_WRREQ_TOTALLEN(s) ISX019_I2C_TOTALLEN(ISX019_I2C_WRREQ_LEN(s))
+#define ISX019_I2C_WRRES_TOTALLEN    ISX019_I2C_TOTALLEN(ISX019_I2C_WRRES_LEN)
+
+#define ISX019_I2C_RDREQ_LEN         (6)
+#define ISX019_I2C_RDRES_LEN(s)      (2 + (s))
+#define ISX019_I2C_RDREQ_TOTALLEN    ISX019_I2C_TOTALLEN(ISX019_I2C_RDREQ_LEN)
+#define ISX019_I2C_RDRES_TOTALLEN(s) ISX019_I2C_TOTALLEN(ISX019_I2C_RDRES_LEN(s))
+
+#define ISX019_I2C_FLOCKREQ_LEN      (6)
+#define ISX019_I2C_FLOCKRES_LEN      (2)
+#define ISX019_I2C_FLOCKREQ_TOTALLEN ISX019_I2C_TOTALLEN(ISX019_I2C_FLOCKREQ_LEN)
+#define ISX019_I2C_FLOCKRES_TOTALLEN ISX019_I2C_TOTALLEN(ISX019_I2C_FLOCKRES_LEN)
+
+#define ISX019_I2C_FWRREQ_LEN        (2)
+#define ISX019_I2C_FWRRES_LEN        (2)
+#define ISX019_I2C_FWRREQ_TOTALLEN   ISX019_I2C_TOTALLEN(ISX019_I2C_FWRREQ_LEN)
+#define ISX019_I2C_FWRRES_TOTALLEN   ISX019_I2C_TOTALLEN(ISX019_I2C_FWRRES_LEN)
+
+/* Constant value of codes for flash lock */
+
+#define ISX019_I2C_FLASHCODE1   (0x57)
+#define ISX019_I2C_FLASHCODE2   (0x52)
+#define ISX019_I2C_FLASHLOCK1   (0x44)
+#define ISX019_I2C_FLASHLOCK2   (0x53)
+#define ISX019_I2C_FLASHUNLOCK1 (0x45)
+#define ISX019_I2C_FLASHUNLOCK2 (0x4e)
+
+/* Status code of I2C command format */
+
+#define ISX019_I2C_STS_OK         (0x01)
+#define ISX019_I2C_STS_ERR_CMD    (0xf1)
+#define ISX019_I2C_STS_ERR_CAT    (0xf2)
+#define ISX019_I2C_STS_ERR_ADDR   (0xf3)
+#define ISX019_I2C_STS_ERR_ACCESS (0xf4)
+#define ISX019_I2C_STS_ERR_BYTE   (0xf7)
+#define ISX019_I2C_STS_ERR_FLASH  (0xfa)
+
+/* Category of ISX019 register */
+
+#define CAT_VERSION       (0x00)
+#define CAT_CONFIG        (0x01)
+#define CAT_SYSCOM        (0x06)
+#define CAT_OTP           (0x08)
+#define CAT_AUTOCTRL      (0x0c)
+#define CAT_SMCFG         (0x0f)
+#define CAT_CATAE         (0x13)
+#define CAT_AEDGRM        (0x14)
+#define CAT_AEWD          (0x15)
+#define CAT_AECOM         (0x18)
+#define CAT_AESOUT        (0x19)
+#define CAT_CATAWB        (0x21)
+#define CAT_AWB_USERTYPE  (0x26)
+#define CAT_AUTOCOM       (0x2c)
+#define CAT_AWBSOUT       (0x31)
+#define CAT_PICTTUNE      (0x34)
+#define CAT_PICTGAMMA     (0x41)
+
+/* Offset of ISX019 register */
+
+/* For CAT_VERSION */
+
+#define ROM_VERSION       (0x0000)
+
+/* For CAT_CONFIG */
+
+#define MODE_SENSSEL      (0x0000)
+#define MODE_POSTSEL      (0x0001)
+#define MODE_SENSPOST_SEL (0x0002)
+#define MODE_IOSEL        (0x0003)
+#define REVERSE           (0x0008)
+
+/* For CAT_SYSCOM */
+
+#define DEVSTS            (0x0001)
+
+/* For CAT_OTP */
+
+#define CHIP_ID           (0x0000)
+#define CHIP_ID_LEN       (11)
+
+/* For CAT_AUTOCTRL */
+
+#define AEWEIGHTMODE      (0x0000)
+
+/* For CAT_CATAE */
+
+#define AEMODE            (0x0000)
+#define SHT_PRIMODE       (0x0008)
+#define GAIN_PRIMODE      (0x000c)
+
+/* For CAT_AEDGRM */
+
+#define SHTCTRLVAL1       (0x0008)
+#define SHTCTRLVAL2       (0x0010)
+#define SHTCTRLVAL3       (0x0018)
+#define SHTCTRLVAL4       (0x0020)
+#define SHTCTRLVAL5       (0x0028)
+#define MAXFRMEXP         (0x007b)
+#define EVSEL             (0x009c)
+
+/* For CAT_AEWD */
+
+#define AEWDMODE          (0x0000)
+#define AEWEIGHTMODE_WD   (0x0001)
+
+/* For CAT_AECOM */
+
+#define GAIN_LEVEL        (0x0036)
+
+/* For CAT_AESOUT */
+
+#define SHT_TIME          (0x01cc)
+#define V_TIME            (0x01d0)
+
+/* For CAT_CATAWB */
+
+#define AWBMODE           (0x0000)
+#define AWBUSER_NO        (0x000a)
+
+/* For CAT_AWB_USERTYPE */
+
+#define USER0_R           (0x0000)
+#define USER0_B           (0x0002)
+#define USER1_R           (0x000c)
+#define USER1_B           (0x000e)
+#define USER2_R           (0x0018)
+#define USER2_B           (0x001a)
+#define USER3_R           (0x0024)
+#define USER3_B           (0x0026)
+#define USER4_R           (0x0030)
+#define USER4_B           (0x0032)
+
+/* For CAT_AUTOCOM */
+
+#define CONT_R            (0x0006)
+#define CONT_B            (0x0008)
+
+/* For CAT_AWBSOUT */
+
+#define AWBSTS            (0x0000)
+
+/* For CAT_PICTTUNE */
+
+#define UISHARPNESS       (0x0000)
+#define UICONTRAST        (0x0001)
+#define UIBRIGHTNESS      (0x0002)
+#define UIHUE             (0x0004)
+#define UISATURATION      (0x0005)
+
+/* For CAT_PICTGAMMA */
+
+#define GAM_KNOT_C0       (0x0000)
+#define GAM_KNOT_C8       (0x0010)
+#define GAM_KNOT_C9       (0x0012)
+#define GAM_KNOT_C10      (0x0014)
+#define GAM_KNOT_C11      (0x0016)
+#define NR_GAM_KNOT_LOWINPUT (9)
+#define NR_GAM_KNOT_HIGHINPUT (16)
+
+#define GAM_LOWINPUT_INTERVAL (double)(32.0 / 4096.0)
+#define GAM_HIGHINPUT_INTERVAL (double)(256.0 / 4096.0)
+#define GAM_OUTPUT_SCALE (255)
+
+/* Definition for ISX019 register setting value */
+
+/* For drive mode */
+
+#define NOT_STREAM_SENS     (0)
+#define NOT_STREAM_POST     (0)
+#define NOT_STREAM_SENSPOST (0)
+#define NOT_STREAM_IO       (0)
+
+#define NORM_30FPS_SENS     (2)
+#define NORM_30FPS_POST     (2)
+#define NORM_30FPS_SENSPOST (2)
+#define NORM_30FPS_IO       (2)
+
+#define DOL2_30FPS_SENS     (6)
+#define DOL2_30FPS_POST     (2)
+#define DOL2_30FPS_SENSPOST (24)
+#define DOL2_30FPS_IO       (2)
+
+#define DOL3_30FPS_SENS     (44)
+#define DOL3_30FPS_POST     (125)
+#define DOL3_30FPS_SENSPOST (160)
+#define DOL3_30FPS_IO       (2)
+
+#define NORM_25FPS_SENS     (3)
+#define NORM_25FPS_POST     (8)
+#define NORM_25FPS_SENSPOST (8)
+#define NORM_25FPS_IO       (2)
+
+#define DOL2_25FPS_SENS     (7)
+#define DOL2_25FPS_POST     (8)
+#define DOL2_25FPS_SENSPOST (30)
+#define DOL2_25FPS_IO       (2)
+
+#define DOL3_25FPS_SENS     (45)
+#define DOL3_25FPS_POST     (131)
+#define DOL3_25FPS_SENSPOST (166)
+#define DOL3_25FPS_IO       (2)
+
+/* For REVERSE register(H_REVERSE and V_REVERSE) */
+
+#define H_REVERSE           (0x01)
+#define V_REVERSE           (0x02)
+
+/* For AEWEIGHTMODE */
+
+#define AEWEIGHT_AVERAGE    (0x00)
+#define AEWEIGHT_CENTER     (0x01)
+#define AEWEIGHT_SPOT       (0x02)
+#define AEWEIGHT_MATRIX     (0x03)
+
+/* For AEWEIGHTMODE(HDR) */
+
+#define AEWEIGHTHDR_AVERAGE (0x00)
+#define AEWEIGHTHDR_CENTER  (0x05)
+#define AEWEIGHTHDR_SPOT    (0x0a)
+#define AEWEIGHTHDR_MATRIX  (0x0f)
+
+/* For AWBMODE */
+
+#define AWBMODE_AUTO        (0x00)
+#define AWBMODE_HOLD        (0x02)
+#define AWBMODE_MANUAL      (0x04)
+
+/* For AEMODE */
+
+#define AEMODE_AUTO         (0x00)
+#define AEMODE_HOLD         (0x01)
+
+/* For AEWDMODE */
+
+#define AEWDMODE_AUTO       (0x00)
+#define AEWDMODE_HDR        (0x01)
+#define AEWDMODE_NORMAL     (0x02)
+
+/* For AWBSTS */
+
+#define AWBSTS_STABLE       (0x02)
+#define AWBSTS_AEWAIT       (0x06)
+
+/* For USERX_R, USERX_B */
+
+#define RED_INCANDESCENT    (0x115f)
+#define BLUE_INCANDESCENT   (0x0e40)
+#define RED_FLUORESCENT     (0x0daf)
+#define BLUE_FLUORESCENT    (0x1250)
+#define RED_DAYLIGHT        (0x0b81)
+#define BLUE_DAYLIGHT       (0x1832)
+#define RED_CLOUDY          (0x0a4f)
+#define BLUE_CLOUDY         (0x1bc5)
+#define RED_SHADE           (0x0a4f)
+#define BLUE_SHADE          (0x1bc5)
+
+#endif /* __DRIVERS_VIDEO_ISX019_REG_H */
diff --git a/include/nuttx/video/isx019.h b/include/nuttx/video/isx019.h
new file mode 100644
index 0000000000..4116475a12
--- /dev/null
+++ b/include/nuttx/video/isx019.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * include/nuttx/video/isx019.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_ISX019_H
+#define __INCLUDE_NUTTX_VIDEO_ISX019_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int isx019_initialize(void);
+int isx019_uninitialize(void);
+#ifdef CONFIG_VIDEO_ISX019_REGDEBUG
+int isx019_read_register(uint8_t cat,
+                         uint16_t addr,
+                         FAR uint8_t *buf,
+                         uint8_t size);
+#endif
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_VIDEO_ISX019_H */