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:40 UTC

[incubator-nuttx] branch master updated (c7823f7914 -> 3366f1fb35)

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

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


    from c7823f7914 arch/xtensa/xtensa_sigdeliver.c: Remove old code that was preventing jumping back to the assembly signal trampoline and getting into its infinite loop.
     new 72f399e052 drivers: video: add isx019 camera sensor
     new 3366f1fb35 boards: spresense: defconfig: enable ISX019 camera driver

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 boards/arm/cxd56xx/common/src/Make.defs            |    4 +
 .../common/src/{cxd56_isx012.c => cxd56_isx019.c}  |  101 +-
 .../arm/cxd56xx/spresense/configs/camera/defconfig |    1 +
 .../spresense/configs/example_camera/defconfig     |    1 +
 boards/arm/cxd56xx/spresense/include/board.h       |    7 +-
 .../arm/cxd56xx/spresense/include/cxd56_isx019.h   |   77 +-
 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 +++
 .../nuttx/{timers/arch_timer.h => video/isx019.h}  |   31 +-
 13 files changed, 3955 insertions(+), 108 deletions(-)
 copy boards/arm/cxd56xx/common/src/{cxd56_isx012.c => cxd56_isx019.c} (66%)
 copy arch/arm/src/samv7/sam_eefc.h => boards/arm/cxd56xx/spresense/include/cxd56_isx019.h (73%)
 create mode 100644 drivers/video/isx019.c
 create mode 100644 drivers/video/isx019_range.h
 create mode 100644 drivers/video/isx019_reg.h
 copy include/nuttx/{timers/arch_timer.h => video/isx019.h} (78%)


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

Posted by xi...@apache.org.
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 */


[incubator-nuttx] 02/02: boards: spresense: defconfig: enable ISX019 camera driver

Posted by xi...@apache.org.
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 3366f1fb3510a5eaca79eee2b6d831a9dbdee4c2
Author: Alin Jerpelea <al...@sony.com>
AuthorDate: Mon May 16 12:49:53 2022 +0000

    boards: spresense: defconfig: enable ISX019 camera driver
    
    Enable the second camera driver for Spresense board
    
    Signed-off-by: Alin Jerpelea <al...@sony.com>
---
 boards/arm/cxd56xx/spresense/configs/camera/defconfig         | 1 +
 boards/arm/cxd56xx/spresense/configs/example_camera/defconfig | 1 +
 2 files changed, 2 insertions(+)

diff --git a/boards/arm/cxd56xx/spresense/configs/camera/defconfig b/boards/arm/cxd56xx/spresense/configs/camera/defconfig
index 51c75f874b..1211f937f8 100644
--- a/boards/arm/cxd56xx/spresense/configs/camera/defconfig
+++ b/boards/arm/cxd56xx/spresense/configs/camera/defconfig
@@ -84,4 +84,5 @@ CONFIG_USBMSC=y
 CONFIG_USBMSC_EPBULKIN=1
 CONFIG_USBMSC_REMOVABLE=y
 CONFIG_VIDEO_ISX012=y
+CONFIG_VIDEO_ISX019=y
 CONFIG_VIDEO_STREAM=y
diff --git a/boards/arm/cxd56xx/spresense/configs/example_camera/defconfig b/boards/arm/cxd56xx/spresense/configs/example_camera/defconfig
index 800a5b05fe..9e07ae6901 100644
--- a/boards/arm/cxd56xx/spresense/configs/example_camera/defconfig
+++ b/boards/arm/cxd56xx/spresense/configs/example_camera/defconfig
@@ -95,4 +95,5 @@ CONFIG_USBMSC=y
 CONFIG_USBMSC_EPBULKIN=1
 CONFIG_USBMSC_REMOVABLE=y
 CONFIG_VIDEO_ISX012=y
+CONFIG_VIDEO_ISX019=y
 CONFIG_VIDEO_STREAM=y